Voici les déclarations à effectuer pour intégrer JPA et Spring (cet exemple se base sur l'utilisation de l'implémentation Oracle Toplink de JPA) :
Etape 1 : Déclaration dans le contexte Spring des dépendances JPA
Activation du tissage lors du runtime pour le contexte Spring afin que tous les beans implémentant l'interface "LoadTimeWeaverAware" (comme le bean LocalContainerEntityManagerFactoryBean) reçoivent une référence vers le tisseur (cf documentation Spring pour plus de précisions).
Remarque, le load time weaving n'est nécessaire qu'avec l'implémentation Toplink
< context : load-time-weaver / >
|
Déclaration du "PersistenceUnitManager" permettant de personnaliser la sélection des unités de persistance et des sources de données.
(Cette étape n'est pas obligatoire )
< bean id = " persistenceUnitManager " class = " org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager " >
< property name = " persistenceXmlLocations " >
< list >
< value > classpath*:META-INF/persistence.xml< / value >
< / list >
< / property >
< property name = " dataSources " >
< map >
< entry key = " localDataSource " value-ref = " dataSource " / >
< / map >
< / property >
< property name = " defaultDataSource " ref = " dataSource " / >
< / bean >
|
Déclaration de l' "EntityManagerFactory" permettant de fournir les instances des gestionnaires d'entités :
< bean id = " entityManagerFactory " class = " org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean "
p : dataSource-ref = " dataSource "
p : persistenceUnitManager-ref = " persistenceUnitManager " >
< property name = " jpaVendorAdapter " >
< bean class = " org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter " p : databasePlatform = " oracle.toplink.essentials.platform.database.oracle.OraclePlatform "
p : showSql = " false " / >
< / property >
< property name = " loadTimeWeaver " >
< bean class = " org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver " / >
< / property >
< property name = " jpaDialect " >
< bean class = " org.springframework.orm.jpa.vendor.TopLinkJpaDialect " / >
< / property >
< / bean >
|
Déclaration du "TransactionManager" qui est le gestionnaire de transactions
< bean id = " txManager "
class = " org.springframework.orm.jpa.JpaTransactionManager "
p : entityManagerFactory-ref = " entityManagerFactory " >
< property name = " jpaDialect " >
< bean class = " org.springframework.orm.jpa.vendor.TopLinkJpaDialect " / >
< / property >
< / bean >
|
Activation de la prise en compte des annotations de type @Required,@Autowired,@PostConstruct,@PreDestroy,@Resource,@PersistenceContext,@PersistenceUnit :
< context : annotation-config / >
|
Déclaration d'un traducteur d'exception :
< bean class = " org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor " / >
|
Etape 2 : Implémentation d'une classe utilisant JPA
Chaque classe qui désire utiliser JPA pour accéder aux données peut :
- Soit hériter de la classe "org.springframework.orm.jpa.support.JpaDaoSupport"
- Soit se faire injecter un attribut de type "org.springframework.orm.jpa.JpaTemplate"
Dans le cas de l'héritage voici le type de déclaration à effectuer pour déclarer la classe (dépendance sur l' "EntityManagerFactory")
< bean id = " myDao " class = " com.drighetto.springjpa.dao.impl.DaoJpaImpl "
p : entityManagerFactory-ref = " entityManagerFactory " / >
|
Note : Pour le moment l'utilisation de JPA avec Spring ne supporte que l'isolation par défaut pour l'isolation des transactions...
Dans la classe org.springframework.orm.jpa.DefaultJpaDialect (la classe "org.springframework.orm.jpa.vendor.TopLinkJpaDialect" hérite de cette classe) dans la méthode beginTransaction() une vérification est faite sur l'isolation placée et si celle-ci n'est pas placée à défaut alors l'exception suivante est levée "Standard JPA does not support custom isolation levels - use a special JpaDialect for your JPA implementation".
Voici le fichier de contexte dans son ensemble :
<? 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 : p = " http://www.springframework.org/schema/p "
xmlns : aop = " http://www.springframework.org/schema/aop "
xmlns : context = " http://www.springframework.org/schema/context "
xmlns : jee = " http://www.springframework.org/schema/jee "
xmlns : tx = " http://www.springframework.org/schema/tx "
xmlns : util = " http://www.springframework.org/schema/util "
xsi : schemaLocation = "
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd " >
< context : load-time-weaver / >
< bean id = " dataSource "
class = " org.apache.commons.dbcp.BasicDataSource " destroy-method = " close "
p : driverClassName = " oracle.jdbc.driver.OracleDriver "
p : url = " jdbc:oracle:thin:@localhost:1521:xe " p : username = " MyTestUser "
p : password = " MyTestUser " / >
< bean id = " persistenceUnitManager "
class = " org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager " >
< property name = " persistenceXmlLocations " >
< list >
< value > classpath*:META-INF/persistence.xml< / value >
< / list >
< / property >
< property name = " dataSources " >
< map >
< entry key = " localDataSource " value-ref = " dataSource " / >
< / map >
< / property >
< property name = " defaultDataSource " ref = " dataSource " / >
< / bean >
< bean id = " entityManagerFactory "
class = " org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean "
p : dataSource-ref = " dataSource "
p : persistenceUnitManager-ref = " persistenceUnitManager " >
< property name = " jpaVendorAdapter " >
< bean
class = " org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter "
p : databasePlatform = " oracle.toplink.essentials.platform.database.oracle.OraclePlatform "
p : showSql = " false " / >
< / property >
< property name = " loadTimeWeaver " >
< bean
class = " org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver " / >
< / property >
< property name = " jpaDialect " >
< bean
class = " org.springframework.orm.jpa.vendor.TopLinkJpaDialect " / >
< / property >
< / bean >
< bean id = " txManager "
class = " org.springframework.orm.jpa.JpaTransactionManager "
p : entityManagerFactory-ref = " entityManagerFactory " >
< property name = " jpaDialect " >
< bean
class = " org.springframework.orm.jpa.vendor.TopLinkJpaDialect " / >
< / property >
< / bean >
< context : annotation-config / >
< bean
class = " org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor " / >
< aop : config >
< aop : advisor advice-ref = " txAdviceDao "
pointcut = " execution(* com.drighetto.springjpa.dao.impl.*.*(..)) " / >
< aop : advisor advice-ref = " txAdviceService "
pointcut = " execution(* com.drighetto.springjpa.services.*.*(..)) " / >
< / aop : config >
< tx : advice id = " txAdviceDao " transaction-manager = " txManager " >
< tx : attributes >
< tx : method name = " read* " propagation = " SUPPORTS "
read-only = " true " / >
< tx : method name = " set* " propagation = " SUPPORTS "
read-only = " true " / >
< tx : method name = " get* " propagation = " SUPPORTS "
read-only = " true " / >
< tx : method name = " * " isolation = " DEFAULT " timeout = " 10 "
propagation = " MANDATORY " read-only = " false "
rollback-for = " org.springframework.dao.DataAccessException " / >
< / tx : attributes >
< / tx : advice >
< tx : advice id = " txAdviceService " transaction-manager = " txManager " >
< tx : attributes >
< tx : method name = " display* " propagation = " SUPPORTS "
read-only = " true " / >
< tx : method name = " set* " propagation = " SUPPORTS "
read-only = " true " / >
< tx : method name = " get* " propagation = " SUPPORTS "
read-only = " true " / >
< tx : method name = " * " isolation = " DEFAULT " timeout = " 10 "
propagation = " REQUIRES_NEW " read-only = " false "
rollback-for = " org.springframework.dao.DataAccessException " / >
< / tx : attributes >
< / tx : advice >
< bean id = " myDao " class = " com.drighetto.springjpa.dao.impl.DaoJpaImpl "
p : entityManagerFactory-ref = " entityManagerFactory " / >
< bean id = " myService "
class = " com.drighetto.springjpa.services.Processor "
p : myDao-ref = " myDao " / >
< / beans >
|
|