Saturday, October 19, 2013

Hibernate Requirements

To integrate Hibernate with your Java application, you will need to use several Java libraries. The first library is the Java Archive (JAR) file for your JDBC driver, which you will need to find for your specific relational database.

SessionFactory object is thread safe

The details of the join table that contains the links between the two classes in a many-to-many relationship go on the owner class. The Category class owns the relationship, so we add a @JoinTable annotation. The @JoinTable annotation indicates that the relationship requires the creation of an additional link table, so we specify the name of the table containing that information.

The @ManyToMany annotation indicates that the Category class has a many-to-many relationship with the Advert class. This many-to-many relationship is bidirectional, which means that the Advert class has a collection of Category objects, and the Category class has a collection of Advert objects. For many-to-many relationships, we need to tell Hibernate which class is the owner of the relationship. For bidirectional many-to-many relationships, either side can be designated as the owner. For this example, the Category class will be the owner.

Entities can contain references to other entities—either directly as a property or field, or indirectly via a collection of some sort (arrays, sets, lists, etc.). These associations are represented using foreign key relationships in the underlying tables.
When only one of the pair of entities contains a reference to the other, the association is unidirectional. If the association is mutual, then it is referred to as bidirectional.

If both ends of the association managed the foreign keys, then we would encounter a problem when client code called the appropriate set method on both ends of the association. Should two foreign key columns be maintained—one in each direction (risking circular dependencies)—or only one? (And if only one, should altering either side affect it, o r only one?)
Ideally, we would like to dictate that only changes to one end of the relationship will result in any updates to the foreign key; and indeed, Hibernate allows us to do this by marking one end of the association as being managed by the other (in the XML mapping files, this is known as the "inverse" of the parent, whereas in the JPA terminology used by the annotation mappings, it is marked as being "mappedBy" the parent in the @OneToMany annotation).

Caution 
inverse and mappedBy are purely about how the foreign key relationships between entities are saved. They have nothing to do with saving the entities themselves. Despite this, they are often confused with the entirely orthogonal cascade functionality (described in the "Cascading Operations" section of this chapter).
While Hibernate lets us specify that changes to one association will result in changes to the database, it does not allow us to cause changes to one end of the association to be automatically reflected in the other end in the Java POJOs. For example, in a one-to-one bidirectional association between an Email class and a Message class, the code in Listing 4-2 is incomplete even if the Message entity is the inverse of the Email entity:

You should not use a load() method unless you are sure that the object exists. If you are not certain, then use one of the get() methods. The load() methods will throw an exception if the unique id is not found in the database, whereas the get() methods will merely return a null reference.
You can also instruct Hibernate to use a flushing mode for the session with the setFlushMode() method. The getFlushMode() method returns the flush mode for the current session, as follows:
public void setFlushMode(FlushMode flushMode)
public FlushMode getFlushMode()
The possible flush modes are the following:
  • ALWAYS: Every query flushes the session before the query is executed This is going to be very slow.
  • AUTO: Hibernate manages the query flushing to guarantee that the data returned by a query is up-to-date.
  • COMMIT: Hibernate flushes the session on transaction commits.
  • MANUAL: Your application needs to manage the session flushing with the flush() method. Hibernate never flushes the session itself.

By default, Hibernate uses the AUTO flush mode. Generally, you should use transaction boundaries to ensure that appropriate flushing is taking place, rather than trying to "manually" flush at the appropriate times.

By default, Hibernate does not cascade any operations—the default behavior can be overridden at the entity level via the XML mapping files using the default-cascade attribute on the <hibernate-mapping> XML element or in the annotated source files.
The last possible cascading type is delete-orphan. Use delete-orphan to remove a child object from the database when you remove the child from the parent's collection. This cascading type only works on one-to-many associations. The all cascading type does not include delete-orphan—you will have to use "all,delete-orphan", as in the following excerpt from a Hibernate mapping file:

Instead, we want only the catalog to load, possibly with the categories as well. Only when the user drills down into the categories should a subset of the products in that category be loaded from the database.
To manage this problem, Hibernate provides a facility called lazy loading. When enabled (this is the default using XML mappings, but not when using annotations), an entity's associated entities will only be loaded when they are directly requested. For example, the following code loads only a single entity from the database:

Lazy Loading

When you load classes into memory from the database, you don't necessarily want all the information to actually be loaded. To take an extreme example, loading a list of e-mails should not cause the full body text and attachments of every e-mail to be loaded into memory. First, they might demand more memory than is actually available. Second, even if they fit, it could take a long time for all of this information to be obtained.
If you were to tackle this problem in SQL, you would probably select a subset of the appropriate fields for the query to obtain the list; for example:
SELECT from, to, date, subject FROM email WHERE username = 'dcminter';
Hibernate will allow you to fashion queries that are rather similar to this, but it also offers a more flexible approach, known as lazy loading. Certain relationships can be marked as being "lazy," and they will not be loaded from disk until they are actually required.
The default in Hibernate 3 is that classes (including collections like Set and Map) should be lazily loaded. For example, when an instance of the User class given in the next listing is loaded from the database, the only fields initialized will be userId and username.
public class User {
   int userId;
   String username;
   EmailAddress emailAddress;
   Set roles;
}
However, as long as the object is still associated with Hibernate in the appropriate way (see Chapter 9), the appropriate objects for emailAddress and roles will be loaded from the database if they are accessed.
This is the default behavior only; the mapping file can be used to specify which classes and fields should behave in this way.


Required Libraries for Running Hibernate 3.5

Hibernate requires several libraries beyond hibernate3.jar. These libraries are included in the lib/required directory of your Hibernate 3.5 installation. Besides the libraries in lib/required, Hibernate also uses a JPA library, which is included in the lib/jpa directory.
Hibernate 3.5 also requires a bytecode library to function. There are two bytecode libraries shipped with the Hibernate distribution — javassist and CGLib. With Hibernate 3.5, you need to use one or the other. In this book, we will use javassist, as it is the default library.

Introduction to the Life Cycle

After adding Hibernate to your application, you do not need to change your existing Java object model to add persistence marker interfaces or any other type of hint for Hibernate. Instead, Hibernate works with normal Java objects that your application creates with the new operator, or that other objects create. For Hibernate's purposes, these can be drawn up into two categories: objects for which Hibernate has entity mappings, and objects that are not directly recognized by Hibernate. A correctly mapped entity object will consist of fields and properties that are mapped, and that are themselves either references to correctly mapped entities, references to collections of such entities, or "value" types (primitives, primitive wrappers, strings, or arrays of these).
Given an instance of an object that is mapped to Hibernate, it can be in any one of three different states: transient, persistent, or detached.
Transient objects exist in memory, as illustrated in Figure 4-1. Hibernate does not manage transient objects or persist changes to transient objects.
Image from book
Figure 4-1: Transient objects are independent of Hibernate.
To persist the changes to a transient object, you would have to ask the session to save the transient object to the database, at which point Hibernate assigns the object an identifier.

Persistent objects exist in the database, and Hibernate manages the persistence for persistent objects. We show this relationship between the objects and the database in Figure 4-2. If fields or properties change on a persistent object, Hibernate will keep the database representation up-to-date.
Image from book
Figure 4-2: Persistent objects are maintained by Hibernate.
Detached objects have a representation in the database, but changes to the object will not be reflected in the database, and vice versa. This temporary separation of the object and the database is shown in Figure 4-3. A detached object can be created by closing the session that it was associated with, or by evicting it from the session with a call to the session's evict() method. One reason you might consider doing this would be to read an object out of the database, modify the properties of the object in memory, and then store the results some place other than your database. This would be an alternative to doing a deep copy of the object.
Image from book
Figure 4-3: Detached objects exist in the database but are not maintained by Hibernate.
In order to persist changes made to a detached object, the application must reattach it to a valid Hibernate session. A detached instance can be associated with a new Hibernate session when your application calls one of the load(), refresh(), merge(), update(), or save() methods on the new session with a reference to the detached object. After the call, the detached object would be a persistent object managed by the new Hibernate session.

If you are already using hibernate.properties, hibernate.cfg.xml will override any settings in hibernate.properties. Both of these files should be located in the root of your application's classpath.



No comments:

Post a Comment