Before Hibernate can be used in an application, the library has to be installed and configured.
The Hibernate ORM can be downloaded from http://hibernate.org/orm/ as a zip file containing a collection of JAR files that have to be added to the classpath manually.
As Hibernate depends on a couple of other open source libraries, it is recommended to let a build tool like Maven or Gradle resolve the dependencies automatically by adding a dependency to the hibernate-core module of the build file.
Before Hibernate can be used, it has to be configured with the correct connection parameters and the database driver to use. This can be done either by using an XML file (hibernate.cfg.xml
) or a properties file (hibernate.properties
). In both cases, the file should be stored in the classpath, normally in src/main/resources/
, if the Mavens standard directory structure is used.
A basic configuration in the XML format could look like this:
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.driver_class"> org.postgresql.Driver </property> <property name="connection.url"> jdbc:postgresql://localhost/car_portal </property> <property name="connection.username"> car_portal_app </property> <property name="connection.password"></property> <property name="dialect"> org.hibernate.dialect.PostgreSQL9Dialect </property> <property name="show_sql">true</property> </session-factory> </hibernate-configuration>
When using a properties file, the configuration would be written in a name=value
format (such as connection.username=car_portal_app
).
In addition to specifying the parameters needed to connect to the database, two optional settings are configured in the example:
true
, Hibernate logs all the executed SQL statements to the console.A complete list of the optional configuration properties is given in chapter 3.4 of the Hibernate reference documentation (http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/).
Before a Java application can interact with the persistence store, it has to open a session. A session is a single-threaded object that holds a JDBC connection to the database. As with connections, a session should be closed as soon as it is no longer needed. A new session can be created by calling openSession()
on the SessionFactory
.
A SessionFactory
is an immutable, thread-safe factory for session instances. It is recommended to instantiate it as a singleton object with the application-global scope.
Often, it is helpful to create a reusable helper class that provides the SessionFactory
:
public class SessionFactoryHelper{ private static final SessionFactory sessionFactory = createSessionFactory(); private static SessionFactory createSessionFactory(){ Configuration configuration = new Configuration().configure(); StandardServiceRegistry registry = new StandardServiceRegistryBuilder() .applySettings(configuration.getProperties()) .build(); return configuration.buildSessionFactory(registry); } public static SessionFactory getSessionFactory(){ return sessionFactory; } }
Upon the first invocation of the SessionFactoryHelper
, createSessionFactory
is called to instantiate the sessionFactory
object.
First, the configuration is loaded from the standard configuration file by calling configure on an instance of Configuration
. The loaded properties are then used to create an instance of StandardServiceRegistry
.
A ServiceRegistry
instance manages services, which provide functionality in a pluggable manner. An example of a service is ConnectionProvider
, which is an interface declaring methods for obtaining and releasing connections. Hibernate always references this interface, while the actual implementation is managed by the registry.
The ServiceRegistry
is then used again to let the Configuration
object build the SessionFactory
.
Once this is done, the factory can be obtained by calling the getSessionFactory
method.
In order to allow Hibernate to store objects in a table, a mapping between the Java class that represents the object and the table that it will be stored in has to be configured.
This can either be done by creating a mapping in the XML format or by adding annotations to an entity-class. In both cases, the mapping has to be added to the session-factory section in the configuration-file:
<mapping resource="Account.hbm.xml"/> <mapping class="carportal.Account"/>
The first entry adds a mapping in the XML format, while the second entry specifies the fully-qualified name of an annotated entity class.
It is possible to add multiple mappings to the configuration, and use both methods at the same time.
A very basic entity-class for the account
table could look like this:
package carportal; public class Account{ private int accountID; private String firstName; private String lastName; private String email; private String password; protected Account(){} }
It contains a private
field for each column in the table and a constructor without parameters. Hibernate needs this constructor to create an instance of the entity using Java reflection API.
For usage from within the application, the setter and getter methods for accessing the fields and a public constructor for initializing the entity should be added as needed.
After creating the entity class, a mapping file (Account.hbm.xml
) should be created in src/main/resources/
with the following content:
<hibernate-mapping package="carportal" schema="carportal_app"> <class name="Account" table="account"> <id name="accountID" column="account_id"> <generator class="identity"/> </id> <property name="firstName" column="first_name"/> <property name="lastName" column="last_name"/> <property name="email"/> <property name="password"/> </class> </hibernate-mapping>
The top level element, hibernate-mapping
, sets two optional parameters that define the default package name and the schema to be added to the unqualified class and table names.
Next, the class node maps a class name to the respective table. The table attribute is optional, and defaults to the class name if omitted.
There can be multiple class nodes in a mapping definition.
The mapping of columns to the fields is configured inside the class node using the id
and column
nodes. There has to be one id
node for each primary key column of the table.
All other columns are defined as a property
node. These are optional, and can be left out if a column will not be used inside the entity-class.
Both id
and property
nodes have a name
attribute, which specifies the field name of the defined class. They can also have an optional column
attribute if the names of the field and column do not match.
Additionally, the id
node configures a generator
class, which defines how the unique identifiers are created. The generator
class can either be given as a shortcut name of one of Hibernate's built-in generators or the class name of an external implementation.
Some of the built-in generators are:
<paramname="sequence">account_id_seq</param>
.A complete documentation of the XML mapping can be found in Chapter 5, SQL Language, of the Hibernate reference manual.
An alternative to XML mapping is to use annotations inside the entity class. Having the mapping inside the class makes it easier to maintain consistency when making changes, as there is only one file to edit.
The annotated version of the Account
class looks like this:
package carportal; import javax.persistence.*; @Entity @Table(name = "account") public class Account{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "account_id") private int accountID; @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; private String email; private String password; @Transient private int someInternalValue; private Account(){} }
The following annotations were added to the Account
class:
@Id
marks a field as primary key. An entity class must define all the primary keys of a table.The fields email
and password
are not annotated in the example, as the account table has columns with matching names. Fields without annotations are automatically added to the mapping with a default configuration.
For the remainder of this chapter, annotation-based mapping will be used, as it is more convenient to use and XML mapping is now considered legacy.
3.133.148.180