Monday, August 29, 2016

JPA: Persisting vs Merging Entities

Persisting entities
  • persist deals with new entities (passing a detached entity may end up with an exception.)
  • persist always causes INSERT SQL operation is executed (i.e. an exception may be thrown if the entity has already been inserted and thus the primary key violation happens.)
  • persist makes a previously removed entity managed again
  • persist makes the passed entity managed
  • persist does not return any value







Merging entities
  • merge deals with both new and detached entities
  • merge causes either INSERT or UPDATE operation according to the sub-scenario (on the one hand it is more robust, on the other hand this robustness needn't be required.)
  • merge throws an exception if a previously removed entity is passed
  • merge copies the state of the passed entity to the managed entity
  • merge returns the managed entity - the clone of the passed entity








So, when should I use persist and when merge?

persist
  • You want the method always creates a new entity and never updates an entity. Otherwise, the method throws an exception as a consequence of primary key uniqueness violation.
  • Batch processes, handling entities in a stateful manner (see Gateway pattern)
  • Performance optimization
merge
  • You want the method either inserts or updates an entity in the database.
  • You want to handle entities in a stateless manner (data transfer objects in services)
  • You want to insert a new entity that may have a reference to another entity that may but may not be created yet (relationship must be marked MERGE). For example, inserting a new photo with a reference to either a new or a preexisting album.

Friday, August 26, 2016

HIBERNATE: IMPLEMENTING INHERITANCES (Introduction & Single-Table Strategy)

So, this is the situation. We have a parent 'Vehicle' class. Then there are two child classes extending from the Vehicle class.



Programmatically expressed as,

PARENT CLASS


CHILD CLASS-1


CHILD CLASS-2


main() method


Resultant Schema








SINGLE-TABLE STRATEGY (more options)

Default inheritance strategy is SINGLE.TABLE

PARENT VEHICLE CLASS


CHILD CLASS-1
This time, the column value for this child class will be 'Bike' inside the table.

CHILD CLASS-2
The value inside the table would be now 'Car'.


main() method:



Resultant Schema









Sunday, August 21, 2016

HIBERNATE: PERSISTING A DETACHED OBJECT

A retrieved persistent object becomes detached once the session is closed. This however can be fixed by reopening the session and reattaching the object to the session with the help of update() method.

Note: This transforms the object back to persistent state.


Make sure hbm2ddl inside hibernate.cfg.xml is set to update and not create!!

JPA: Object Lifecycle States

CREATING & SAVING A NEW OBJECT is changing state from Transient to Persistent by means of the Session object's save() method.





Fetching an instance from the database automatically gives us a persistent object and changes to it are constantly tracked.




Then there's another method of Session object called delete() which removes an instance from the database and returns a transient object!!

HIBERNATE: MANY TO MANY MAPPING

Simplest way is by marking the associated members by @ManyToMany and the rest is taken care of.






The objects must be attached to their counterpart's arraylist as seen in the screenshot.





This however created a redundant schema. One table is completely unnecessary here.!!!





So this can be removed by putting mappedBy inside one of the classes of one's choice.





And now the resultant schema will have one table less than before, thanks to mappedBy.




HIBERNATE: ONE TO MANY MAPPING

This kind of relationship is denoted through @OneToMany annotation. An optional annotation, @JoinTable can be used to rename the join-table and the constituent attributes.





This is how the vehicle class looks like when the relationship is one-way!!





Finally, in the main method, first the individual Vehicle objects are defined and then each of them gets assigned to the inner arraylist of the parent entity.





This is how the schema looks like. @JoinTable attributes' influence can be seen here clearly with the names.
Basically, two separate tables are created for the both entities and a table is created just for the sake of joining both the entities.






If a two-way relationship is required, in that case, a UserDetails object must be contained within the Vehicle class too. This way, one can fetch the owner of a vehicle. 
This is done using @ManyToOne annotation after the object aforementioned has been placed.






With the changed structure of the Vehicle entity, now one must also save the user for each vehicle to retain the two-way relationship.





The schema remains the same!


However, the above schema is redundant as the extra table is unnecessary. The extra table can be merged into the schema of the vehicle. This can be done by removing the settings previously made and setting the 'mappedBy' attribute of @OneToMany annotation. mappedBy takes the name of the member variable that provides the connection from the other class.







This is the class that provides the join this time, therefore containing the USER_ID foreign key. @JoinTable annotation can be used to rename the table though.




This is the resultant schema, thereby reducing the redundant join table.





HIBERNATE: ONE TO ONE MAPPING

A Vehicle entity is inside a UserDetails entity!

Here is the definition of vehicle entity:


This newly defined entity must be mentioned in the hibernate.cfg.xml file.




Now put the Vehicle object inside the UserDetails class definition:
Used annotations are @OneToOne (which is self explanatory) and @JoinColumn (is optional) which takes the attribute name to rename the otherwise generated foreign key column name.





The generated schema looks like the following:



Basically, both the entities have separate tables and just one column to connect them in the parent USER_DETAILS class. 

However, the order of SQL queries made up here is very interesting. First, both the entities are inserted, and then the association using foreign key is made using an UPDATE operation.


HIBERNATE: Proxy Objects & FetchType attribute

Hibernate by default uses lazy fetching of associated objects which may throw exceptions if the session closes before fetching the inner objects.




 Hibernate uses something called Proxy objects to optimize the performance. It has all the basic class members excluding the COMPOSITE ones in this case. Upon request for the same, it then fetches it from the database.





This can be overridden by setting fetch type as EAGER as in the example below:



Saturday, August 20, 2016

HIBERNATE: Saving Collections


  • Imagine a situation where you want to save the list of current and past addresses of an employee. 
  • One cannot say what would be the right number of objects. 
  • Hence, a collection of Address is to be used in this situation.

This is the element to be stored as a collection of.



Instead of using @Embedded annotation this time on the class member, we use @ElementCollection to denote the presence of a collection-type member of the class.





This upon executing the main() method as shown below will produce another table which will consist of the addresses for each user.



A new table is created combining the names of the entity class and the value object's class as show below:



The name of table may not seem very user-friendly and therefore there are ways to rename it to whatever the hell you like. 

This can be done through @JoinTable annotation. Some additional annotations can be used to rename the foreign key to the parent table, i.e. @JoinColumn(name="***")






Some additional Hibernate-native annotations can be used to add primary key to the join table created.

  • @GenericGenerator is an id generator provided by the Hibernate.
  • @CollectionId is an annotation used to add primary key column to the table created for a collection of embedded value objects inside the parent entity class.



To be Noted! As can be seen from upper screenshot, the collection data type has changed to ArrayList from Set since sets do not support indexing, which means there's no such things are indices/positions inside a set structure.






HIBERNATE: Two Value Objects inside One Entity

WHAT IF THERE ARE TWO VALUE OBJECTS (or EMBEDDED OBJECTS) OF THE SAME TYPE LIKE BELOW?



  • The relational schema for this one is not possible as the column names are already used up by the time the first value object is mapped to the table. 
  • This requires renaming of the columns through @AttributeOverride annotation. 
  • A plural of this annotation, i.e. @AnnotationOverrides is used to bundle up a bunch of such renaming overrides as below...


HIBERNATE: Embedding Value (Non Entity) Objects into Entity


  1. An entity has a meaning of its own and can exist independently. 
  2. Value objects on the other hand do not have a meaning of their own. 
  3. Hence, if we have embedding a value object into an entity, then the fields of the value object shall receive a corresponding column in the relational schema, resulting in a single table despite a clear association.
Let us add a value object called Address to the User class.
This new entity will map to the shown schema. (Since each user has one address only)







How can this be realized in Hibernate?

Answer: Using @Embeddable and @Embedded annotations from standard JPA.


Here is the definition of the Address class that will be embedded inside UserDetails class.





And here is the definition of the UserDetails class


HIBERNATE: Hibernate.cfg.xml Correct Settings

Click to Zoom In


  • show_sql decides whether or not to display the SQL queries inside console during execution. Possible values are create and update.
  • If set to create, that will drop the previous schema every time the program is executed. If set to update, the previous schema will be completely ignored in case the entity has changed or if no changes, then will simply use the same schema for CRUD operations.
  • Also, it is necessary to mention all the entity classes here as done in the last block. These mapping are necessary to keep track of the entities.

HIBERNATE: Save & Retrieve an Entity in Hibernate

 //HOW TO SAVE  
 SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); //Don't create this object too often since it's heavyweight and takes up a lot of resources to create...  
 Session session = sessionFactory.openSession();  
 session.beginTransaction();  
 session.save(user); //or whatever object that needs to be persisted  
 session.getTransaction().commit();  
 session.close();  //Always close a session after use

 //HOW TO RETREIVE USING PRIMARY KEY OR ID  
 session = sessionFactory.openSession(); //previous session is destroyed, so a new session is being generated  
 session.beginTransaction(); //transaction needs to be started again  
 user = (User) session.get(User.class, 1); //Type-casting is necessary upon retrieval  
 session.close();