Hibernate, Entities and Database Generation"

From Documentation
(Created page with '{{ZKEssentialsPageHeader}} Hibernate persists Objects to the database but to do this we need two things, a database schema and a set of mapped classes. In the previous section w…')
 
m
Line 1: Line 1:
 
{{ZKEssentialsPageHeader}}
 
{{ZKEssentialsPageHeader}}
 +
 +
__TOC__
  
 
Hibernate persists Objects to the database but to do this we need two things, a database schema and a set of mapped classes. In the previous section we explored the Hibernate configuration file and found the following lines:
 
Hibernate persists Objects to the database but to do this we need two things, a database schema and a set of mapped classes. In the previous section we explored the Hibernate configuration file and found the following lines:

Revision as of 08:47, 8 November 2010

Stop.png This article is out of date, please refer to http://books.zkoss.org/zkessentials-book/master/ for more up to date information.


Hibernate persists Objects to the database but to do this we need two things, a database schema and a set of mapped classes. In the previous section we explored the Hibernate configuration file and found the following lines:

<property name="hibernate.hbm2ddl.auto">create-drop</property>

<mapping class="demo.model.bean.Order"/>
<mapping class="demo.model.bean.OrderItem"/>
<mapping class="demo.model.bean.User"/>
<mapping class="demo.model.bean.Product"/>

One of the most important properties in this XML file is “hibernate.hbm2ddl.auto” set as “create-drop”. When set to create the option will create exports the schema DDL to the database when Hibernate’s SessionFactory is created. This is very useful when developing a data driven application as it eliminates the need to manually update SQL scripts when your schema needs to change. However, this setting is not recommended for production usage.

The other properties enable the mapping of Java classes to Database tables. In general, this mapping is declared in two ways:

  • By giving the class name using the attribute class
  • By providing a URI to an XML resource which describes the mapping

Mapping by XML or annotations achieve the same task and generally the method of description depends on the developer. Some developers prefer XML, some prefer annotations. In this case we chose to use annotations.

Using Hibernate Annotations

Annotations in Hibernate are placed on the class declaration when instructing Hibernate that the class is an Entity. Then developers have a choice, annotations can be places on field declarations or on the getter of the property.

There are varying opinions on which is better and why however, in this case we have chosen to place the annotation on the field value as it is clearer for the purposes of this chapter. Having established where annotations are placed let’s investigate what is actually placed using a class as an example.

@Entity
@Table(name="products")
public class Product {
	
	@Id
        @GeneratedValue(strategy=GenerationType.AUTO)
	private long id;

        @Column(name="productname")
	private String name;

        @Temporal(TemporalType.TIMESTAMP)
	private Date createDate;
	private float price;
	private int quantity;
	private boolean available; 
	private String imgPath;

	
}

The above code demonstrates how the Product class was annotated to allow persistence. Taking the annotations one at a time we will explore what they do.

@Entity

An entity is a lightweight persistence domain objects representing a table in a database. In this case we let Hibernate know that the class Product is an entity. This is required for classes you would like to persist to the database.

@Table(name="products")

The table entity is set at the class level and enables us to define the table, catalog and schema names of the entity mappings. If names are not specified then the default values are used, however, in our case product is an SQL reserved word therefore we cannot leave it as default hence we set the name as products in this case.

@Id

We need to let Hibernate know which field of ours id the ID, in this case this is easily achieved by applying the annotation @Id.


@GeneratedValue(strategy=GenerationType.AUTO)

Along with the annotation for the @Id, if it is auto-incremented by the database we also need to inform Hibernate. In this case we let Hibernate know by specifying the @GeneratedValue and setting the strategy to GenerationType AUTO.

@Column(name="productname")

The next annotation refers to the definition of a column. Under normal circumstances we do not need to provide a name however, in this case without specifying the name of the column it would default to “name.” Just as “product”, “name” is also an SQL reserved keyword therefore we need to specify a better name for the column.


@Temporal(TemporalType.TIMESTAMP)

Java APIs do not define the temporal precision of time. When placing data into persistent storage we would like to describe the expected prevision. In this case we use the Temporal attribute to specify it. Types include DATE, TIME and TIMESTAMP.

These attributes which we have explored are also used throughout the application in the other beans. There is only one exception to this present in Order.java which explores the description of a linking table using Hibernate annotations.


Creating the linking table

An Order has a one-to-many relationship with OrderItems, to map this relationship in the database we need to introduce a linking table name OrderedItems. This relationship is shown below:

ZKEss linking table.png

In order for Hibernate to generate the database schema and map the relationship correctly we need to tell it about this relationship. To do this we use two annotations:

  • @OneToMany
  • @JoinTable

Let’s take a look at the relative code.

@OneToMany
@JoinTable(
    name="OrderedItems",
    joinColumns=@JoinColumn(name="orderid"),
    inverseJoinColumns=@JoinColumn(name="orderitemid")
)
@LazyCollection(value=LazyCollectionOption.FALSE)
private List<OrderItem> items = new ArrayList<OrderItem>();


The “name” sets the table name that Hibernate (in this case) will create. If you are not using Hibernate to create the schema as in this tutorial then it refers to the table name. The “@joinColumn” in this case takes the “name” and “referencedColumnName” which are the name of the column in the table OrderedItems and the name of the referenced column within the entity.

“joinColumns” requires the foreign key columns of the join table which reference the primary table of the entity owning the association, in this case the order id. On the other hand “inverseJoinColumns” requires the foreign key columns of the join table which reference the primary table of the entity that does not own the association, in this case the OrderItem’s id.

To make it easier, the Order owns the association (ie. Owns the Order items) so its key is passed to “joinColumns” and OrderItem does not own the association so it is passed to “inverseJoinColumns.”


Lazy Loading

There is one last thing to consider; when the object Order is loaded we will also want to load its OrderItems as they will be accessed at the same time. The problem is Hibernate will lazily load collections which are joined. This means that when the Order object is loaded then the its OrderItems aren’t.

In this case Hibernate only loads the first object level which can lead to exceptions such as a LazyLoadException when we access the item list and it has not been initialized. In this case it is easy to fix by making use of the @LazyCollection annotation and setting the option to FALSE:

@LazyCollection(value=LazyCollectionOption.FALSE)

This will ensure that when an Order is loaded its OrderItems are too. When designing larger systems we will obviously have to take into account how much data should be loaded and whether we should follow lazy loading practices or not. For the purposes of this chapter lazy loading is not required.

The final item to finishing working with your Hibernate application is to introduce Session management and how we implemented the DAOs to use Hibernate.




Last Update : 2010/11/08

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.