Premier projet avec Tapestry5, Spring et Hibernate
Date de publication : 03/10/2007 , Date de mise à jour : 18/11/2007
Par
Baptiste Meurant (baptiste-meurant.developpez.com)
Ce tutoriel a pour objectif de guider vos premiers pas dans la création d'un projet Web basé sur Tapestry5, Spring et Hibernate à travers un exemple très simple de page de login.
I. Introduction
II. Pré requis
II.A. Installations
II.B. Préparation de la BDD
Remarque : les tables MySQL doivent être au format InnoDB pour que la génération des classes du modèle (voir mapping Hibernate) fonctionne correctement sous Eclipse.
III. Création du projet
IV. Architecture logicielle
V. Mise en place d'Hibernate
V.A. Installation d'Hibernate Tools
V.B. Ajout des librairies
V.C. Configuration de la connexion
V.D. Génération de la couche model et du mapping O/R
V.E. Ajout des classes mappées à la configuration Hibernate
VI. Mise en place de Spring
VI.A. Couche d'accès aux données
VI.B. Couche de services
VI.C. Gestion des Transactions
VI.D. Integration de Spring au lancement du projet
VII. Mise en place de Tapestry
VII.A. Simple login
VII.B. Intégration avec Spring
VIII. Mise en place du chargement retardé pour Hibernate
IX. Conclusion
X. Remerciements
XI. Dans la même série ...
I. Introduction
Ce tutoriel propose une application blanche pour un projet Tapestry5-Spring-Hibernate. Elle propose une page de login et une page principale et recherche l'existence du user en BDD. Le tutoriel se décompose en deux parties : une application blanche Spring-Hibernate autonome puis l'intégration de Tapestry5 à cette application. Ceci permettra de réutiliser la première partie avec un autre framework front.
Les sources de ce tutoriel sont téléchargeables
ici [mirroir
http]
la version pdf de ce tutoriel est disponible
ici [mirroir
http]
II. Pré requis
II.A. Installations
- Installer Eclipse et WTP téléchargeables ici ou à défaut, sur le site officiel d'eclipse
- Installer Tomcat 5.5, téléchargeable ici
- Installer mySQL, téléchargeable ici
II.B. Préparation de la BDD
- Créer une base de données et créer la table user :
| creation de la table user |
CREATE TABLE `user` (
`id_user` int(10) unsigned NOT NULL auto_increment,
`login_user` varchar(25) NOT NULL default '',
`password_user` varchar(25) NOT NULL default '',
PRIMARY KEY (`id_user`)
) ENGINE=InnoDB;
|
Remarque : les tables MySQL doivent être au format InnoDB pour que la génération des classes du modèle (voir mapping Hibernate) fonctionne correctement sous Eclipse.
| insertion du user de test |
INSERT INTO user VALUES ('test', 'test');
|
III. Création du projet
Note : Si vous avez déjà un projet existant, passez directement au chapitre suivant.
- Créer un nouveau projet de type Dynamic Web : Aller dans File -> new Project et choisir Web -> Dynamic Web Project. Cliquer sur Next.

Figure1 : Création du projet
- Renseigner le nom du projet et choisir un Target Runtime. Si rien n'est défini, cliquer sur new.

Figure2 : Configuration du projet
- Choisir un runtime (ici tomcat 5.5). Attention, il est nécessaire d'avoir installé le serveur.

Figure3 : Choix du runtime
- Renseigner les informations demandées et cliquer sur Finish.

Figure4 : Configuration du serveur
- De retour à l'interface de la Figure2, cliquer sur Next puis encore sur Next.

Figure5 : Finalisation du projet
- Changer le content directory à 'docs' (non obligatoire). Cliquer sur Finish.
- A l'issue de ces étapes, le package explorer devrait avoir l'allure de la Figure6 : un projet de type Dynamic Web créé ainsi qu'une configuration Server intégrée à Eclipse.

Figure6 : Projet vide
IV. Architecture logicielle
L'un des intérêts de l'intégration de ces différents frameworks est de permettre la mise en place d'une architecture logicielle rigoureuse, de manière à garantir la maintenabilité, l'évolutivité et l'exploitabilité des applications. La figure ci-dessous montre l'architecture qui sera mise en place dans le cadre de ce tutoriel.
Ce type d'architecture est très largement admise comme efficace et est généralisable à n'importe quel projet Web.

Figure7 : Architecture Logicielle
La principale caractéristique de cette architecture est la séparation des préoccupations (données vs métier vs web) grâce à la séparation stricte des couches applicatives. En effet, on peut observer sur la figure ci-dessus, les trois couches de cette application :
- Couche DAO : cette couche permet les accès à la BDD à travers le framework Hibernate.
- Couche Service : cette couche contient l'ensemble du code métier de l'application, elle organise et orchestre les accès à la couche DAO et ses aspects transactionnels. Ces différents aspects sont gérés et organisés par le framework Spring.
- Couche Front : cette couche est la couche d'entrée dans l'application du point de vue du client. Elle appelle les traitements de la couche Service en fonction des actions effectuées par le client et récupère les données retournées. Elle met ensuite en forme ces données pour les afficher au client. Cette couche est réalisée grâce au framework Tapestry5.
Ces trois couches sont rigoureusement séparées les unes des autres en ce sens qu'il ne doit exister idéalement aucune dépendance entre elles. Concrètement, chaque couche ne connaît que les interfaces de la couche immédiatement inférieure. Ainsi la couche Service ne connaît que les interfaces de la couche DAO et la couche Front ne connaît que les interfaces de la couche Service. De cette manière, chaque couche publie, via ses interfaces, l'ensemble des traitements qu'elle met à disposition des couches supérieures. Le lien entre interface et implémentation, qui introduit un couplage technologique (c'est dans l'implémentation uniquement que l'on fait référence à Hibernate par exemple) est géré par Spring.
C'est en effet Spring qui va nous permettre d'effectuer, au chargement de l'application, le lien entre Interface et Implémentation grâce à son moteur d'Inversion de Contrôle et d'injection de dépendances (voir plus loin). Le développeur ne travaille ensuite que sur des appels d'interfaces et non sur l'implémentation directement ce qui favorise grandement, on l'imagine, l'évolutivité et le faible couplage d'une application.
Enfin, on remarque une couche particulière, la couche model. Cette couche est la seule couche transverse à l'application puisqu'elle permet en effet de faire correspondre au modèle BDD le modèle objet que l'on va utiliser dans l'application pour manipuler les entités métier. Chaque couche peut donc naturellement manipuler les différentes entités métiers représentées par une hiérarchie de JavaBean correspondant chacun à une entité relationnelle.
Cette correspondance est appelée mapping Object/Relationnel et est permise par l'utilisation d'Hibernate. Chaque notion relationnelle est ainsi représentée sous sa forme objet ainsi que ses dépendances. Cela permet ensuite de faire persister les objets vers la BDD de manière complètement transparente. Ainsi, comme on le verra plus tard, chaque modification effectuée sur un objet mappé dans un contexte transactionnel sera automatiquement répercutée en base de donnée sans action explicite de la part du développeur. C'est ce que l'on appelle la persistance.
Insistons quelques instants sur la manipulation de la BDD. Le schéma et les explications ci-dessus montrent en effet que cette manipulation comporte deux aspects :
- La couche DAO publie des méthodes d'accès à la BDD de type création, recherche et suppression d'enregistrements (CREATE, SELECT et DELETE). En bref, cette couche permet de récupérer des instances d'objets à partir d'enregistrement BDD, de créer des nouvelles instances d'objets en créant les enregistrements BDD ou de supprimer des instances existantes en supprimant les enregistrements BDD.
- Le mapping O/R et la persistance des données permettent, dans un contexte transactionnel, d'effectuer toutes les opérations de type mise à jour (UPDATE). En effet, une fois récupérées des instances d'objets persistés grâce à la couche DAO, toute modification de l'instance entraînera une modification de l'enregistrement mappé.
Ainsi :
- Aucune méthodes de mises à jour d'instances n'est nécessaire pour les objets qui ont été obtenus dans un context transactionnel depuis la couche DAO.
- Cependant, les méthodes de création d'objet correspondant à des INSERT en base de données restent necessaires, car même dans un contexte transactionnel la couche Services ne peut décider à votre place s'il faut persister ou non une nouvelle instance de la couche model. Lorsque l'on crée un objet du model, il peut en effet s'agir d'une variable de travail temporaire par exemple qu'on ne souhaite donc pas enregistrer.
Ces différents aspects seront détaillés par la suite.
V. Mise en place d'Hibernate
Note : La version d'Hibernate considérée ici est une version 3.2 ou supérieure.
Dans cette partie nous allons nous charger de générer le modèle objet à partir du modèle relationnel et de mettre en place la persistance de ce modèle grâce à Hibernate.
V.A. Installation d'Hibernate Tools
Hibernate Tools est un plugin Eclipse permettant de générer automatiquement les classes de mapping du modèle à partir de la BDD :
- Extraire le zip téléchargé.
- Copier les deux répertoires plugins et features qu'il contient dans le répertoire d'installation d'Eclipse.
- Redémarrer Eclipse.
- Un certain nombre de nouveaux éléments apparaissent dans l'interface, prouvant l'installation du plugin :

Figure8 : Hibernate Tools Installé
V.B. Ajout des librairies
- Récupérer le driver de votre BDD (pour MySQL, voir ici) et le copier dans WEB-INF/lib
- Faire un refresh sur le projet dans Eclipse, le jar doit apparaître dans les Web App librairies.
- Inclure l'ensemble des jar nécessaires à Hibernate.

Figure9 : Ajout des jar Hibernate
V.C. Configuration de la connexion
- Créer un répertoire config et l'inclure en tant que source folder.

Figure10 : Création du répertoire config
- Sélectionner le répertoire config et cliquer sur File/New/Other. Puis choisir Hibernate/Hibernate configuration file.

Figure11 : Création du fichier de configuration Hibernate
- Configurer la connexion à la BDD en fonction des paramètres locaux. Penser à bien cocher la case 'Create Console configuration'

Figure12 : Configuration des paramètres de connexion
- Nous allons en profiter pour configurer la console Hibernate Tools afin de disposer d'un outil simple de génération de mapping. Configurer la console comme indiqué ci-dessous :

Figure13 : Configuration de la console
- Cliquer sur Classpath/Add JAR et ajouter le driver BDD puis cliquez sur Finish.

Figure14 : Création du lien entre la console et le driver
Le fichier de configuration Hibernate a été créé comme ceci :
| Fichier de configuration Hibernate - 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.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/experiments</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
</session-factory>
</hibernate-configuration>
|
- Ouvrir la vue Console et explorer la BDD. Le résultat devrait être celui-ci. Dans le cas contraire, vérifier les paramètres de connexion.

Figure15 : Exploration de la BDD via la console
V.D. Génération de la couche model et du mapping O/R
- Lancer la génération de code automatique :

Figure16 : Lancement de la génération automatique
- Configurer la génération de code comme ceci :

Figure17 : Configuration de la génération automatique 1
- Cliquer sur Exporters et cocher uniquement la génération de Domain code. Cliquer sur Run.

Figure18 : Configuration de la génération automatique 2
- Le code de la classe User a été généré avec l'ensemble des annotations nécessaires au mapping Hibernate.

Figure19 : Génération du JavaBean User mappé
| Classe User générée |
package tuto.webssh.domain.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "user", catalog = "experiments")
public class User implements java.io.Serializable {
private int idUser;
private String loginUser;
private String passwordUser;
public User() {
}
public User(int idUser, String loginUser, String passwordUser) {
this.idUser = idUser;
this.loginUser = loginUser;
this.passwordUser = passwordUser;
}
@Id
@Column(name = "id_user", unique = true, nullable = false)
public int getIdUser() {
return this.idUser;
}
public void setIdUser(int idUser) {
this.idUser = idUser;
}
@Column(name = "login_user", nullable = false, length = 25)
public String getLoginUser() {
return this.loginUser;
}
public void setLoginUser(String loginUser) {
this.loginUser = loginUser;
}
@Column(name = "password_user", nullable = false, length = 25)
public String getPasswordUser() {
return this.passwordUser;
}
public void setPasswordUser(String passwordUser) {
this.passwordUser = passwordUser;
}
}
|
On note les annotations :
- @Entity qui permet de déclarer la classe comme une entité persistante Hibernate.
- @Table qui permet d'associer l'entité à une table d'un catalogue, d'un schéma, d'une database donnée.
- @Id qui définit une propriétaire comme identifiant de l'entité (clé primaire).
- @Column qui associe la propriété avec un champ BDD et gère un certain nombre d'options. La propriété id par exemple, est unique et ne peut être commitée à null. On peut ainsi définir si la propriété peut être modifiée, etc. Cela permet à Hibernate d'effectuer les contrôles de cohérence et de sécurité en amont de l'enregistrement en base.
V.E. Ajout des classes mappées à la configuration Hibernate
Modifier le fichier hibernate.cfg.xml pour mapper la classe générée.
| Modification du fichier hibernate.cfg.xml |
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/experiments</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping class="tuto.webssh.domain.model.User"/>
</session-factory>
</hibernate-configuration>
|
Suite à cela, l'objet User est un objet persistant. Toute instance de User correspondra à un enregistrement BDD.
VI. Mise en place de Spring
Note : La version de Spring considérée ici est une version 2.0 ou supérieure.
- Télécharger Spring ici
- Décompresser le zip et copier le spring.jar dans WEB-INF/lib

Figure20 : Ajout des librairies Spring
Le framework Spring repose sur un moteur d'inversion de contrôle et d'injection de dépendances. Il s'agit de développer l'application en se basant uniquement sur des interfaces - ce qui permet de découper proprement l'application en couches bien distinctes. C'est ensuite le framework - en tant que contrôleur du flot d'exécution de l'application - d'injecter, au démarrage de l'application, le code de l'implémentation dans les différentes classes utilisant l'interface qu'elle étend. Ceci est fait grâce à un mécanisme d'injection de beans Spring grâce à des setters fournis par le développeur dans ses classes et à la configuration de chacun des couples interface/implémentation en tant que bean Spring configuré dans différents fichiers xml.
En se reposant sur ces mécanismes, nous allons créer deux couches distinctes : la couche d'accès aux données (dao) et la couche de services métiers (service) et leur permettre de travailler ensemble.
VI.A. Couche d'accès aux données
- Créer l'interface UserDao dans le package dao

Figure21 : Création de l'interface UserDao
- Créer l'implémentation de cette interface UserDaoImpl dans le package dao.hibernate3. Afin de bénéficier des fonctionnalités avancées et des API de Spring en ce qui concerne l'intégration avec Hibernate, faire dériver cette classe de la classe HibernateDaoSupport.

Figure22 : Création de l'implémentation UserDaoImpl 1

Figure23 : Création de l'implémentation UserDaoImpl 2

Figure24 : Création de l'implémentation UserDaoImpl 3
Voici les interfaces et classes créées. On en profite pour ajouter tout de suite le code dont on aura besoin par la suite :
| Interface UserDao |
package tuto.webssh.domain.dao;
import org.springframework.dao.DataAccessException;
import tuto.webssh.domain.model.User;
@author
public interface UserDao {
@param
@param
@return
@throws
public boolean checkLogin (String login, String password);
@param
@return
@throws
public User getUser(String login);
}
|
| Implémentation UserDaoImpl |
package tuto.webssh.domain.dao.hibernate3;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import tuto.webssh.domain.dao.UserDao;
import tuto.webssh.domain.model.User;
@author
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
{@inheritDoc}
public boolean checkLogin(String login, String password) {
if (null == login || null == password) {
throw new IllegalArgumentException("Login and password are mandatory. Null values are forbidden.");
}
try {
logger.info("Check user with login: "+login+" and password : [PROTECTED]");
Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
Criteria crit = session.createCriteria(User.class);
crit.add(Expression.ilike("loginUser", login));
crit.add(Expression.eq("passwordUser", password));
User user = (User)crit.uniqueResult();
return (user != null);
}
catch(DataAccessException e) {
logger.error("Exception - DataAccessException occurs : "+e.getMessage()
+" on complete checkLogin().");
return false;
}
}
{@inheritDoc}
public User getUser(String login) {
if (null == login) {
throw new IllegalArgumentException("Login is mandatory. Null value is forbidden.");
}
try {
logger.info("get User with login: "+login);
Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
Criteria crit = session.createCriteria(User.class);
crit.add(Expression.eq("loginUser", login));
User user = (User)crit.uniqueResult();
return user;
}
catch(DataAccessException e) {
logger.error("Exception - DataAccessException occurs : "+e.getMessage()
+" on complete getUser().");
return null;
}
}
}
|
On remarquera :
- l'utilisation du logger (API commons-logging) nativement intégré du fait de l'extension de la classe HibernateDaoSupport - l'utilisation de l'API générique commons-logging permet de greffer un système de log beaucoup plus puissant comme log4j par exemple.
- l'utilisation de la très riche API Hibernate Criteria permettant d'effectuer des requêtes en 'mode objet'. Noter que le même résultat peut être obtenu en HQL mais paraît - de mon point de vue - beaucoup moins élégant.
- l'utilisation des diverses interfaces Spring d'accès à la couche Hibernate qui permet de simplifier grandement les accès à la couche de mapping (par exemple le getHibernateTemplate(), etc.).
Créer un fichier xml ApplicationContextDao.xml dans WEB-INF et déclarer le couple interface implémentation sous la forme de bean Spring. Par défaut, les beans Spring sont des singleton et sont donc ThreadSafe. Cela garantit que le code peut être appelé sans risque de manière concurrente par deux process différents. Ce mécanisme est entièrement géré en interne par Spring.
Ce fichier définit un bean userDao correspondant à une interface et y associe l'implémentation correspondante. Ce bean contient une propriété (au sens des JavaBeans) sessionFactory définissant la configuration de la session Hibernate et notamment le lien vers le fichier de configuration Hibernate ainsi que la stratégie permettant de récupérer les différents objets mappés dans Hibernate. Ici, il s'agit de la stratégie basée sur les annotations.
| Fichier xml Spring Généré - ApplicationContextDao.xml |
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="userDao" class="tuto.webssh.domain.dao.hibernate3.UserDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
</beans>
|
VI.B. Couche de services
Les éléments de la couche dao vont être utilisés par les services métiers de la couche service supérieure :
- Dans deux nouveaux packages service et service.impl, créer l'interface UserManager et son implémentation UserManagerImpl.

Figure25 : Création du UserManager
| Interface UserManager |
package tuto.webssh.service;
import tuto.webssh.domain.model.User;
@author
public interface UserManager {
@param
@param
@return
public boolean checkLogin (String login, String password);
@param
@return
public User getUser(String login);
@param
@param
@return
public User changePassword (String login, String password);
}
|
| Implémentation UserManagerImpl |
package tuto.webssh.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import tuto.webssh.domain.dao.UserDao;
import tuto.webssh.domain.model.User;
import tuto.webssh.service.UserManager;
@author
public class UserManagerImpl implements UserManager {
private final Log logger = LogFactory.getLog(UserManagerImpl.class);
{@inheritDoc}
public boolean checkLogin (String login, String password) {
return userDao.checkLogin(login, password);
}
{@inheritDoc}
public User changePassword(String login, String password) {
User user = userDao.getUser(login);
if (user != null) {
user.setPasswordUser(password);
}
return user;
}
{@inheritDoc}
@SuppressWarnings("finally")
public User getUser(String login) {
return userDao.getUser(login);
}
}
|
On désire que la couche service accède à la couche dao. Cependant, partant du principe de séparation stricte des couches, l'ensemble des implémentations de services ne vont accéder directement qu'aux interfaces des dao et non aux implémentations. C'est Spring qui se chargera d'injecter les implémentations dans les objets (du type de l'interface) prévus à cet effet. Cette opération est possible grâce, d'une part à l'association faite entre l'interface et l'implémentation au niveau du fichier xml et, d'autre part par un injecteur (setter) prévu à cet effet dans chaque implémentation de la couche service.
- Editer la classe UserManagerImpl pour créer l'injecteur qui lui permettra d'accéder aux dao. On en profite pour ajouter les méthodes dont on aura besoin par la suite.
| Modification de UserManagerImpl |
package tuto.webssh.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import tuto.webssh.domain.dao.UserDao;
import tuto.webssh.domain.model.User;
import tuto.webssh.service.UserManager;
@author
public class UserManagerImpl implements UserManager {
private final Log logger = LogFactory.getLog(UserManagerImpl.class);
private UserDao userDao = null;
@param
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
{@inheritDoc}
public boolean checkLogin (String login, String password) {
return userDao.checkLogin(login, password);
}
{@inheritDoc}
public User changePassword(String login, String password) {
User user = userDao.getUser(login);
if (user != null) {
user.setPasswordUser(password);
}
return user;
}
{@inheritDoc}
@SuppressWarnings("finally")
public User getUser(String login) {
return userDao.getUser(login);
}
}
|
On remarque qu'il n'est fait mention ici d'aucune implémentation : seule l'interface est connue et accédée via la variable locale userDao. Au moment du démarrage de l'application, Spring utilisera le setter fournit pour injecter l'implémentation de l'interface UserDao définie dans le bean userDao du fichier ApplicationContextDao.xml dans l'objet userDao de la classe UserManagerImpl. Grâce à des appels à celui-ci et à la configuration effectuée dans le fichier ApplicationContextDao.xml, l'ensemble des méthodes de l'objet UserDao seront accessibles (Attention : seules les méthodes déclarées dans l'interfaces pourront être utilisées).
Pour pouvoir effectuer cette injection correctement, Spring a besoin que soit définit le bean userManager et qu'il référence, en tant que propriété interne, le bean userDao.
- Créer un fichier ApplicationContext.xml dans WEB-INF et y placer le code suivant :
| applicationContext.xml |
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="userManager" class=" tuto.webssh.service.impl.UserManagerImpl">
<property name="userDao">
<ref bean="userDao" />
</property>
</bean>
</beans>
|
On retrouve le mécanisme d'association interface/implémentation et on découvre l'injection de dépendance avec la définition de la propriété userDao qui fait référence au bean définit plus haut de même nom. Attention aux règles de nommage : le nom de la propriété du bean doit correspondre exactement au nom de la propriété du bean userManager. Pour y accéder, Spring transformera le nom de cette propriété en la faisant commencer par une majuscule puis en ajoutant 'set' devant.
VI.C. Gestion des Transactions
Outre l'inversion de contrôle, l'injection de dépendances, la structuration en couche, Spring offre des mécanismes de gestion des transactions BDD très puissants et très élégants dont on souhaite pouvoir bénéficier ici. Ces transactions sont gérées par des mécanismes de proxy et de PAO (Programmation Orientée Aspect), mécanismes qui sont au cœur même du framework Spring. La configuration des transactions se fait en trois temps :
- Définition du proxy général abstrait de manière globale à l'application dans un fichier xml Spring : dans ApplicationContextDao.xml, ajouter :
| applicationcontextDao.xml - configuration des transactions |
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="transactionProxy" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED, readOnly</
|