Clouds
Home

Test Driven Development

Aspect Oriented Programming

Annotation Based Programming

Inversion Of Control - Part 1

Inversion Of Control - Part 2

Hibernate Interview Questions - Part 1

Hibernate Interview Questions - Part 2

Hibernate Interview Questions - Part 3

Spring Interview Questions

EJB 3.0 Interview Questions

Hibernate Interview Questions - Part 3


What is the difference between the session.get() method and the session.load() method ?

Both the session.get(..) and session.load() methods create a persistent object by loading the required object from the database. But if there was not such object in the database then the method session.load(..) throws an exception whereas session.get("") returns null.

What is the difference between the session.update() method and the session.lock() method ?

Both of these methods and saveOrUpdate() method are intended for reattaching a detached object. The session.lock() method simply reattaches the object to the session without checking or updating the database on the assumption that the database in sync with the detached object. It is the best practice to use either session.update(..) or session.saveOrUpdate(). Use session.lock() only if you are absolutely sure that the detached object is in sync with your detached object or if it does not matter because you will be overwriting all the columns that would have changed later on within the same transaction. Note: When you reattach detached objects you need to make sure that the dependent objects are reattached as well.

How would you reattach detached objects to a session when the same object has already been loaded into the session ?

You can use the session.merge() method call.

What are the general considerations or best practices for defining your Hibernate persistent classes ?

A Hibernate persistent class is a Plain Old Java Object (POJO), which has not interfaces to be implemented and no persistent superclass to be extended. The following are the requirements and best practices (all are not strict requirements) to consider for your Hibernate persistent classes:
  • You must have a default no-argument constructor for your persistent classes and there should be getXXX() (i.e accessor/getter) and setXXX( i.e. mutator/setter) methods for all your persistable instance variables.
  • You should implement the equals() and hashCode() methods based on your business key and it is important not to use the id field in your equals() and hashCode() definition if the id field is a surrogate key (i.e. Hibernate managed identifier). This is because the Hibernate only generates and sets the field when saving the object.

    Car car = session.load(Car.class, carId);
    car.getParts().add(new Part("Steering")); // adds a new entity with id = null (if Integer)
    // or id = 0 (if primitive int)
    car.getParts().add(new Part("Accelerator"));// has id = null too so overwrites last added
    // object in the Set.


    Alternatively if you use manually assigned id fields then you can use your id field in your equals() and hashCode() methods but you must make sure to set the id field prior to adding the object to the Set and it is quite difficult to guarantee this in most applications.

    Car car = session.load(Car.class, carId); Part part1 = new Part("Steering"); part1.setId(1001); car.getParts().add(part1)); //adds a new part entity with id=1001 Part part2 = new Part("Accelerator"); part1.setId(1002); car.getParts().add(part2); //has the id=1002 so adds a new part entity with id=1002

    So to avoid the problem of inadvertently not setting the id prior to adding the object to the Set, it is recommended to use the "semi" unique business key (i.e natural key) to implement equals() and hashCode() methods.
  • It is recommended to implement the Serializable interface. This is potentially useful if you want to migrate around a multi-processor cluster.
  • The persistent class should not be final because if it is final then lazy loading cannot be used by creating proxy objects.
  • Use XDoclet tags for generating your *.hbm.xml files or Annotations (JDK 1.5 onwards), which are less verbose than *.hbm.xml files.

    What is the difference between an object identity and a database identity ?

    Object

  • Identity: car1 == car2 (i.e. car1 & car 2 are pointing to the same object).
  • Equality: car1.equals(car2)

    Database

  • Identity: car1.getId().equals(car2.getId()) Where "id" is the primary key. If the ids are equal then both the car objects are referring to the same row in the database.

    What are the important considerations in writing your equals() & hashCode() methods ?

  • Use your semi unique business keys. For example you can use the following immutable fields (i.e. instance variables) as your business keys in your Car persistence class: name, model and createddate. You need to make sure that the fields used in your equals() method must be used in your hashCode() method as well.
  • If two objects are equal i.e. car1.equals(car2) returns "true" then car1.hashCode() == car2.hashCode() must return "true" as well. But if two objects are not equal i.e. car1.equals(car2) returns "false" then car1.hashCode() == car2.hashCode() can return either "true" or "false".
  • When referring to fields (i.e. instance variables) of the argument object, always use the accessor methods rather than directly using the instance variables because your supplied argument object might be a proxy object rather than the actual object. For example:

    public boolean equals(Object supplied) {
    if (this == supplied){
    return true; //same objects
    }
    if (other == null) {
    return false;
    }
    if(! (other instanceOf Car) ) {
    return false;
    }
    final Car car2 = (Car) supplied;
    if( this.name.equals (car2.getName()) &&
    this.model.equals (car2.getModel()) &&
    this.createdDate.equals (car2.getCreatedDate()) ) {
    return true;
    }
    else {
    return false;
    }
    }


    Need to make sure that all the three fields used in equals() method are used in hashCode() method as well.

    public int hashCode() {
    int hashCode = name.hashCode() * 11;
    hashCode = hashCode + model.hashCode() * 17;
    hashCode = hashCode + createdDate.hashCode() * 29;
    return hashCode;
    }


    What are the different types of persistent objects defined by Hibernate ?

  • Entity objects (aka first rank class): These objects have a persistent identity. Usually an identifier field (e.g. id), which is managed by Hibernate. These are typically central business objects like Investor, Customer, Order etc
  • Value objects (aka second rank class): These objects do not have an identity and only exist in a relationship to an entity object (aka first rank class). These are typically supporting objects such as Address, Name etc.

    What association or aggregation relationships can be mapped with Hibernate ?

    Database relationships are typically defined in terms of cardinality and direction. From an OO perspective, relationships are defined as association or aggregation. These relationships for objects can be viewed as either unidirectional (i.e. when one object knows about the other but not vice versa ) or bidirectional (i.e. both objects would know about each other). Cardinality can be defined as one-to-one (i.e. both on primary key as well as foreign key with a unique constraint), one-to-many, many-to-one and many-to-many. Hibernate managed entity objects can be mapped for all the above mentioned cardinality and direction.

    How would you map inheritance relationships in Hibernate ?

    There are number of ways Hibernate can handle inheritance among entity objects. The simplest is to use one table for the whole hierarchy. Only one table is required. With this design strategy, each row of the table can hold an object of any type from the entity object inheritance hierarchy. You should assign one column as the "discriminator" property of an entity class, which contains a value used to tell which actual type of object is stored in that particular row. Another strategy to map inheritance relationship is to use table per subclass strategy. Say you have a table called Vehicle and three subclass tables called Car, Van and Bus. These 3 subclass tables will have primary key associations to the superclass table Vehicle. So this relational model is actually a one-to-one association on a primary key. The entity object model will have a superclass representing the Vehicle table and 3 entity subclasses representing the Car, Van and Bus tables. Another strategy to map inheritance relationship is to use table per concrete class strategy. There will only be 3 tables (i.e. Car, Van and Bus) involved for the subclasses. The entity object model will have a superclass representing the Vehicle table and 3 entity subclasses representing the Car, Van and Bus tables. If your superclass Vehicle is abstract, then map it with abstract="true". Finally, you could also mix table per class hierarchy strategy with table per subclass strategy.

    Explain some of the pitfalls of Hibernate and explain how to avoid them? Give some tips on Hibernate best practices ?

    Pitfalls on Hibernate and how to avoid them:
  • O/R mapping framework like Hibernate is well suited for read -> modify -> write centric applications and not suited for write centric applications (i.e. batch processes with large data sets like 5000 rows or more) where data is seldom read.
  • Use the ThreadLocal session pattern when obtaining Hibernate session objects. This is important because Hibernateís native API does not use the current thread to maintain associations between session and transaction or between session and application thread. Spring ORM support for Hibernate can not only take care of the above pitfall but also can improve productivity.
  • Handle resources properly by making sure you properly flush and commit each session object when persisting information and also make sure you release or close the session object when you are finished working with it. Most developers fall into this pitfall. If you pass a connection object to your session object then remember to issue session.close().close () which will first release the connection back to the pool and then will close the session. If you do not pass a connection object then issue session.close() to close the session.
  • Use lazy associations when you use relationships otherwise you can unwittingly fall into the trap of executing unnecessary SQL statements in your Hibernate applications. Let us look at an example: Suppose we have a class Employee with many-to-one relationship with class Department. So one department can have many employees. Suppose we want to list the name of the employees then we will construct the query as follows:

    Query query = session.createQuery("from Employee emp");
    List list = query.list();


    Hibernate will generate the following SQL query: SELECT from Employee; If it only generates the query above then it is okay and it serves our purpose, but we get another set of SQL queries without asking it to do anything. One for each of the referenced departments in Department table. If you had 5 departments then the following query will be executed 5 times with corresponding department id. This is the N+1 selects problem. In our example it is 5 + 1. Employee table is queried once and Department table is queried 5 times. SELECT from Department where DEPARTMENT.id=? Solution is to make the Department class lazy (in Hibernate 3.0 the default value for lazy attribute is "true"), simply by enabling the lazy attribute in the Departmentís hbm.xml mapping definition file, which will result in executing only the first statement from the Employee table and not the 5 queries from the Department table.

    <class name="com.Department" table="Department" lazy="true" > ... </class>

    Only one query is required to return an employee object with its department initialized. In Hibernate, lazy loading of persistent objects are facilitated by proxies (i.e. virtual proxy design pattern). In the above example you have a Department object, which has a collection of Employee objects. Letís say that Employee objects are lazy loaded. If you make a call department.getEmployees() then Hibernate will load only the employeeIDs and the version numbers of the Employee objects, thus saving loading of individual objects until later. So what you really have is a collection of proxies not the real objects. The reason being, if you have hundreds of employees for a particular department then chances are good that you will only deal with only a few of them. So, why unnecessarily instantiate all the Employee objects? This can be a big performance issue in some situations.
  • Avoid N+1 selects problem: Having looked at the N+1 problem occurring inadvertently due to not having a lazy association in the previous example, now what if we need the Departmental information in addition to the Employee details. It is not a good idea to execute N+1 times.

    <class name="com.Department" table="Department" lazy="true" > ... </class>

    Now to retrieve Departmental info you would:

    Query query = session.createQuery("from Employee emp");
    List list = query.list();
    Iterator it = list.iterator();
    while(iter.hasNext()) {
    Employee emp = (Employee) it.next();
    emp.getDepartment().getName(); //N+1 problem. Since Department is not already loaded so
    //additional query is required for each department.
    }


    The solution is to make sure that the initial query retrieves all the data needed to load the objects by issuing a HQL fetch join (eager loading) as shown below:

    "from Employee emp join fetch emp.Department dept"

    The above HQL results in an inner join SQL as shown below:

    SELECT FROM employee inner join department on employee.departmentId = department.id.

    Alternatively you can use a criteria query as follows:

    Criteria crit = session.createCriteria(Employee.class); crit.setFetchMode("department", FetchMode.EAGER);

    The above approach creates the following SQL:

    SELECT FROM employee left outer join department on employee.departmentId = department.id where 1=1;

    Tips on Hibernate best practices:

  • Define equals() and hashCode() methods with the semi unique business key attributes (should not use the indentifier property) for the entity objects that are stored in a collection like a Set. Follow the equals() & hashCode() contracts.
  • Leave all your associations by default as lazy and also specify an appropriate batch-size for performance. Also make it a conscious choice to eagerly fetch data only for specific use cases.
  • Define your session management (i.e. use of detached objects etc), caching (both 1st level & 2nd level cache) and flush (i.e. auto-flush vs defining your own synchronization points etc) strategies early in your project.
  • Prefer using bi-directional associations for a one-to-many association with an inverse="true" attribute for efficiency. Also use batch updates/inserts for bulk inserts/updates (may even consider using Stored Procedures directly for large data).
  • Where possible use surrogate key as your identifier as opposed to using composite keys.
  • Keep your database transactions as short as possible with the use of detached objects and also understand the Hibernate object life cycles and states.
  • Use Spring ORM support for hibernate, which reduces the code size by almost a half and provides additional benefits such as easier testing, consistent exception hierarchy and management of Hibernate resources.

    Spring Interview Questions>>>




    Home Clouds