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 2


How does hibernate support legacy applications ?

You can use user defined data types and composite primary keys to get additional flexibility to support legacy applications. It is best practice to use wrapper classes like Boolean, Integer, Long etc instead of primitive types in your persistent classes. For example If you have a legacy application, which has the value of null for a Boolean property in its legacy table, then hibernate will throw a PropertyAccessException if you use the primitive type boolean since it cannot take the null value.

Explain some of the following attributes used in *.hbm.xml mapping file ?

cascade

Lets you control your graph of objects as to how automatically any associated objects gets saved, updated or deleted. It is also known as transitive persistence.
  • none (default): no automatic action.
  • save-update: save or update actions are automatically passed to the child entities.
  • delete: Delete actions are automatically passed to child entities.
  • delete-orphan: When a child is removed from the parent, then the child is automatically deleted.
  • all: save, update and delete actions are passed to child entities but not delete-orphan.
  • all-delete-orphan: save, update, delete and deleteorphan actions are passed to child entities.
  • There are other cascade values such as merge, replicate, persist, lock etc.
  • If you have a true composition relationship, where if the parent gets deleted then the children should also be deleted, then you should set the cascade attribute to alldelete-orphan. For example if an Order object is deleted then all its LineItem objects (i.e. children) should also be deleted as well.

    <hibernate-mapping>
    <class name="Car" table="car">
    ...
    <set name="parts" cascade="all" lazy="true">
    <key column="part_id" />
    <one-to-many class="com.Part" />
    </set>
    ...
    </class>
    </hibernate-mapping>


    inverse

    This attribute is used when you use the one-to-many and many-to-one bidirectional association to indicate that many-to-one side controls the association as opposed to one-to-many side. If you do not have the inverse flag or if it is set to false then the one-to-many side will control the association, which means if you have the following scenario:

    Car car1 = new Car("blue");
    car1.getParts().add(new Part("Steering"));
    car1.getParts().add(new Part("Brake"));
    session.save(car1);


    This will result in 3 INSERT SQL calls (1 for the parent Car object and 2 times for the Part objects). Since the association is controlled by the Car object (i.e. one-tomany side), inserting the part objects will not set the foreign key value (i.e. car_id) into the Part objects. There will be two additional UPDATE SQL calls to add the Car objectís foreign key value into the Part records. So this is not only inefficient but also will cause errors during INSERT SQL calls to Part objects if every part should have a car (i.e. foreign-key column car_id in Part is a not-null column). The solution to overcome the above issue is to set the attribute inverse="true" on the Car object (i.e. one-tomany side) to indicate that the ownership of the association should be given to the Part objects (i.e., many-to-one side). Since the association belongs to the Part objects there will never be an INSERT SQL call to the Part record with a null car_id.

    //one-to-many side
    <hibernate-mapping>
    <class name="Car" table="car">
    ...
    <set name="parts" cascade="all" inverse="true">
    <key column="part_id" />
    <one-to-many class="com.Part" />
    </set>
    ...
    </class>

    </hibernate-mapping>
    //many-to-one side
    <hibernate-mapping>
    <class name="Part" table="part">
    ...
    <many-to-one name="car" column="car_id" / >
    ...
    </class>
    </hibernate-mapping>


    lazy

    This property is used to determine if all the associated graph of objects should be "eagerly" fetched or "lazily" loaded when methods like session.get(""), session.load(""), session.find(""), etc are executed. The lazy loading uses proxy objects. lazy= true (default on hibernate 3.0 onwards) means load associated objects lazily. lazy=false means load associated objects eagerly. It is the best practice to set the lazy attribute to true in the mapping file and make it a conscious choice to eagerly join in your HQL or eagerly fetch in your criteria query for specific use cases. For e.g. String hqlQuery = " FROM Car c OUTER JOIN FETCH c.parts WHERE c.color=?"; If you want to access a lazily initialized collection, you must make sure that the session is open, otherwise an exception will be thrown. You could also optimize your lazy loading strategy by specifying the batch-size attribute as discussed next.

    <hibernate-mapping>
    <class name="Car" table="car">
    ...
    <set name="parts" cascade="all" lazy="true">
    <key column="part_id" />
    <one-to-many class="com.Part" />
    </set>
    ...
    </class>
    </hibernate-mapping>

    //session should be open to access a proxy object
    Session session= sessionFactory.openSession();
    Car car = session.load(Car.class, 12);// id =12
    Set parts = car.getParts();
    session.close(); //session is closed.
    Part part1 = (Part)parts.get(0); //exception is thrown
    //because the session is closed


    batch-size

    This is used as an optimization strategy for loading objects lazily. Hibernate can load several uninitialized proxy objects if one proxy object or collection is accessed. For example, say you have 50 Car objects loaded into a session with a session.find(...) query operation. Say each car object has an association with a collection of 10 Part objects. So if you iterate through all your Car objects, there will be 50 SQL SELECT calls to the database for every invocation of car.getParts() method. If you set your batch-size attribute to 20, then there will be only 3 SQL SELECTs to the database. Hibernate will load 20,20,10 collections in just 3 SELECT calls.

    <hibernate-mapping>
    <class name="Car" table="car">
    ...
    <set name="parts" batch-size="20">
    <key column="part_id" />
    <one-to-many class="com.Part" />
    </set>
    ..
    </class>
    </hibernate-mapping>


    unsaved-value

    unsaved-value attribute comes into play when you use the saveOrUpdate("") method. null is the default value. Other values supported are any, none, and id-value. If the unsaved-value is set to null or not set at all (default value is null) and if the primary-key property value is null then hibernate assumes that the object is transient and assigns a new primary-key id value before saving. If the primary-key property value is not-null then hibernate assumes that the object is already persistent and updates the object in the database without inserting. If you use a long primitive value instead of a Long wrapper object (best practice is to use wrapper objects) to store the primary key then the unsaved-value attribute value should be set to 0 because primitive values cannot be null.

    <hibernate-mapping>
    <class name="Car" table="car">
    <id name="id" column="car_id" type="long" unsaved-value="null">
    <generator class="native" />
    </id>
    <set name="parts" cascade="all" lazy="true">
    <key column="part_id" />
    <one-to-many class="com.Part" />
    </set>
    ...
    </class>
    </hibernate-mapping>


    Hibernate Interview Questions - Part 3>>>




    Home Clouds