workshop spring session 2 - la persistance au sein des applications java

22
Workshop Spring - Session 2 La persistance au sein des applications Java Conçu en décembre 2011 Réactualisé en novembre 2014 # 1

Upload: antoine-rey

Post on 08-Jul-2015

3.955 views

Category:

Technology


8 download

TRANSCRIPT

Page 1: Workshop spring   session 2 - La persistance au sein des applications Java

Workshop Spring - Session 2La persistance au sein des

applications Java

Conçu en décembre 2011Réactualisé en novembre 2014

# 1

Page 2: Workshop spring   session 2 - La persistance au sein des applications Java

1. La persistance des données facilitée

Gestion des exceptions

Déclarer une source de données

Classes de support pour JDBC, Hibernate et JPA

2. Encore plus loin avec

Spring Data JPA

et QueryDSL

3. Gestion des transactions

Agenda du workshop n°2

# 2

Page 3: Workshop spring   session 2 - La persistance au sein des applications Java

Mise en œuvre de la persistance

Les atouts du framework Spring :

Facilite l’utilisation de JDBC et des principaux ORM

Rend le code plus lisible

Limite les risques d’erreur inhérents à la libération des ressources

Gestion des exceptions

Laisse la possibilité d’accéder à la technologie sous-jacente

Gère élégamment les transactions

Le projet Spring Data apporte un support :

Encore plus avancé pour JDBC et JPA

Pour les différents types de bases de données

(orientées graphes, colonnes, map …)

# 3

Page 4: Workshop spring   session 2 - La persistance au sein des applications Java

# 4

Gestion des exceptions

Les exceptions levées par un DAO doivent être indépendantes de la

technologie sous-jacente :

SQLException pour JDBC

HibernateException pour Hibernate

Spring permet de s’abstraire de ces exceptions techniques en disposant

de sa propre hiérarchie d’exceptions d’accès aux données

Non vérifiée (runtime), DataAccessException en est l’exception parent

Les classes de support d’accès aux données de Spring permettent

d’encapsuler l’exception technique dans une DataAccessException

SQLException avec code erreur ORA-1722 en

DataIntegrityViolationException

Page 5: Workshop spring   session 2 - La persistance au sein des applications Java

# 5

Quelques exceptions

DataIntegrityViolationException : utilisée lorsqu’une violation de contrainte

d'intégrité est détectée par la base (ex : contrainte d’unicité, clé étrangère)

DataAccessResourceFailureException : problème de connexion à la base

de données

ConcurrencyFailureException : fait suite à un problème de concurrence

d’accès aux données (verrou pessimiste ou optimiste)

DeadlockLoserDataAccessException : signale que le processus est bloqué

par un verrou

DataRetrievalFailureException : erreur produite lors d’une requête de

sélection (ex: l’objet n’existe pas ou plus)

Page 6: Workshop spring   session 2 - La persistance au sein des applications Java

# 6

Source de données

Possibilité Cas d’utilisation Exemple de déclaration

Pool de connexions

par JNDI

• Application web déployée dans un serveur d’application

<jee:jndi-lookup

id="dataSource"

jndi-name="jdbc/DemoDataSource"/>

Pool de connexionsembarqué

• Application standalone

<bean id="dataSource"

class="org.apache.commons.dbcp

.BasicDataSource"

destroy-method="close"

p:driverClassName="${db.driver}"

p:username="{db.user}" ... />

Connexionunique à la

base

• Tests unitaires • Batchs

<bean id="dataSource"

class="org.springframework.jdbc

.datasource.SingleConnectionDataSource"

p:suppress-close="true"

p:driverClassName="${db.driver}"

p:username="{db.user}" ... />

Page 7: Workshop spring   session 2 - La persistance au sein des applications Java

# 7

Hiérarchie d’exceptionsDataAccessException

NonTransientDataAccessException RecoverableDataAccessException TransientDataAccessException

ConcurrencyFailureException TransientDataAccessResourceExceptionDataIntegrityViolationException PermissionDeniedDataAccessException

OptimisticLockingFailureExceptionPessimisticLockingFailureException

ObjectOptimisticLockingFailureExceptionCannotAcquireLockException

DuplicateKeyException DataRetrievalFailureException

IncorrectResultSizeDataAccessExceptionObjectRetrievalFailureException

Page 8: Workshop spring   session 2 - La persistance au sein des applications Java

# 8

Template Method Pattern

Squelette d’un algorithme à l’aide d’opérations abstraites

Permet de masquer le code technique générique

Le développeur se concentre sur la requête et l’extraction du résultat

SQL pour JDC, HQL ou Criteria pour Hibernate …

JdbcOperations StatementCallbackDAO

result

result

execute (callback)

doInStatement (statement)

Exécute la requêteRécupère le résultat

Récupère la connexionPrépare le statement

Gère les exceptionsFerme le statementLibère la connexion

Page 9: Workshop spring   session 2 - La persistance au sein des applications Java

# 9

Support de JDBC

JdbcTemplate template = new JdbcTemplate(dataSource);

String sql = "select count(*) from client";

int nombreClient = template.queryForInt(sql);

sql = "select * from client";

RowMapper<Client> rowMapper =

ParameterizedBeanPropertyRowMapper.newInstance(Client.class);

List<Client> clients = template.query(sql, rowMapper);

sql = "insert into client (id, nom, prenom) VALUES (?, ?, ?)";

template.update(sql, client.getId(), client.getNom(),

client.getPrenom());

Les classes JdbcTemplate et NamedParameterJdbcTemplate

centralisent toute la puissance du support JDBC de Spring.

Remarque: la classe SimpleJdbcTemplate est dépréciée depuis Spring 3 au profitdes 2 classes citées.

Page 10: Workshop spring   session 2 - La persistance au sein des applications Java

# 10

Support des ORM

Solutions ORM supportées par Spring 4 :

JPA 2.1

Hibernate 3.6 et 4.x

JDO 2.x

Cohérence des classes de support de ces différentes technologies

Création et configuration de l’EntityManagerFactory / SessionFactory

Gestion du cycle de vie des EntityManager / sessions Hibernate

Synchronise l’ouverture d’une transaction et la création d’une session

Page 11: Workshop spring   session 2 - La persistance au sein des applications Java

# 11

Parallèles entre solutions

Concept JDBC Hibernate JPA

Resource Connection Session EntityManager

Resource factory DataSource SessionFactory EntityManagerFactory

Exception SQLException HibernateException PersistenceException

Classe de support

JDBC Hibernate JPA

Template class JdbcTemplate HibernateTemplate JpaTemplate

DAO support JdbcDaoSupport HibernateDaoSupport JpaDaoSupport

Transaction DataSourceTransactionManager

HibernateTransactionManager

JpaTransactionManager

Classes principales des différentes API d’accès aux données

Classes de support de Spring pour les différentes API d’accès aux données

Légende : à éviter pour les nouveaux projets. Préférez l’API native d’Hibernatesupprimer de Spring 4.x

Page 12: Workshop spring   session 2 - La persistance au sein des applications Java

# 12

Exemples de DAO@Repository

public class JpaClientDAO extends JpaDaoSupport implements IClientDAO {

public List<Client> findByNom1(String nom) {

return getJpaTemplate().findByNamedQuery("Client.findByNom", nom);

}

public List<Client> findByNom2(String nom) {

String query = “select c from Client c where c.nom = ?1";

return getJpaTemplate().find(query, nom);

}

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

@Repository

public class JpaClientDAO implements ICompteDAO {

@PersistenceContext

private EntityManager entityManager;

public List<Client> findAll() {

return entityManager.createQuery("from Client").getResultList();

}

Requête nommée définie sur l’entité Client parl’annotation @NamedQuery

Requête dynamique JPQL

Injection par Spring du contexte persistant JPA

Exemple valide en Spring 3.x maispas en 4.X suite à la suppression des 2 classes de support

Page 13: Workshop spring   session 2 - La persistance au sein des applications Java

# 13

Encore plus loin

Le projet Spring Data JPA simplifie l’écriture de la couche d’accès aux données

Continuation du projet Hades

Apporte le support pour une approche Domain Driven Developpment (DDD)

Retour à la vraie conception objet

Tout en conservant la séparation entre le fonctionnel et la technique

Utilise le pattern Repository

Manipule uniquement des objets du domaine métier (entités)

Comparé à une interface d’accès à une collection d’objets du domaine

Ne nécessite aucune implémentation : le code est généré par le framework

Fonctions CRUD disponibles en standard : save, findById, count, exists …

Page 14: Workshop spring   session 2 - La persistance au sein des applications Java

# 14

Toujours plus loin

Implémentation dynamique des requêtes à partir du nom de la méthode

S’appuie sur des conventions de nommage

Interprète les mots clés : And, Or, Like, OrderBy, NotIn, Between …

Ajout possible de requêtes personnalisées avec leur implémentation

Gestion de la pagination et du tri

Suivi de la création et de la modification des entités (dates et utilisateurs)

Les Spécifications permettent de réutiliser des Criterias JPA 2

Support de la librairie QueryDSL pour requêter des entités

de manière typesafe

avec une syntaxe épurée et fluide

Page 15: Workshop spring   session 2 - La persistance au sein des applications Java

# 15

Exemple de JpaRepository// Repository de l’entité Client dont l’identifiant est un entier

public interface ClientRepository extends JpaRepository<Client, Integer> {

// Recherche par nom de clients

List<Client> findByNom(String nom);

// Recherche effectuée à partir du solde es comptes des clients

List<Client> findByComptesSoldeGreaterThan(Double montant);

// Recherche paginée et ordonnée

Page<Client> findByPrenom(String prenom, Pageable pageable);

// Utilisation de la requête JPQL spécifiée

@Query("select count(c) from Client c where u.prenom=?1")

Long countWithPrenom(String prenom);

}

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:jpa="http://www.springframework.org/schema/data/jpa" … >

<!– Détecte et active tous les Repository du package spécifié -->

<jpa:repositories base-package="fr.sqli.bfa.demo.repository" />

</beans>

Page 16: Workshop spring   session 2 - La persistance au sein des applications Java

# 16

Query DSL en Action

// Interface héritant de JpaRepository et QueryDslPredicateExecutor

@Autowired

QueryDslJpaRepository<User, Integer> repository;

...

// Méta-modèle de l'entité Client généré à partir des annotations JPA

// Référence les propriétés et les associations d’un client

QClient client = QClient.client;

// Création de prédicats réutilisables

BooleanExpression majeur = client.age.gt(18);

BooleanExpression sousTutelle = client.tuteur.isNotNull();

// Exécution de requêtes type-safe

// - utilisant des prédicats

List<Client> sousResponsabilites = repository.findAll(majeur.or(sousTutelle));

Integer nombreParisiens = repository.count(client.ville.like("paris"));

// - écrites "naturellement" avec Query DSL

JPAQuery query = new JPAQuery(em);

List<Client> clients =

query.from(client).join(client.addresses).fetch().list(client);

Integer maxSolde = query.from(client).uniqueResult(client.solde.max());

Page 17: Workshop spring   session 2 - La persistance au sein des applications Java

# 17

Support des transactions

API générique pour la gestion des transactions

Transparence sur la nature d’une transaction (locale ou globale)

Intégration aux différentes technologies :

JDBC, Hibernate, JPA, JMS, JCA, XA

Différentes approches pour la démarcation des transactions

Par programmation

En AOP

Par annotations

Permet d’utiliser le service transactionnel des serveurs JEE

Page 18: Workshop spring   session 2 - La persistance au sein des applications Java

# 18

Les attributs transactionnels

Propagation des transactions

Niveau d’isolation

Conditions de rollback

Optimisations sur les transactions en lecture-seule

Time-out

Gestionnaire de transaction

Page 19: Workshop spring   session 2 - La persistance au sein des applications Java

# 19

Exemples de propagation

MANDATORY : la méthode doit forcément être exécutée au sein d’un

contexte transactionnel. Si tel n’est pas le cas, une exception est levée.

REQUIRED : la méthode doit forcément être exécutée dans un

contexte transactionnel. S’il n’existe pas lors de l’appel, il est créé.

PROPAGATION_REQUIRES_NEW

Client Service DAO

sans TX

TX1

TX1

TX2

Page 20: Workshop spring   session 2 - La persistance au sein des applications Java

# 20

Démarcation par annotations

L’annotation @Transactional permet de déclarer des transactions

Sur une classe ou une interface

l’interface est à privilégier

toutes les méthodes en bénéficient

Sur une méthode

modifie le comportement défini au niveau de la classe

L’annotation @Transactional s’hérite, ce qui permet de :

Bénéficier du comportement transactionnel d’une classe parent

Modifier le comportement d’une classe ou d’une méthode redéfinie

Par défaut, Spring crée un proxy transactionnel à partir de l’interface

Attention aux appels directs de méthode sans passer par le bean

Page 21: Workshop spring   session 2 - La persistance au sein des applications Java

# 21

@Transactional par l’exemple

<!-- Active la détection des annotations @Transactional -->

<tx:annotation-driven />

@Transactional(rollbackFor=BusinessException.class)

public interface IBanqueService {

void effectuerVirement(Compte compteSrc, Compte compteDest,

BigDecimal montant) throws SommeIndisponibleException;

@Transactional(readOnly=true)

List<Client> rechercherClient(Criteres criteres);

@Transactional(timeout=30000, Propagation=Propagation.REQUIRES_NEW)

void crediter(Compte compte, BigDecimal montant);

}

Page 22: Workshop spring   session 2 - La persistance au sein des applications Java

# 22

Annotation versus AOP

Tableau comparant l’utilisation de l’annotation @Transactional et de

fichier XML pour définir des aspects

Annotation AOP

Avantages + Compilation+ Productivité

+ Indépendance envers Spring+ Configuration centralisée+ Tissage statique possible

Inconvénients - Couplage fort- Pollution du code

- Lisibilité- Validation à l’exécution- Refactoring délicat- Certaine rigueur nécessaire