Premiers pas avec l'hibernation
Utilisation de la configuration XML pour configurer Hibernate
Je crée un fichier appelé database-servlet.xml
quelque part sur le classpath.
Au départ, votre fichier de configuration ressemblera à ceci :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
</beans>
Vous remarquerez que j’ai importé les espaces de noms Spring tx
et jdbc
. C’est parce que nous allons les utiliser assez fortement dans ce fichier de configuration.
La première chose que vous voulez faire est d’activer la gestion des transactions basée sur les annotations ("@Transactional"). La principale raison pour laquelle les gens utilisent Hibernate dans Spring est que Spring gérera toutes vos transactions pour vous. Ajoutez la ligne suivante à votre fichier de configuration :
<tx:annotation-driven />
Nous devons créer une source de données. La source de données est essentiellement la base de données qu’Hibernate va utiliser pour conserver vos objets. Généralement, un gestionnaire de transactions aura une source de données. Si vous souhaitez qu’Hibernate communique avec plusieurs sources de données, vous disposez de plusieurs gestionnaires de transactions.
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="" />
<property name="url" value="" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
La classe de ce bean peut être tout ce qui implémente javax.sql.DataSource
afin que vous puissiez écrire la vôtre. Cet exemple de classe est fourni par Spring, mais n’a pas son propre pool de threads. Une alternative populaire est Apache Commons org.apache.commons.dbcp.BasicDataSource
, mais il en existe bien d’autres. Je vais expliquer chacune des propriétés ci-dessous :
-
driverClassName : le chemin d’accès à votre pilote JDBC. Il s’agit d’un fichier JAR spécifique à la base de données qui devrait être disponible sur votre chemin de classe. Assurez-vous que vous disposez de la version la plus récente. Si vous utilisez une base de données Oracle, vous aurez besoin d’un OracleDriver. Si vous avez une base de données MySQL, vous aurez besoin d’un MySQLDriver. Voyez si vous pouvez trouver le pilote dont vous avez besoin [ici] [1], mais une recherche rapide sur Google devrait vous donner le bon pilote.
-
url : L’URL de votre base de données. Habituellement, ce sera quelque chose comme
jdbc\:oracle\:thin\:\path\to\your\database
oujdbc:mysql://path/to/your/database
. Si vous recherchez sur Google l’emplacement par défaut de la base de données que vous utilisez, vous devriez être en mesure de savoir ce que cela devrait être. Si vous obtenez uneHibernateException
avec le messageorg.hibernate.HibernateException: Connection can not be null when 'hibernate.dialect' not set
et que vous suivez ce guide, il y a 90 % de chances que votre URL soit erronée, 5% de chances que votre base de données ne soit pas démarrée et 5% de chances que votre nom d’utilisateur/mot de passe soit erroné. -
username : Le nom d’utilisateur à utiliser lors de l’authentification auprès de la base de données.
-
password : Le mot de passe à utiliser lors de l’authentification auprès de la base de données.
La prochaine étape consiste à configurer la SessionFactory
. C’est la chose qu’Hibernate utilise pour créer et gérer vos transactions, et parle en fait à la base de données. Il a pas mal d’options de configuration que je vais essayer d’expliquer ci-dessous.
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="au.com.project />
<property name="hibernateProperties">
<props>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
</props>
</property>
</bean>
-
dataSource : Votre bean de source de données. Si vous avez modifié l’ID de la source de données, définissez-le ici.
-
packagesToScan : Les packages à analyser pour trouver vos objets annotés JPA. Ce sont les objets que la fabrique de session doit gérer, seront généralement des POJO et annotés avec
@Entity
. Pour plus d’informations sur la configuration des relations d’objet dans Hibernate [voir ici][2]. -
annotatedClasses (non affiché) : vous pouvez également fournir une liste de classes à analyser par Hibernate si elles ne sont pas toutes dans le même package. Vous devez utiliser
packagesToScan
ouannotatedClasses
mais pas les deux. La déclaration ressemble à ceci :
<property name="annotatedClasses">
<list>
<value>foo.bar.package.model.Person</value>
<value>foo.bar.package.model.Thing</value>
</list>
</property>
- hibernateProperties : Il y en a une myriade, toutes amoureusement [documentées ici][3]. Les principaux que vous utiliserez sont les suivants :
- hibernate.hbm2ddl.auto : L’une des questions les plus brûlantes d’Hibernate détaille cette propriété. [Voir pour plus d’informations][4]. J’utilise généralement la validation et configure ma base de données à l’aide de scripts SQL (pour une mémoire en mémoire) ou crée la base de données au préalable (base de données existante).
- hibernate.show_sql : indicateur booléen, si vrai, Hibernate imprimera tout le SQL qu’il génère sur
stdout
. Vous pouvez également configurer votre enregistreur pour vous montrer les valeurs qui sont liées aux requêtes en définissantlog4j.logger.org.hibernate.type=TRACE
log4j.logger.org.hibernate.SQL=DEBUG
dans votre gestionnaire de journaux (J’utilise log4j). - hibernate.format_sql : indicateur booléen, fera en sorte qu’Hibernate imprime joliment votre SQL sur stdout.
- hibernate.dialect (non affiché, pour une bonne raison) : de nombreux anciens tutoriels vous montrent comment définir le dialecte Hibernate qu’il utilisera pour communiquer avec votre base de données. Hibernate peut détecter automatiquement le dialecte à utiliser en fonction du pilote JDBC que vous utilisez. Puisqu’il existe environ 3 dialectes Oracle différents et 5 dialectes MySQL différents, je laisserais cette décision à Hibernate. Pour une liste complète des dialectes pris en charge par Hibernate [voir ici][5].
Les 2 derniers beans que vous devez déclarer sont :
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
id="PersistenceExceptionTranslator" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Le PersistenceExceptionTranslator
traduit les HibernateException
ou SQLExceptions
spécifiques à la base de données en exceptions Spring qui peuvent être comprises par le contexte de l’application.
Le bean TransactionManager
est ce qui contrôle les transactions ainsi que les annulations.
Remarque : Vous devriez auto-câbler votre bean SessionFactory
dans vos DAO.
[1] : http://mvnrepository.com/tags/jdbc [2] : http://stackoverflow.com/questions/24257449/how-do-i-use-annotations-to-define-x-relationship-in-hibernate-4-and-spring [3] : http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#configuration-optional [4] : http://stackoverflow.com/questions/438146/hibernate-hbm2ddl-auto-possible-values-and-what-they-do [5] : http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#configuration-optional-dialects
Configuration Hibernate sans XML
Cet exemple est tiré de [ici][1]
package com.reborne.SmartHibernateConnector.utils;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class LiveHibernateConnector implements IHibernateConnector {
private String DB_DRIVER_NAME = "";
private String DB_URL = "jdbc:h2:~/liveDB;MV_STORE=FALSE;MVCC=FALSE";
private String DB_USERNAME = "sa";
private String DB_PASSWORD = "";
private String DIALECT = "org.hibernate.dialect.H2Dialect";
private String HBM2DLL = "create";
private String SHOW_SQL = "true";
private static Configuration config;
private static SessionFactory sessionFactory;
private Session session;
private boolean CLOSE_AFTER_TRANSACTION = false;
public LiveHibernateConnector() {
config = new Configuration();
config.setProperty("hibernate.connector.driver_class", DB_DRIVER_NAME);
config.setProperty("hibernate.connection.url", DB_URL);
config.setProperty("hibernate.connection.username", DB_USERNAME);
config.setProperty("hibernate.connection.password", DB_PASSWORD);
config.setProperty("hibernate.dialect", DIALECT);
config.setProperty("hibernate.hbm2dll.auto", HBM2DLL);
config.setProperty("hibernate.show_sql", SHOW_SQL);
/*
* Config connection pools
*/
config.setProperty("connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
config.setProperty("hibernate.c3p0.min_size", "5");
config.setProperty("hibernate.c3p0.max_size", "20");
config.setProperty("hibernate.c3p0.timeout", "300");
config.setProperty("hibernate.c3p0.max_statements", "50");
config.setProperty("hibernate.c3p0.idle_test_period", "3000");
/**
* Resource mapping
*/
// config.addAnnotatedClass(User.class);
// config.addAnnotatedClass(User.class);
// config.addAnnotatedClass(User.class);
sessionFactory = config.buildSessionFactory();
}
public HibWrapper openSession() throws HibernateException {
return new HibWrapper(getOrCreateSession(), CLOSE_AFTER_TRANSACTION);
}
public Session getOrCreateSession() throws HibernateException {
if (session == null) {
session = sessionFactory.openSession();
}
return session;
}
public void reconnect() throws HibernateException {
this.sessionFactory = config.buildSessionFactory();
}
}
Veuillez noter qu’avec le dernier Hibernate, cette approche ne fonctionne pas bien (la version Hibernate 5.2 autorise toujours cette configuration)
[1] : https://github.com/reborne/SmartHibernateConnector
Exemple d’hibernation simple utilisant XML
Pour configurer un projet Hibernate simple utilisant XML pour les configurations, vous avez besoin de 3 fichiers, hibernate.cfg.xml, un POJO pour chaque entité et un EntityName.hbm.xml pour chaque entité. Voici un exemple de chacun utilisant MySQL :
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.connection.url">
jdbc:mysql://localhost/DBSchemaName
</property>
<property name="hibernate.connection.username">
testUserName
</property>
<property name="hibernate.connection.password">
testPassword
</property>
<!-- List of XML mapping files -->
<mapping resource="HibernatePractice/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
DBSchemaName, testUserName et testPassword seraient tous remplacés. Assurez-vous d’utiliser le nom complet de la ressource si elle se trouve dans un package.
Employé.java
package HibernatePractice;
public class Employee {
private int id;
private String firstName;
private String middleName;
private String lastName;
public Employee(){
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getMiddleName(){
return middleName;
}
public void setMiddleName(String middleName){
this.middleName = middleName;
}
public String getLastName(){
return lastName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
}
Employé.hbm.xml
<hibernate-mapping>
<class name="HibernatePractice.Employee" table="employee">
<meta attribute="class-description">
This class contains employee information.
</meta>
<id name="id" type="int" column="empolyee_id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="middleName" column="middle_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
</class>
</hibernate-mapping>
Encore une fois, si la classe est dans un package, utilisez le nom de classe complet packageName.className.
Une fois que vous avez ces trois fichiers, vous êtes prêt à utiliser la mise en veille prolongée dans votre projet.