SlideShare una empresa de Scribd logo
1 de 96
2013-11-15

Spring Data - 20131114

1
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

2
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

3
Spring Data - Introduction
⦿Utilité du pattern DAO ?
⦿Hétérogénéité des bases de données

2013-11-15

Spring Data - 20131114

4
Spring Data - Introduction
⦿Module Spring
⦿Son but :
⦿Faciliter l’écriture des couches d’accès aux
données
⦿Tenter d’offrir une abstraction commune pour
l’accès aux données quelques soient les sources
de données sous-jacentes, tout en prenant en
compte les spécificités de celles-ci

⦿Sources de données : JPA, Neo4j, MongoDB,
GemFire, Hadoop, ElasticSearch, REST, Redis, Couchbase, …
2013-11-15

Spring Data - 20131114

5
Spring Data
API de manipulation de
la source de données
(JPA, Neo4j, MongoDB,
etc.)

Manipule

Spring Data

Source de
données

2013-11-15

Spring Data – 20131114

6
Spring Data

Spring Data JPA

Spring Data
Neo4j

Spring Data
MongoDB

Spring Data
Gemfire

Spring Data Commons

2013-11-15

Spring Data – 20131114

7
Spring Data
⦿Utilisé sur un projet chez SFR
⦿Motivations

2013-11-15

Spring Data - 20131114

8
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

9
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

10
Spring Data JPA
⦿Spring Data JPA offre une couche
d’abstraction supplémentaire par rapport à
JPA
⦿Se charge de l'implémentation des
fonctionnalités les plus courantes des DAO
⦿On se concentre sur l’essentiel : l’écriture des
requêtes

2013-11-15

Spring Data - 20131114 - sdjpabase

11
Spring Data JPA
Manipule

JPA

Spring Data

Se base sur
Hibernate

EclipseLink

…

JDBC

BDD
2013-11-15

Spring Data - 20131114 - sdjpabase

12
Spring Data JPA
⦿Pour l'intégrer, il suffit d'ajouter une
dépendance dans Maven :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>

2013-11-15

Spring Data - 20131114 - sdjpabase

13
Spring Data JPA
⦿Principe de base
⦿Pour écrire le DAO pour un type d’entités, il
faut étendre certaines interfaces fournies par
Spring Data :
public interface PersonneDao extends CrudRepository<Personne, Long> {
}

Nom de l'entité qu'on manipule
Type de l'identifiant de l'entité

2013-11-15

Spring Data - 20131114 - sdjpabase

14
Spring Data JPA
⦿Les différentes interfaces :
⦿Repository : vous ne ferez pas grand-chose avec,
hormis les méthodes que vous ajouterez
⦿CrudRepository : vous aurez des fonctionnalités
CRUD de base
⦿PagingAndSortingRepository : vous aurez en plus
des méthodes pour la pagination et le tri
⦿JpaRepository : vous aurez en plus des méthodes
propres à JPA
2013-11-15

Spring Data - 20131114 - sdjpabase

15
Spring Data JPA
Spring Data Commons

Repository

CrudRepository

PagingAndSortingRepository

JpaRepository

Pas de méthode

save(S), findOne(ID), exists(), findAll(), deleteAll(), …

findAll(Sort), findAll(Pageable)

flush(), saveAndFlush(T), deleteInBatch(Iterable<T>), …
Spring Data JPA

2013-11-15

Spring Data - 20131114 - sdjpabase

16
Spring Data JPA
⦿ CrudRepository :
public interface PersonneDao extends CrudRepository<Personne, Long> {}
public class PersonneDaoTest {
@Autowired
private PersonneDao personneDao;
public void setup() {
personneDao.deleteAll();
}
public void testSave() { …
Personne personneSauvee = personneDao.save(personne);
…}
public void testCrudDao() {…
Assert.assertEquals(1, personneDao.count());
Assert.assertEquals(true, personneDao.exists(personneSauvee.getId()));
for (Personne personneDeLaListe : personneDao.findAll()) {…}
Personne personneTrouvee = personneDao.findOne(personneSauvee.getId());
personneDao.delete(personneSauvee);
Assert.assertEquals(0, personneDao.count());…
}

2013-11-15

Spring Data - 20131114 - sdjpabase

17
Spring Data JPA
⦿ PagingAndSortingRepository :
public interface PersonnePaginationDao extends PagingAndSortingRepository<Personne, Long>{}

public class PersonnePaginationDaoTest {
private PersonnePaginationDao personnePaginationDao;
public void testTriDesc(){…
Iterable<Personne> personnesTrouvees =
personnePaginationDao.findAll(new Sort(Sort.Direction.DESC, "nom"));
…}
public void testPagination() {
Assert.assertEquals(10, personnePaginationDao.count());
Page<Personne> personnes =
personnePaginationDao.findAll(new PageRequest(1, 3));
Assert.assertEquals(1, personnes.getNumber());
Assert.assertEquals(3, personnes.getSize()); // la taille de la pagination
Assert.assertEquals(10, personnes.getTotalElements()); //nb total d'éléments récupérables
Assert.assertEquals(4, personnes.getTotalPages()); // nombre de pages
Assert.assertTrue(personnes.hasContent());
…}
}

2013-11-15

Spring Data - 20131114 - sdjpabase

18
Spring Data JPA
⦿Vous pouvez filtrer les méthodes que vous
voulez être utilisables : il suffit de les copier
dans votre interface qui étendra l'interface
Spring la plus restrictive
⦿Par exemple, pour n'avoir que les méthodes
findOne et save :
interface MyBaseRepository<T, ID extends Serializable>
extends Repository<T, ID> {
T findOne(ID id);
T save(T entity);
}

2013-11-15

Spring Data - 20131114 - sdjpabase

19
Spring Data JPA
⦿ Vous pouvez aussi écrire une requête juste avec le nom de la méthode
⦿ Exemple :
public interface RequetesPersonnaliseesDao
extends CrudRepository<Personne, Long> {
public Personne findByNom(String nom);
public Personne findByNomOrPrenom(String nom,
String prenom);
public Personne findByVelo(Velo velo);
public Personne findByVeloAndNom(Velo velo, String nom);
…}
List<Person> findDistinctPeopleByLastnameOrFirstname(String
lastname, String firstname);
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String
lastname, String firstname);
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);

2013-11-15

Spring Data - 20131114 - sdjpabase

20
Spring Data JPA
Logique

GreaterThan, IsGreaterThan

IN

In, IsIn

IS

Is, Equals, (or no keyword)

IS_NOT_NULL

NotNull, IsNotNull

IS_NULL

Null, IsNull

LESS_THAN

LessThan, IsLessThan

LIKE

Like, IsLike

NOT

Not, IsNot
NotIn, IsNotIn

NOT_LIKE

NotLike, IsNotLike

REGEX

Regex, MatchesRegex,
Matches

…
2013-11-15

GREATER_THAN

NOT_IN

⦿Il existe une série
de mots-clés pour
écrire sa requête
(cf. annexe de la
documentation de
référence)

Mot-clé Spring Data

…

Spring Data - 20131114 - sdjpabase

21
Spring Data JPA
⦿Spring va créer une requête à partir des
propriétés et des mots-clés mentionnés dans le
nom de la méthode
⦿Si on fait une recherche à partir d’une « souspropriété », on donne à Spring le chemin vers
celle-ci. Exemple : Si Person a une propriété
Address qui a une propriété ZipCode, on peut
faire :
List<Person>
findByAddressZipCode(ZipCode zipCode);
2013-11-15

Spring Data - 20131114 - sdjpabase

22
Spring Data JPA
⦿S’il y a ambiguïté dans les propriétés, on peut
mettre un « _ ». Exemple :
Si la classe Person a un attribut addressZip et un
autre address (de type Address qui contient
ZipCode) :
List<Person>
findByAddress_ZipCode(ZipCode
zipCode);

2013-11-15

Spring Data - 20131114 - sdjpabase

23
Spring Data JPA
⦿Certains types de Spring sont
automatiquement reconnus. Du coup, on
peut ajouter des paramètres de pagination et
de tri :
Page<User> findByLastname(String
lastname, Pageable pageable);
List<User> findByLastname(String
lastname, Sort sort);
List<User> findByLastname(String
lastname, Pageable pageable);

2013-11-15

Spring Data - 20131114 - sdjpabase

24
Spring Data JPA
⦿Exemple :
public interface RequetesPersonnaliseesDao
extends CrudRepository<Personne, Long> {
public List<Personne> findByNomStartingWith(String nom,
Sort ordreTri);
}
public void testRecuperationParNomEtTri() {
String baseNom = "aaa";
// sauvegarde des personnes avec pour nom : "baseNom"+i, avec i={0, 1, 2, 3}
final List<Personne> listePersonnes =
this.requetesPersonnaliseesDao.findByNomStartingWith(baseNom,
new Sort(Direction.DESC, "nom"));
for (Personne personne : listePersonnes)
{ System.out.println(personne.getNom()); }
}

Affiche : aaa3, aaa2, aaa1, aaa0

2013-11-15

Spring Data - 20131114 - sdjpabase

25
Spring Data JPA
⦿Requêtes nommées :
⦿On peut les mettre dans le META-INF/orm.xml ou en
annotations dans l’entité
⦿Exemple :
@Entity
@NamedQuery(name = "User.findByEmailAddress",
query = "select u from User u where u.emailAddress = ?1")
public class User { …
}

⦿Et dans le répository, on ne fait que déclarer la méthode :
public interface UserRepository
extends JpaRepository<User, Long> {
User findByEmailAddress(String emailAddress);
}

2013-11-15

Spring Data - 20131114 - sdjpabase

26
Spring Data JPA
⦿ Vous pouvez aussi ajouter l’annotation @Query si vos noms
de méthodes sont beaucoup trop longues
⦿ Exemple :
@Query("from Personne p where p.nom = ?1 and p.prenom = ?2")
public Personne
maRequêteAvecQueryDeRechercheParNomEtPrenom(String nom,
String prenom);

⦿ Ca marche aussi avec les requêtes de modification, pour
lesquelles il faut l’annotation @Modifying :
@Query("update Personne p set p.nom = :nom where p.id = :id")
@Modifying
public int metAJourNom(@Param("nom")String nom,
@Param("id") Long id);

⦿ On peut nommer les paramètres avec @Param

2013-11-15

Spring Data - 20131114 - sdjpabase

27
Spring Data JPA
⦿On peut mettre plusieurs arguments que
Spring comprendra en fonction de leur
déclaration dans la méthode
@Query("from Personne p where p.nom = ?1 and p.prenom = ?2")
public Personne maRequêteAvecQueryDeRechercheParNomEtPrenom(String
nom, String prenom);

⦿@Query prend l’ascendant sur les requêtes
nommées

2013-11-15

Spring Data - 20131114 - sdjpabase

28
Spring Data JPA
⦿Que ce soit pour @Query ou @NamedQuery,
on peut mettre du code SQL natif
(respectivement avec l’attribut nativeQuery
et @NamedNativeQuery)

2013-11-15

Spring Data - 20131114 - sdjpabase

29
Spring Data JPA
⦿3 stratégies pour dire à Spring comment
récupérer les requêtes :
⦿CREATE : à partir des noms des méthodes
⦿USE_DECLARED_QUERY : annotations, requêtes
nommées ou tout autre moyen propre à la
source de données sous-jacente
⦿CREATE_IF_NOT_FOUND : recherche d’abord une
requête associée, puis crée la requête à partir du
nom de la méthode

⦿Déclaré dans la configuration Spring
2013-11-15

Spring Data - 20131114 - sdjpabase

30
Spring Data JPA
⦿ Comment configurer Spring Data JPA avec Hibernate et H2 :
<!-- Déclaration des paquetages contenant les DAO -->
<jpa:repositories base-package="fr.soat.springdata.jpa.dao" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- <property name="persistenceUnitName" value="spring-jpa" /> utile si
on a un persistence.xml -->
<property name="packagesToScan" value="fr.soat.springdata.jpa.entites" /> <!-- pour se débarasser du
persistence.xml -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="database" value="H2" />
</bean>
</property>
</bean>

<jdbc:embedded-database id="dataSource" type="H2" />

2013-11-15

Spring Data - 20131114 - sdjpabase

31
Spring Data JPA
⦿La balise <repositories /> existe pour chaque
module de Spring Data
⦿Spring scanne les paquetages mentionnés à la
recherche de Repository
⦿Pour chaque interface trouvée, Spring va créer le
FactoryBean qui va construire le proxy qui va
traiter les appels
⦿Spring active la récupération des exceptions
levées par la source de données et les convertit
en DataAccessException
2013-11-15

Spring Data - 20131114 - sdjpabase

32
Spring Data JPA
⦿Les requêtes personnalisées
⦿2 possibilités :
⦿Soit vous voulez écrire une méthode
personnalisée pour tous les DAO
⦿Soit vous voulez juste ajouter une méthode
personnalisée pour un DAO

2013-11-15

Spring Data - 20131114 - sdjpabase

33
Spring Data JPA
⦿
Ajouter une méthode personnalisée
pour tous les DAO
⦿
L’applicationContext.xml devra être
modifié :
<jpa:repositories
base-package="fr.soat.springdata.jpa.dao"
factory-class=
"fr.soat.springdata.jpa.dao.personnalisees.tous.DaoCommunAuxAutresD
aoFactoryBean"
/>

2013-11-15

Spring Data - 20131114 - sdjpabase

34
Spring Data JPA
⦿
Ajouter une méthode personnalisée pour
tous les DAO
⦿ FactoryBean devra être créé :
Un
public class DaoCommunAuxAutresDaoFactoryBean<R extends JpaRepository<T, I>, T, I
extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
@Override
protected RepositoryFactorySupport createRepositoryFactory(final
EntityManager entityManager) {
// dans JpaRepositoryFactoryBean, on ne fait que renvoyer un
JpaRepositoryFactory
return new DaoCommunAuxAutresDaoFactory<T, I>(entityManager);
}
…

2013-11-15

Spring Data - 20131114 - sdjpabase

35
Spring Data JPA
⦿Ajouter une méthode personnalisée pour tous les DAO
⦿Un FactoryBean devra être créé (2) :
…
private static class DaoCommunAuxAutresDaoFactory<T, I extends Serializable> extends
JpaRepositoryFactory {
private EntityManager entityManager;
public DaoCommunAuxAutresDaoFactory(final EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
@Override
@SuppressWarnings("unchecked")
protected Object getTargetRepository(final RepositoryMetadata metadata) {
// dans JpaRepositoryFactory, on renvoyait un SimpleJpaRepository
return new DaoCommunAuxAutresDaoImpl<T, I>((Class<T>) metadata.getDomainType(),
this.entityManager);
}
@Override
protected Class<?> getRepositoryBaseClass(final RepositoryMetadata metadata) {
/* On peut ignorer metadata qui sert à JpaRepositoryFactory */
return DaoCommunAuxAutresDao.class;
// dans JpaRepositoryFactory, on renvoyait soit un SimpleJpaRepository.class soit
un QueryDslJpaRepository.class
}}}

2013-11-15

Spring Data - 20131114 - sdjpabase

36
Spring Data JPA
⦿
Ajouter une méthode personnalisée
pour tous les DAO
⦿
L’interface qui devra être étendue
par tous les autres Repository :
@NoRepositoryBean
public interface DaoCommunAuxAutresDao<T, ID extends Serializable>
extends JpaRepository<T, ID>{
List<T>
uneMethodeDeRechercheCommuneATousLesDaoParLExemple(T exemple);
}

2013-11-15

Spring Data - 20131114 - sdjpabase

37
Spring Data JPA
⦿Ajouter une méthode personnalisée pour tous les DAO
⦿La classe implémentant l’interface commune à tous les
DAO :
public class DaoCommunAuxAutresDaoImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
implements DaoCommunAuxAutresDao<T, ID> {
private EntityManager entityManager;
public DaoCommunAuxAutresDaoImpl(final Class<T> domainClass, final EntityManager entityManager) {
super(domainClass, entityManager);
this.entityManager = entityManager;
}
@Override
public List<T> uneMethodeDeRechercheCommuneATousLesDaoParLExemple(final T exemple) {
Session session = (Session) this.entityManager.getDelegate();
Example hibernateExample = Example.create(exemple).ignoreCase().enableLike(MatchMode.ANYWHERE);
Criteria criteria = session.createCriteria(exemple.getClass()).add(hibernateExample);
return criteria.list();
}
}

2013-11-15

Spring Data - 20131114 - sdjpabase

38
Spring Data JPA
⦿
Ajouter une méthode personnalisée
pour tous les DAO
⦿ Repository quelconque :
Un
public interface AutrePersonneDao
extends DaoCommunAuxAutresDao<Personne, Long>{}

2013-11-15

Spring Data - 20131114 - sdjpabase

39
Spring Data JPA
⦿Ajouter une méthode personnalisée pour tous les DAO
⦿La classe de test :
@ContextConfiguration("classpath:applicationContext_daoCommun.xml")…
public class PersonneDaoPersonnaliseeBaseImplTest {
@Autowired
private AutrePersonneDao autrePersonneDao;
@Test
public void test() {
List<Personne> personnesTrouvees =
this.autrePersonneDao.uneMethodeDeRechercheCommuneATousLesDaoPa
rLExemple(this.personneSauvee);
}
}

2013-11-15

Spring Data - 20131114 - sdjpabase

40
Spring Data JPA (QueryDsl)
⦿ Parenthèse sur QueryDsl
⦿ QueryDsl est un outil ayant le même but que l'API Criteria (écriture des requêtes avec
vérification lors de la compilation), mais qui rend les requêtes plus parlantes
⦿ Criteria :
CriteriaQuery query = builder.createQuery(); Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
builder.equal( men.get( Person_.gender ), Gender.MALE ),
builder.equal( men.get( Person_.relationshipStatus ),RelationshipStatus.SINGLE ));
Predicate womenRestriction = builder.and(
builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
builder.equal( women.get( Person_.relationshipStatus ),RelationshipStatus.SINGLE ));
query.where( builder.and( menRestriction, womenRestriction ) );

⦿ QueryDsl :
JPAQuery query = new JPAQuery(em);
QPerson men = new QPerson("men");
QPerson women = new QPerson("women");
query.from(men, women).where(
men.gender.eq(Gender.MALE),
men.relationshipStatus.eq(RelationshipStatus.SINGLE),
women.gender.eq(Gender.FEMALE),
women.relationshipStatus.eq(RelationshipStatus.SINGLE));

2013-11-15

Spring Data - 20131114 - sdjpabase

41
Spring Data JPA
⦿Ajouter une méthode personnalisée à un
DAO
⦿Il faut une interface qui va contenir la
méthode personnalisée :
public interface PersonneDaoAvecMethodePersonnalisee {
public List<Personne>
uneMethodePersonnaliseeDeRechercheParNom(String nom);
}

2013-11-15

Spring Data - 20131114 - sdjpabase

42
Spring Data JPA
⦿Ajouter une méthode personnalisée à un DAO
⦿Il faut ensuite une classe implémentant l’interface
(nom = nom de l’interface + "Impl", configurable) :
public class PersonneDaoPersonnaliseeRepositoryImpl implements
PersonneDaoAvecMethodePersonnalisee {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Personne>
uneMethodePersonnaliseeDeRechercheParNom(String nom) {
return this.entityManager.createQuery("from Personne p where
p.nom = ?1").setParameter(1, nom).getResultList(); }
}

2013-11-15

Spring Data - 20131114 - sdjpabase

43
Spring Data JPA
⦿Ajouter une méthode personnalisée à un
DAO
⦿On termine en créant l’interface DAO qui sera
utilisée et à qui on va adjoindre la méthode
personnalisée :
public interface PersonneDaoPersonnaliseeRepository
extends CrudRepository<Personne, Long>,
PersonneDaoAvecMethodePersonnalisee {}

2013-11-15

Spring Data - 20131114 - sdjpabase

44
Spring Data JPA
⦿Ajouter une méthode personnalisée à un DAO
⦿La classe utilisatrice :
public class PersonneDaoPersonnaliseeRepositoryTest {
@Autowired
private PersonneDaoPersonnaliseeRepository
personneDaoPersonnaliseeRepository;
…
@Test
public void test() {
List<Personne> personneList =
this.personneDaoPersonnaliseeRepository.uneMethodePersonnaliseeDeRecherc
heParNom(this.personneSauvee.getNom());
}
}

2013-11-15

Spring Data - 20131114 - sdjpabase

45
Spring Data JPA
⦿Comment bénéficier de l'avantage de l'API
Criteria (vérification des requêtes à la
compilation) ?
⦿Utiliser des Specification
⦿Intégrer QueryDsl

⦿Inspiré des concepts du Domain Driven Design
⦿Plus d'informations ici :
http://spring.io/blog/2011/04/26/advancedspring-data-jpa-specifications-and-querydsl
2013-11-15

Spring Data - 20131114 - sdjpabase

46
Spring Data JPA
⦿Principe de l'utilisation des Specification
⦿Créer un objet qui implémente l'interface
Specification
⦿Le DAO étend en plus , JpaSpecificationExecutor
⦿Mettre le ou une combinaison de Specification
en paramètre des méthodes classiques de Spring
Data

2013-11-15

Spring Data - 20131114 - sdjpabase

47
Spring Data JPA
⦿ Exemple d'utilisation des Specification
1. On crée des objets Specification :
public CustomerSpecifications {
public static Specification<Customer> customerHasBirthday() {
return new Specification<Customer> {
public Predicate toPredicate(Root<T> root, CriteriaQuery query,
CriteriaBuilder cb) {
return cb.equal(root.get(Customer_.birthday), today);
}
};
}
public static Specification<Customer> isLongTermCustomer() {
return new Specification<Customer> {
public Predicate toPredicate(Root<T> root, CriteriaQuery query,
CriteriaBuilder cb) {
return cb.lessThan(root.get(Customer_.createdAt), new
LocalDate.minusYears(2));
}
};
}
}

2013-11-15

Spring Data - 20131114 - sdjpabase

48
Spring Data JPA
⦿Exemple d'utilisation des Specification
2. Notre DAO étend en plus
JpaSpecificationExecutor :
public interface CustomerRepository extends JpaRepository<Customer>,
JpaSpecificationExecutor {}

3. Le client peut ensuite les utiliser :
customerRepository.findAll(hasBirthday());
customerRepository.findAll(isLongTermCustomer());
customerRepository.findAll(where(customerHasBirthday()).and(isLongTermCu
stomer()));

2013-11-15

Spring Data - 20131114 - sdjpabase

49
Spring Data JPA
⦿Principe de l'utilisation de QueryDsl
⦿On inclut le plugin Maven de QueryDsl
⦿Le DAO étend en plus QueryDslPredicateExecutor

2013-11-15

Spring Data - 20131114 - sdjpabase

50
Spring Data JPA
⦿Exemple d'utilisation de QueryDsl
1. Notre DAO étend en plus
JpaSpecificationExecutor :
public interface CustomerRepository extends JpaRepository<Customer>,
QueryDslPredicateExecutor {
}

2. Le client peut ensuite les utiliser :
BooleanExpression customerHasBirthday = customer.birthday.eq(today);
BooleanExpression isLongTermCustomer =
customer.createdAt.lt(today.minusYears(2));
customerRepository.findAll(customerHasBirthday.and(isLongTermCustomer));

2013-11-15

Spring Data - 20131114 - sdjpabase

51
Spring Data JPA
⦿Les transactions :
⦿Toutes les méthodes pour récupérer des données
sont en readOnly=true. Les autres sont en
@Transactional(donc readOnly= false)
⦿@Transactional est configurable (timeout, readOnly,
…)
⦿Pour qu’une suite d’opérations soient dans la même
transaction, il suffit de mettre @Transactional dans
la méthode englobante. Il faudra ajouter
<tx:annotation-driven /> dans la configuration
2013-11-15

Spring Data - 20131114 - sdjpabase

52
Spring Data JPA
⦿L’intégration de Spring Data avec Spring MVC
⦿Offre quelques facilités :
⦿Récupération automatique des entités
⦿Pagination

2013-11-15

Spring Data – 20131114 - sdjpawebapp

53
Spring Data JPA
⦿ La récupération automatique des entités
⦿ Avant, on était obligé, à partir de l’identifiant, de récupérer les entités de la base
de données :
@Controller
@RequestMapping("/welcome/")
public class HelloController {
@RequestMapping("/voir/{id}")
public String voirVelo(@PathVariable("id") final Long id,
final Model modele) {
Velo veloTrouve = this.veloDao.findOne(id);
modele.addAttribute("message", "Modèle de vélo : " +
veloTrouve.getModele());
return "basique/fiche";
}
}
⦿ C’est très fastidieux

2013-11-15

Spring Data - 20131114 - sdjpawebapp

54
Spring Data JPA
⦿ Avec Spring Data, si on met directement en paramètre une
entité, celle-ci sera chargée automatiquement :
@Controller
@RequestMapping("/sdtouch/")
public class ControleurUnPeuMieuxAvecSD {
@RequestMapping("/voir/{id}")
public String
voirVelo(@PathVariable("id") final Velo veloTrouve,
final Model modele) {
modele.addAttribute("message",
"Modèle de vélo : " + veloTrouve.getModele());
return "sdtouch/fiche";

}
}

2013-11-15

Spring Data - 20131114 - sdjpawebapp

55
Spring Data JPA
⦿ Pour cela, il faut modifier un peu le dispatcherServletservlet.xml pour y ajouter un convertisseur :
<mvc:annotation-driven conversion-service="conversionService" />
<!-- Nécessaire pour la conversion String (id) vers une entité
récupéré par Spring Data (avec findOne()) -->
<bean class=
"org.springframework.data.repository.support.DomainClassConverter">
<!-- on va ajouter DomainClassConverter à la liste des
converters de conversionService -->
<constructor-arg ref="conversionService" />
</bean>
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean"
/>

2013-11-15

Spring Data - 20131114 - sdjpawebapp

56
Spring Data JPA
⦿Pour la pagination, il faut récupérer les
paramètres de la requête HTTP pour récupérer
la page à afficher et la taille de la page :
@RequestMapping(value="/{page}/{pageSize}", method =
RequestMethod.GET)
public String printWelcome(final Model modele,
@PathVariable("page") final int page,
@PathVariable("pageSize") final int pageSize) {
Pageable pageable = new PageRequest(page, pageSize);
Page<Velo> resultat = this.veloDao.findAll(pageable);
return "basique/hello";
}

2013-11-15

Spring Data - 20131114 - sdjpawebapp

57
Spring Data JPA
⦿Spring Data améliore un peu la chose :
@RequestMapping(method = RequestMethod.GET)
public String printWelcome(final Model modele,
@PageableDefaults(pageNumber = 0, value = 2)final Pageable
pageable) {
final Page<Velo> resultatRecherche =
this.veloDao.findAll(pageable);
modele.addAttribute("velosTrouves",
resultatRecherche.getContent());
modele.addAttribute("pagination", resultatRecherche);
return "sdtouch/hello";
}

2013-11-15

Spring Data - 20131114 - sdjpawebapp

58
Spring Data JPA
⦿Comment s’opère la magie de Spring Data
(attention, spoiler) ?

2013-11-15

Spring Data – 20131114 - proxylab

59
Spring Data JPA
⦿Comment s’opère la magie de Spring Data ?
⦿Chargement des requêtes au chargement :
⦿Scanne les paquetages mentionnés dans l’applicationContext.xml
⦿Quand Spring trouve un repository, JpaRepositoryFactory va
créer un SimpleJpaRepository qui implémente JpaRepository
⦿Il met ensuite cet objet dans un Proxy
⦿Juste avant, il va associer à ce proxy un intercepteur de méthode
qui permet la résolution des requêtes personnalisées, nommées,
avec @Query, etc. Donc à ce stade, les requêtes sont résolues et
en cache

⦿Appel des méthodes des interfaces
⦿Quand une de ces méthodes est appelée, c’est en réalité le proxy
qui est appelé
⦿Celui-ci va appeler la méthode correspondante de l’objet
SimpleJpaRepository qu’on lui a donné au chargement
2013-11-15

Spring Data - 20131114 - proxylab

60
Spring Data JPA
⦿Comment s’opère la magie de Spring Data ?
Exemple.
⦿"Spring" :
public void injecteDansClient(final Client client) {
UnDao dao = (UnDao)
Proxy.newProxyInstance(Thread.currentThread().
getContextClassLoader(),
new Class[] { UnDao.class },
new ProxyInjecte());
client.setDao(dao);
}

2013-11-15

Spring Data - 20131114 - proxylab

61
Spring Data JPA
⦿Comment s’opère la magie de Spring Data ? Exemple.
⦿L'InvocationHandler :
class ProxyInjecte implements InvocationHandler {
private ClasseNonAppeleeParClient classeNonAppeleeParClient =
new ClasseNonAppeleeParClient();
public Object invoke(final Object proxy,
final Method method,
final Object[] args)
throws Throwable {
if (method.getName().equals("bambiFaitDodo")) {
this.classeNonAppeleeParClient.bambiFaitDodo();
} else if (method.getName().equals("atchoum")) {
this.classeNonAppeleeParClient.atchoum();
}
return null;
}
}

2013-11-15

Spring Data - 20131114 - proxylab

62
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

63
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

64
Spring Data Neo4j
⦿Neo4j : une base de données orientée graphe
⦿Cas d'utilisation typique : les réseaux sociaux
⦿Spring Data Neo4j apporte un niveau
d’abstraction supplémentaire à la
manipulation des graphes

2013-11-15

Spring Data - 20131114

65
Spring Data Neo4j
⦿ Neo4j quelques commandes de base
⦿ Démarrage d’une base Neo4j en mémoire :
public class Neo4jMain {
private final static String DB_PATH = "bdd_neo4j";
public static void main(String[] args) {
GraphDatabaseService graphDb =
new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
registerShutdownHook(graphDb);
}
private static void registerShutdownHook(final GraphDatabaseService graphDb) {
/* Pour que Neo4j s'arrête correctement, même en cas de Ctrl-C */
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
graphDb.shutdown();
}
} );
}}

2013-11-15

Spring Data – 20131114 - neo4jbasique

66
Spring Data Neo4j
⦿ Neo4j quelques commandes de base
⦿ Pour créer le graphe, qu’avec des noeuds :
Transaction tx = this.graphDb.beginTx();
try {
this.acteur = this.graphDb.createNode();
this.acteur.setProperty("nom", "Diesel");
this.acteur.setProperty("prenom", "Vin");
Node noeudFilm = this.graphDb.createNode();
noeudFilm.setProperty(Film.TITRE, "Rapides et dangereux");
this.acteur.createRelationshipTo(noeudFilm, JOUE_DANS);
noeudFilm = this.graphDb.createNode();// on utilise les noeuds
noeudFilm.setProperty(Film.TITRE, "Trop rapide et trop pas content");
this.acteur.createRelationshipTo(noeudFilm, JOUE_DANS);
tx.success();
} finally {
tx.finish();
}

2013-11-15

Spring Data – 20131114 - neo4jbasique

67
Spring Data Neo4j
⦿Neo4j quelques commandes de base
⦿Pour créer le graphe, en essayant d’utiliser des beans :
Transaction tx = this.graphDb.beginTx();
try {…
Film film = new Film(this.graphDb.createNode());
film.setTitre("Il faut sauver le soldat Ryan");
this.acteur.createRelationshipTo(film.getNoeud(),
JOUE_DANS);
tx.success();
} finally {
tx.finish();
}

2013-11-15

Spring Data – 20131114 - neo4jbasique

68
Spring Data Neo4j
⦿ Neo4j quelques commandes de base
⦿ Et dans le bean Film, on a :
public class Film {
public static final String TITRE = "TITRE";
private Node noeud;
public Film(Node noeud) { this.noeud = noeud; }
public Node getNoeud() { return this.noeud; }
public String getTitre() {
return (String) this.noeud.getProperty(TITRE);
}
public void setTitre(String nom) { this.noeud.setProperty(TITRE,
nom); }
}

⦿ La relation doit étendre RelationshipType :
public enum JoueDansRelationEnum implements RelationshipType {
JOUE_DANS;
}

2013-11-15

Spring Data – 20131114 - neo4jbasique

69
Spring Data Neo4j
⦿ Neo4j quelques commandes de base
⦿ Pour afficher le contenu du graphe, on peut utiliser un « Traverser » :
public void afficheGraphe() {
Traverser traverseurDeFilms = getTraverseursFilms();
for (Path path : traverseurDeFilms) {
if (path.length() == 0) {
System.out.println(path.endNode().getProperty("nom") +
" a joué dans les films suivants :");
} else {
System.out.println(path.endNode().getProperty(Film.TITRE));
}
}}
private Traverser getTraverseursFilms() {
TraversalDescription td =
Traversal.description().
breadthFirst().
relationships(JOUE_DANS).
evaluator(Evaluators.all());
return td.traverse(this.acteur);
}

2013-11-15

Spring Data – 20131114 - neo4jbasique

70
Spring Data Neo4j
⦿ Neo4j quelques commandes de base
⦿ Neo4j a son langage de « requêtage », le Cypher :
public void exempleCypher() {
String requete = "start n=node("+this.acteur.getId()+") " +
"match n-[:JOUE_DANS]->films " +
"where films." + Film.TITRE + " =~ 'Trop.*' " +
"return n, n.nom, n.prenom, films." + Film.TITRE;
ExecutionResult result = this.engine.execute(requete);
String rows = "";
for ( Map<String, Object> row : result) {
for ( Entry<String, Object> column : row.entrySet() ) {
rows += column.getKey() + ": " + column.getValue() + "; ";
}
rows += "n";
}
System.out.println(rows);
}

⦿ Affiche : n: Node[13]; n.nom: Diesel; films.TITRE: Trop rapide et trop pas
content; n.prenom: Vin;
2013-11-15

Spring Data – 20131114 - neo4jbasique

71
Spring Data Neo4j
⦿Ce qu’apporte Spring Data Neo4j
⦿Les nœuds deviennent des beans Java classiques.
Pareil pour les relations
⦿Les opérations de base peuvent se faire à partir
des interfaces
⦿Une bonne partie des opérations valables pour
JPA sont valables pour Neo4j

2013-11-15

Spring Data – 20131114 - sdneo4jbase

72
Spring Data Neo4j
⦿S'inclut avec une dépendance Maven :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-aspects</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>

2013-11-15

Spring Data – 20131114 - sdneo4jbase

73
Spring Data Neo4j
⦿Un exemple de nœud Spring Data Neo4j :
@NodeEntity
public class Acteur {
@GraphId
private Long idNoeud;
@Indexed(indexType =
IndexType.FULLTEXT,
indexName="nom")
private String nom;
private String prenom;

public void aJoueDans(Film film) {
this.films.add(film);
}

@RelatedTo(direction=Direction.
BOTH, type="aJoueDans")
private Set<Film> films;
@RelatedToVia
private Set<Realisation>
realisations;
// getters et setters classiques
2013-11-15

public Realisation aRealise(Film
film) {
Realisation realisation =
new Realisation();
realisation.setActeur(this);
realisation.setFilm(film);
realisations.add(realisation);
return realisation;
}

Spring Data – 20131114 - sdneo4jbase

74
Spring Data Neo4j
⦿Les relations deviennent aussi des beans Java
classiques :

@RelationshipEntity(type="aRealise")
public class Realisation {
@GraphId
private Long id;

private Calendar dateRealisation;
@StartNode
private Acteur acteur;
@EndNode
private Film film;
// getters et setters classiques
2013-11-15

Spring Data – 20131114 - sdneo4jbase

75
Spring Data Neo4j
⦿Les DAO sont toujours aussi minimalistes :
public interface ActeurDao extends GraphRepository<Acteur> {
@Query("start acteur=node({0}) " +
"match acteur-[:aRealise]->film " +
"return film")
Iterable<Film> recupereMoiTousLesFilmsRealisesPar(Acteur
acteur);
}

2013-11-15

Spring Data – 20131114 - sdneo4jbase

76
Spring Data Neo4j
⦿L'utilisation s'en trouve simplifiée :
public void setup() {
this.acteurDao.deleteAll();
Acteur vinDiesel = new Acteur();
vinDiesel.setNom("Diesel");
vinDiesel.setPrenom("Vin");
vinDiesel.aJoueDans(leFilm("Strays"));
vinDiesel.aJoueDans(leFilm("Il faut sauver le soldat Ryan"));
vinDiesel.aJoueDans(leFilm("Les Initiés"));
final Film multiFacial = leFilm("Multi-Facial");
this.filmDao.save(multiFacial);
vinDiesel.aRealise(multiFacial).en(1994);
this.acteurDao.save(vinDiesel);
}
2013-11-15

Spring Data – 20131114 - sdneo4jbase

77
Spring Data Neo4j
⦿D'autres exemples d'utilisation :
EndResult<Film> filmsTrouves = this.filmDao.findAll();
EndResult<Film> filmsTrouves =
this.filmDao.findAllByPropertyValue("titre", "Strays");
Film filmTrouve = this.filmDao.findByPropertyValue("titre", "Les Initiés");
Iterable<Film> filmsTrouves = this.filmDao.findByTitreContaining("Il");
Acteur vinDiesel = this.acteurDao.findOne(identifiantVinDiesel);
final Iterable<Film> filmsTrouves =
this.acteurDao.recupereMoiTousLesFilmsRealisesPar(vinDiesel);

2013-11-15

Spring Data – 20131114 - sdneo4jbase

78
Spring Data Neo4j
⦿On peut aussi utiliser les Traversers :
final Acteur vinDiesel =
this.acteurDao.findOne(this.identifiantVinDiesel);
TraversalDescription traversalDescription =
Traversal.description().
breadthFirst().
evaluator(Evaluators.atDepth(1));
final Iterable<Film> filmsJouesParVinDiesel =
this.filmDao.findAllByTraversal(vinDiesel,
traversalDescription);

2013-11-15

Spring Data – 20131114 - sdneo4jbase

79
Spring Data Neo4j
⦿L'applicationContext.xml :
<neo4j:repositories
base-package="fr.soat.springdata.neo4j.sdneo4jbase.dao" />
<neo4j:config storeDirectory="data/bdd_neo4j" />

2013-11-15

Spring Data – 20131114 - sdneo4jbase

80
Spring Data Neo4j
⦿La hiérarchie des interfaces Spring Data :
findAllByTraver
TraversalRepository sal

PagingAndSortingRepository

CRUDRepository

save(U),
findOne(Long),
findAll(),…

IndexRepository

findAllByQuery
findAllByRange
…

GraphRepository

2013-11-15

Spring Data – 20131114 - sdneo4jbase

81
Spring Data JPA
Spring Data Commons

Repository

CrudRepository

PagingAndSortingRepository

JpaRepository

Pas de méthode

save(S), findOne(ID), exists(), findAll(), deleteAll(), …

findAll(Sort), findAll(Pageable)

flush(), saveAndFlush(T), deleteInBatch(Iterable<T>), …
Spring Data JPA

2013-11-15

Spring Data - 20131114 - sdjpabase

82
Spring Data Neo4j
⦿D'autres interfaces sont disponibles, comme
CypherDslRepository pour exécuter du
CypherDsl, SpatialRepository pour les
requêtes spatiales

2013-11-15

Spring Data – 20131114 - sdneo4jbase

83
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

84
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

85
Spring Data REST
⦿Spring Data REST simplifie l’exposition des
services REST
⦿Pour offrir un service REST, il suffit :
⦿De dire qu’on utilise Spring Data REST pour une
source de données particulière (JPA, Neo4j,
MongoDB, etc.)
⦿D’étendre une des interfaces de Spring Data
⦿De dire où se situent ces interfaces d’export
⦿De… non, c’est tout

2013-11-15

Spring Data – 20131114 - sdrestws

86
Spring Data REST
Spring Data REST WebMVC

Spring MVC

Spring Data JPA

Spring Data
Neo4j

Spring Data
MongoDB

Spring Data Commons

2013-11-15

Spring Data – 20131114 - sdjpabase

87
Spring Data REST
⦿ Dans le pom.xml :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
… et les dépendances vers H2 et Hibernate

2013-11-15

Spring Data - 20131114 - sdrestws

88
Spring Data REST
⦿Un brin de folie, le DAO a une annotation à
lui :
@RestResource(path="chanson") //pour personnaliser un peu la façon dont le
service web est appelé
public interface ChansonDao extends CrudRepository<Chanson, Long> {
}

⦿Le bean Chanson :
@Entity
public class Chanson {
@Id
private Long id;
private String titre;…}

2013-11-15

Spring Data - 20131114 - sdrestws

89
Spring Data REST
⦿Utilisation :
mvn clean install jetty:run lance Jetty et le fait écouter sur le port 8080
curl -H "Content-Type: application/json" -d '{"titre":"Get
Lucky","id":"2"}' http://localhost:8080/chanson
curl -v http://localhost:8080/chanson/2
Renvoie :
{
"links" : [ {
"rel" : "self";
"href" : "http://localhost:8080/chanson/2"
} ],
"titre" : "Get Lucky"
}

2013-11-15

Spring Data - 20131114 - sdrestws

90
Spring Data REST
⦿Limites de Spring Data REST

2013-11-15

Spring Data - 20131114 - sdrestws

91
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

92
Spring Data
⦿Introduction
⦿Spring Data JPA
⦿Spring Data Neo4j
⦿Spring Data Rest
⦿Aperçu de Spring Data MongoDB

2013-11-15

Spring Data - 20131114

93
Spring Data MongoDb
⦿ Aperçu de Spring Data MongoDB
⦿ On a un bean :
@Document(collection = "menu") // annotations pas nécessaires
public class MenuItem {
@Id private String id;
@Field("itemName") @Indexed private String name;
}

⦿ Le répository associé
public interface MenuItemRepository
extends CrudRepository<MenuItem, String> {
public List<MenuItem> findByIngredientsNameIn(String... name);
}

⦿ Un exemple d'utilisation
menuItemRepository.save(eggFriedRice());
List<MenuItem> peanutItems
menuItemRepository.findByIngredientsNameIn("Peanuts");

2013-11-15

Spring Data - 20131114

94
Spring Data - conclusion
⦿Pour aller plus loin :
⦿Le site de Spring Data :
http://projects.spring.io/spring-data/
⦿Le livre sur Spring Data :
⦿http://shop.oreilly.com/product/0636920024767.do
⦿Et ses exemples : https://github.com/springprojects/spring-data-book

⦿Le livre sur Spring Data Neo4j : Good Relationships
The Spring Data Neo4j Guide Book
⦿Mes exemples :
⦿https://github.com/xeter/soirees3t

2013-11-15

Spring Data - 20131114

95
Spring Data

2013-11-15

Spring Data - 20131114

96

Más contenido relacionado

La actualidad más candente

Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)
Eric SIBER
 
Presentation Spring, Spring MVC
Presentation Spring, Spring MVCPresentation Spring, Spring MVC
Presentation Spring, Spring MVC
Nathaniel Richand
 

La actualidad más candente (20)

Cours design pattern m youssfi partie 1 introduction et pattern strategy
Cours design pattern m youssfi partie 1 introduction et pattern strategyCours design pattern m youssfi partie 1 introduction et pattern strategy
Cours design pattern m youssfi partie 1 introduction et pattern strategy
 
Architecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependancesArchitecture jee principe de inversion de controle et injection des dependances
Architecture jee principe de inversion de controle et injection des dependances
 
Sécurité des Applications Web avec Json Web Token (JWT)
Sécurité des Applications Web avec Json Web Token (JWT)Sécurité des Applications Web avec Json Web Token (JWT)
Sécurité des Applications Web avec Json Web Token (JWT)
 
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...Mohamed youssfi support architectures logicielles distribuées basées sue les ...
Mohamed youssfi support architectures logicielles distribuées basées sue les ...
 
Spring mvc
Spring mvcSpring mvc
Spring mvc
 
Support Web Services SOAP et RESTful Mr YOUSSFI
Support Web Services SOAP et RESTful Mr YOUSSFISupport Web Services SOAP et RESTful Mr YOUSSFI
Support Web Services SOAP et RESTful Mr YOUSSFI
 
Maven et industrialisation du logiciel
Maven et industrialisation du logicielMaven et industrialisation du logiciel
Maven et industrialisation du logiciel
 
Angular
AngularAngular
Angular
 
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014Formation JPA Avancé / Hibernate gratuite par Ippon 2014
Formation JPA Avancé / Hibernate gratuite par Ippon 2014
 
Microservices avec Spring Cloud
Microservices avec Spring CloudMicroservices avec Spring Cloud
Microservices avec Spring Cloud
 
Support de cours technologie et application m.youssfi
Support de cours technologie et application m.youssfiSupport de cours technologie et application m.youssfi
Support de cours technologie et application m.youssfi
 
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka StreamsTraitement distribue en BIg Data - KAFKA Broker and Kafka Streams
Traitement distribue en BIg Data - KAFKA Broker and Kafka Streams
 
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...Support de cours EJB 3 version complète Par Mr  Youssfi, ENSET, Université Ha...
Support de cours EJB 3 version complète Par Mr Youssfi, ENSET, Université Ha...
 
Support de cours angular
Support de cours angularSupport de cours angular
Support de cours angular
 
Introduction à Symfony
Introduction à SymfonyIntroduction à Symfony
Introduction à Symfony
 
Maven
MavenMaven
Maven
 
Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)Support programmation orientée aspect mohamed youssfi (aop)
Support programmation orientée aspect mohamed youssfi (aop)
 
Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)
 
Presentation Spring, Spring MVC
Presentation Spring, Spring MVCPresentation Spring, Spring MVC
Presentation Spring, Spring MVC
 
Appalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPAppalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSP
 

Similar a Présentation spring data Matthieu Briend

Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -introNosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Olivier Mallassi
 

Similar a Présentation spring data Matthieu Briend (16)

[FR] Introduction à Spring Data Neo4j 3.x
[FR] Introduction à Spring Data Neo4j 3.x[FR] Introduction à Spring Data Neo4j 3.x
[FR] Introduction à Spring Data Neo4j 3.x
 
Android ORMLite
Android   ORMLiteAndroid   ORMLite
Android ORMLite
 
Spring data
Spring dataSpring data
Spring data
 
20150402 meetup r addicts du printemps
20150402  meetup r addicts du printemps20150402  meetup r addicts du printemps
20150402 meetup r addicts du printemps
 
Modèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueModèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratique
 
Sudoc, Calames, theses.fr et le Web de données
Sudoc, Calames, theses.fr et le Web de donnéesSudoc, Calames, theses.fr et le Web de données
Sudoc, Calames, theses.fr et le Web de données
 
Hibernate
HibernateHibernate
Hibernate
 
Datamapper L Orm Dans Rails 3
Datamapper L Orm Dans Rails 3Datamapper L Orm Dans Rails 3
Datamapper L Orm Dans Rails 3
 
Spark (v1.3) - Présentation (Français)
Spark (v1.3) - Présentation (Français)Spark (v1.3) - Présentation (Français)
Spark (v1.3) - Présentation (Français)
 
Springioc
SpringiocSpringioc
Springioc
 
Presentation JPA
Presentation JPAPresentation JPA
Presentation JPA
 
Hello mongo
Hello mongoHello mongo
Hello mongo
 
Spark - Alexis Seigneurin (Français)
Spark - Alexis Seigneurin (Français)Spark - Alexis Seigneurin (Français)
Spark - Alexis Seigneurin (Français)
 
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -introNosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
Nosql, hadoop, map reduce, hbase, sqoop, voldemort, cassandra -intro
 
Programmation Android - 09 - Web services
Programmation Android - 09 - Web servicesProgrammation Android - 09 - Web services
Programmation Android - 09 - Web services
 
Open data & linked data
Open data & linked dataOpen data & linked data
Open data & linked data
 

Más de SOAT

20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat
SOAT
 

Más de SOAT (20)

Back from Microsoft //Build 2018
Back from Microsoft //Build 2018Back from Microsoft //Build 2018
Back from Microsoft //Build 2018
 
L'entreprise libérée
L'entreprise libéréeL'entreprise libérée
L'entreprise libérée
 
Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !
 
JAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseJAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entreprise
 
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUESARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
 
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
 
1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-Durand1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-Durand
 
2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-Durand2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-Durand
 
Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido
 
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu ParisotDans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
 
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
 
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
 
Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014
 
20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat
 
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
 
Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014
 
ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)
 
Xamarin et le développement natif d’applications Android, iOS et Windows en C#
 Xamarin et le développement natif d’applications Android, iOS et Windows en C# Xamarin et le développement natif d’applications Android, iOS et Windows en C#
Xamarin et le développement natif d’applications Android, iOS et Windows en C#
 
A la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - SoatA la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - Soat
 
MongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de donnéesMongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de données
 

Présentation spring data Matthieu Briend

  • 2. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 2
  • 3. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 3
  • 4. Spring Data - Introduction ⦿Utilité du pattern DAO ? ⦿Hétérogénéité des bases de données 2013-11-15 Spring Data - 20131114 4
  • 5. Spring Data - Introduction ⦿Module Spring ⦿Son but : ⦿Faciliter l’écriture des couches d’accès aux données ⦿Tenter d’offrir une abstraction commune pour l’accès aux données quelques soient les sources de données sous-jacentes, tout en prenant en compte les spécificités de celles-ci ⦿Sources de données : JPA, Neo4j, MongoDB, GemFire, Hadoop, ElasticSearch, REST, Redis, Couchbase, … 2013-11-15 Spring Data - 20131114 5
  • 6. Spring Data API de manipulation de la source de données (JPA, Neo4j, MongoDB, etc.) Manipule Spring Data Source de données 2013-11-15 Spring Data – 20131114 6
  • 7. Spring Data Spring Data JPA Spring Data Neo4j Spring Data MongoDB Spring Data Gemfire Spring Data Commons 2013-11-15 Spring Data – 20131114 7
  • 8. Spring Data ⦿Utilisé sur un projet chez SFR ⦿Motivations 2013-11-15 Spring Data - 20131114 8
  • 9. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 9
  • 10. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 10
  • 11. Spring Data JPA ⦿Spring Data JPA offre une couche d’abstraction supplémentaire par rapport à JPA ⦿Se charge de l'implémentation des fonctionnalités les plus courantes des DAO ⦿On se concentre sur l’essentiel : l’écriture des requêtes 2013-11-15 Spring Data - 20131114 - sdjpabase 11
  • 12. Spring Data JPA Manipule JPA Spring Data Se base sur Hibernate EclipseLink … JDBC BDD 2013-11-15 Spring Data - 20131114 - sdjpabase 12
  • 13. Spring Data JPA ⦿Pour l'intégrer, il suffit d'ajouter une dépendance dans Maven : <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.2.0.RELEASE</version> </dependency> 2013-11-15 Spring Data - 20131114 - sdjpabase 13
  • 14. Spring Data JPA ⦿Principe de base ⦿Pour écrire le DAO pour un type d’entités, il faut étendre certaines interfaces fournies par Spring Data : public interface PersonneDao extends CrudRepository<Personne, Long> { } Nom de l'entité qu'on manipule Type de l'identifiant de l'entité 2013-11-15 Spring Data - 20131114 - sdjpabase 14
  • 15. Spring Data JPA ⦿Les différentes interfaces : ⦿Repository : vous ne ferez pas grand-chose avec, hormis les méthodes que vous ajouterez ⦿CrudRepository : vous aurez des fonctionnalités CRUD de base ⦿PagingAndSortingRepository : vous aurez en plus des méthodes pour la pagination et le tri ⦿JpaRepository : vous aurez en plus des méthodes propres à JPA 2013-11-15 Spring Data - 20131114 - sdjpabase 15
  • 16. Spring Data JPA Spring Data Commons Repository CrudRepository PagingAndSortingRepository JpaRepository Pas de méthode save(S), findOne(ID), exists(), findAll(), deleteAll(), … findAll(Sort), findAll(Pageable) flush(), saveAndFlush(T), deleteInBatch(Iterable<T>), … Spring Data JPA 2013-11-15 Spring Data - 20131114 - sdjpabase 16
  • 17. Spring Data JPA ⦿ CrudRepository : public interface PersonneDao extends CrudRepository<Personne, Long> {} public class PersonneDaoTest { @Autowired private PersonneDao personneDao; public void setup() { personneDao.deleteAll(); } public void testSave() { … Personne personneSauvee = personneDao.save(personne); …} public void testCrudDao() {… Assert.assertEquals(1, personneDao.count()); Assert.assertEquals(true, personneDao.exists(personneSauvee.getId())); for (Personne personneDeLaListe : personneDao.findAll()) {…} Personne personneTrouvee = personneDao.findOne(personneSauvee.getId()); personneDao.delete(personneSauvee); Assert.assertEquals(0, personneDao.count());… } 2013-11-15 Spring Data - 20131114 - sdjpabase 17
  • 18. Spring Data JPA ⦿ PagingAndSortingRepository : public interface PersonnePaginationDao extends PagingAndSortingRepository<Personne, Long>{} public class PersonnePaginationDaoTest { private PersonnePaginationDao personnePaginationDao; public void testTriDesc(){… Iterable<Personne> personnesTrouvees = personnePaginationDao.findAll(new Sort(Sort.Direction.DESC, "nom")); …} public void testPagination() { Assert.assertEquals(10, personnePaginationDao.count()); Page<Personne> personnes = personnePaginationDao.findAll(new PageRequest(1, 3)); Assert.assertEquals(1, personnes.getNumber()); Assert.assertEquals(3, personnes.getSize()); // la taille de la pagination Assert.assertEquals(10, personnes.getTotalElements()); //nb total d'éléments récupérables Assert.assertEquals(4, personnes.getTotalPages()); // nombre de pages Assert.assertTrue(personnes.hasContent()); …} } 2013-11-15 Spring Data - 20131114 - sdjpabase 18
  • 19. Spring Data JPA ⦿Vous pouvez filtrer les méthodes que vous voulez être utilisables : il suffit de les copier dans votre interface qui étendra l'interface Spring la plus restrictive ⦿Par exemple, pour n'avoir que les méthodes findOne et save : interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> { T findOne(ID id); T save(T entity); } 2013-11-15 Spring Data - 20131114 - sdjpabase 19
  • 20. Spring Data JPA ⦿ Vous pouvez aussi écrire une requête juste avec le nom de la méthode ⦿ Exemple : public interface RequetesPersonnaliseesDao extends CrudRepository<Personne, Long> { public Personne findByNom(String nom); public Personne findByNomOrPrenom(String nom, String prenom); public Personne findByVelo(Velo velo); public Personne findByVeloAndNom(Velo velo, String nom); …} List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); List<Person> findByLastnameOrderByFirstnameAsc(String lastname); 2013-11-15 Spring Data - 20131114 - sdjpabase 20
  • 21. Spring Data JPA Logique GreaterThan, IsGreaterThan IN In, IsIn IS Is, Equals, (or no keyword) IS_NOT_NULL NotNull, IsNotNull IS_NULL Null, IsNull LESS_THAN LessThan, IsLessThan LIKE Like, IsLike NOT Not, IsNot NotIn, IsNotIn NOT_LIKE NotLike, IsNotLike REGEX Regex, MatchesRegex, Matches … 2013-11-15 GREATER_THAN NOT_IN ⦿Il existe une série de mots-clés pour écrire sa requête (cf. annexe de la documentation de référence) Mot-clé Spring Data … Spring Data - 20131114 - sdjpabase 21
  • 22. Spring Data JPA ⦿Spring va créer une requête à partir des propriétés et des mots-clés mentionnés dans le nom de la méthode ⦿Si on fait une recherche à partir d’une « souspropriété », on donne à Spring le chemin vers celle-ci. Exemple : Si Person a une propriété Address qui a une propriété ZipCode, on peut faire : List<Person> findByAddressZipCode(ZipCode zipCode); 2013-11-15 Spring Data - 20131114 - sdjpabase 22
  • 23. Spring Data JPA ⦿S’il y a ambiguïté dans les propriétés, on peut mettre un « _ ». Exemple : Si la classe Person a un attribut addressZip et un autre address (de type Address qui contient ZipCode) : List<Person> findByAddress_ZipCode(ZipCode zipCode); 2013-11-15 Spring Data - 20131114 - sdjpabase 23
  • 24. Spring Data JPA ⦿Certains types de Spring sont automatiquement reconnus. Du coup, on peut ajouter des paramètres de pagination et de tri : Page<User> findByLastname(String lastname, Pageable pageable); List<User> findByLastname(String lastname, Sort sort); List<User> findByLastname(String lastname, Pageable pageable); 2013-11-15 Spring Data - 20131114 - sdjpabase 24
  • 25. Spring Data JPA ⦿Exemple : public interface RequetesPersonnaliseesDao extends CrudRepository<Personne, Long> { public List<Personne> findByNomStartingWith(String nom, Sort ordreTri); } public void testRecuperationParNomEtTri() { String baseNom = "aaa"; // sauvegarde des personnes avec pour nom : "baseNom"+i, avec i={0, 1, 2, 3} final List<Personne> listePersonnes = this.requetesPersonnaliseesDao.findByNomStartingWith(baseNom, new Sort(Direction.DESC, "nom")); for (Personne personne : listePersonnes) { System.out.println(personne.getNom()); } } Affiche : aaa3, aaa2, aaa1, aaa0 2013-11-15 Spring Data - 20131114 - sdjpabase 25
  • 26. Spring Data JPA ⦿Requêtes nommées : ⦿On peut les mettre dans le META-INF/orm.xml ou en annotations dans l’entité ⦿Exemple : @Entity @NamedQuery(name = "User.findByEmailAddress", query = "select u from User u where u.emailAddress = ?1") public class User { … } ⦿Et dans le répository, on ne fait que déclarer la méthode : public interface UserRepository extends JpaRepository<User, Long> { User findByEmailAddress(String emailAddress); } 2013-11-15 Spring Data - 20131114 - sdjpabase 26
  • 27. Spring Data JPA ⦿ Vous pouvez aussi ajouter l’annotation @Query si vos noms de méthodes sont beaucoup trop longues ⦿ Exemple : @Query("from Personne p where p.nom = ?1 and p.prenom = ?2") public Personne maRequêteAvecQueryDeRechercheParNomEtPrenom(String nom, String prenom); ⦿ Ca marche aussi avec les requêtes de modification, pour lesquelles il faut l’annotation @Modifying : @Query("update Personne p set p.nom = :nom where p.id = :id") @Modifying public int metAJourNom(@Param("nom")String nom, @Param("id") Long id); ⦿ On peut nommer les paramètres avec @Param 2013-11-15 Spring Data - 20131114 - sdjpabase 27
  • 28. Spring Data JPA ⦿On peut mettre plusieurs arguments que Spring comprendra en fonction de leur déclaration dans la méthode @Query("from Personne p where p.nom = ?1 and p.prenom = ?2") public Personne maRequêteAvecQueryDeRechercheParNomEtPrenom(String nom, String prenom); ⦿@Query prend l’ascendant sur les requêtes nommées 2013-11-15 Spring Data - 20131114 - sdjpabase 28
  • 29. Spring Data JPA ⦿Que ce soit pour @Query ou @NamedQuery, on peut mettre du code SQL natif (respectivement avec l’attribut nativeQuery et @NamedNativeQuery) 2013-11-15 Spring Data - 20131114 - sdjpabase 29
  • 30. Spring Data JPA ⦿3 stratégies pour dire à Spring comment récupérer les requêtes : ⦿CREATE : à partir des noms des méthodes ⦿USE_DECLARED_QUERY : annotations, requêtes nommées ou tout autre moyen propre à la source de données sous-jacente ⦿CREATE_IF_NOT_FOUND : recherche d’abord une requête associée, puis crée la requête à partir du nom de la méthode ⦿Déclaré dans la configuration Spring 2013-11-15 Spring Data - 20131114 - sdjpabase 30
  • 31. Spring Data JPA ⦿ Comment configurer Spring Data JPA avec Hibernate et H2 : <!-- Déclaration des paquetages contenant les DAO --> <jpa:repositories base-package="fr.soat.springdata.jpa.dao" /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- <property name="persistenceUnitName" value="spring-jpa" /> utile si on a un persistence.xml --> <property name="packagesToScan" value="fr.soat.springdata.jpa.entites" /> <!-- pour se débarasser du persistence.xml --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> <property name="generateDdl" value="true" /> <property name="database" value="H2" /> </bean> </property> </bean> <jdbc:embedded-database id="dataSource" type="H2" /> 2013-11-15 Spring Data - 20131114 - sdjpabase 31
  • 32. Spring Data JPA ⦿La balise <repositories /> existe pour chaque module de Spring Data ⦿Spring scanne les paquetages mentionnés à la recherche de Repository ⦿Pour chaque interface trouvée, Spring va créer le FactoryBean qui va construire le proxy qui va traiter les appels ⦿Spring active la récupération des exceptions levées par la source de données et les convertit en DataAccessException 2013-11-15 Spring Data - 20131114 - sdjpabase 32
  • 33. Spring Data JPA ⦿Les requêtes personnalisées ⦿2 possibilités : ⦿Soit vous voulez écrire une méthode personnalisée pour tous les DAO ⦿Soit vous voulez juste ajouter une méthode personnalisée pour un DAO 2013-11-15 Spring Data - 20131114 - sdjpabase 33
  • 34. Spring Data JPA ⦿ Ajouter une méthode personnalisée pour tous les DAO ⦿ L’applicationContext.xml devra être modifié : <jpa:repositories base-package="fr.soat.springdata.jpa.dao" factory-class= "fr.soat.springdata.jpa.dao.personnalisees.tous.DaoCommunAuxAutresD aoFactoryBean" /> 2013-11-15 Spring Data - 20131114 - sdjpabase 34
  • 35. Spring Data JPA ⦿ Ajouter une méthode personnalisée pour tous les DAO ⦿ FactoryBean devra être créé : Un public class DaoCommunAuxAutresDaoFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> { @Override protected RepositoryFactorySupport createRepositoryFactory(final EntityManager entityManager) { // dans JpaRepositoryFactoryBean, on ne fait que renvoyer un JpaRepositoryFactory return new DaoCommunAuxAutresDaoFactory<T, I>(entityManager); } … 2013-11-15 Spring Data - 20131114 - sdjpabase 35
  • 36. Spring Data JPA ⦿Ajouter une méthode personnalisée pour tous les DAO ⦿Un FactoryBean devra être créé (2) : … private static class DaoCommunAuxAutresDaoFactory<T, I extends Serializable> extends JpaRepositoryFactory { private EntityManager entityManager; public DaoCommunAuxAutresDaoFactory(final EntityManager entityManager) { super(entityManager); this.entityManager = entityManager; } @Override @SuppressWarnings("unchecked") protected Object getTargetRepository(final RepositoryMetadata metadata) { // dans JpaRepositoryFactory, on renvoyait un SimpleJpaRepository return new DaoCommunAuxAutresDaoImpl<T, I>((Class<T>) metadata.getDomainType(), this.entityManager); } @Override protected Class<?> getRepositoryBaseClass(final RepositoryMetadata metadata) { /* On peut ignorer metadata qui sert à JpaRepositoryFactory */ return DaoCommunAuxAutresDao.class; // dans JpaRepositoryFactory, on renvoyait soit un SimpleJpaRepository.class soit un QueryDslJpaRepository.class }}} 2013-11-15 Spring Data - 20131114 - sdjpabase 36
  • 37. Spring Data JPA ⦿ Ajouter une méthode personnalisée pour tous les DAO ⦿ L’interface qui devra être étendue par tous les autres Repository : @NoRepositoryBean public interface DaoCommunAuxAutresDao<T, ID extends Serializable> extends JpaRepository<T, ID>{ List<T> uneMethodeDeRechercheCommuneATousLesDaoParLExemple(T exemple); } 2013-11-15 Spring Data - 20131114 - sdjpabase 37
  • 38. Spring Data JPA ⦿Ajouter une méthode personnalisée pour tous les DAO ⦿La classe implémentant l’interface commune à tous les DAO : public class DaoCommunAuxAutresDaoImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements DaoCommunAuxAutresDao<T, ID> { private EntityManager entityManager; public DaoCommunAuxAutresDaoImpl(final Class<T> domainClass, final EntityManager entityManager) { super(domainClass, entityManager); this.entityManager = entityManager; } @Override public List<T> uneMethodeDeRechercheCommuneATousLesDaoParLExemple(final T exemple) { Session session = (Session) this.entityManager.getDelegate(); Example hibernateExample = Example.create(exemple).ignoreCase().enableLike(MatchMode.ANYWHERE); Criteria criteria = session.createCriteria(exemple.getClass()).add(hibernateExample); return criteria.list(); } } 2013-11-15 Spring Data - 20131114 - sdjpabase 38
  • 39. Spring Data JPA ⦿ Ajouter une méthode personnalisée pour tous les DAO ⦿ Repository quelconque : Un public interface AutrePersonneDao extends DaoCommunAuxAutresDao<Personne, Long>{} 2013-11-15 Spring Data - 20131114 - sdjpabase 39
  • 40. Spring Data JPA ⦿Ajouter une méthode personnalisée pour tous les DAO ⦿La classe de test : @ContextConfiguration("classpath:applicationContext_daoCommun.xml")… public class PersonneDaoPersonnaliseeBaseImplTest { @Autowired private AutrePersonneDao autrePersonneDao; @Test public void test() { List<Personne> personnesTrouvees = this.autrePersonneDao.uneMethodeDeRechercheCommuneATousLesDaoPa rLExemple(this.personneSauvee); } } 2013-11-15 Spring Data - 20131114 - sdjpabase 40
  • 41. Spring Data JPA (QueryDsl) ⦿ Parenthèse sur QueryDsl ⦿ QueryDsl est un outil ayant le même but que l'API Criteria (écriture des requêtes avec vérification lors de la compilation), mais qui rend les requêtes plus parlantes ⦿ Criteria : CriteriaQuery query = builder.createQuery(); Root<Person> men = query.from( Person.class ); Root<Person> women = query.from( Person.class ); Predicate menRestriction = builder.and( builder.equal( men.get( Person_.gender ), Gender.MALE ), builder.equal( men.get( Person_.relationshipStatus ),RelationshipStatus.SINGLE )); Predicate womenRestriction = builder.and( builder.equal( women.get( Person_.gender ), Gender.FEMALE ), builder.equal( women.get( Person_.relationshipStatus ),RelationshipStatus.SINGLE )); query.where( builder.and( menRestriction, womenRestriction ) ); ⦿ QueryDsl : JPAQuery query = new JPAQuery(em); QPerson men = new QPerson("men"); QPerson women = new QPerson("women"); query.from(men, women).where( men.gender.eq(Gender.MALE), men.relationshipStatus.eq(RelationshipStatus.SINGLE), women.gender.eq(Gender.FEMALE), women.relationshipStatus.eq(RelationshipStatus.SINGLE)); 2013-11-15 Spring Data - 20131114 - sdjpabase 41
  • 42. Spring Data JPA ⦿Ajouter une méthode personnalisée à un DAO ⦿Il faut une interface qui va contenir la méthode personnalisée : public interface PersonneDaoAvecMethodePersonnalisee { public List<Personne> uneMethodePersonnaliseeDeRechercheParNom(String nom); } 2013-11-15 Spring Data - 20131114 - sdjpabase 42
  • 43. Spring Data JPA ⦿Ajouter une méthode personnalisée à un DAO ⦿Il faut ensuite une classe implémentant l’interface (nom = nom de l’interface + "Impl", configurable) : public class PersonneDaoPersonnaliseeRepositoryImpl implements PersonneDaoAvecMethodePersonnalisee { @PersistenceContext private EntityManager entityManager; @Override public List<Personne> uneMethodePersonnaliseeDeRechercheParNom(String nom) { return this.entityManager.createQuery("from Personne p where p.nom = ?1").setParameter(1, nom).getResultList(); } } 2013-11-15 Spring Data - 20131114 - sdjpabase 43
  • 44. Spring Data JPA ⦿Ajouter une méthode personnalisée à un DAO ⦿On termine en créant l’interface DAO qui sera utilisée et à qui on va adjoindre la méthode personnalisée : public interface PersonneDaoPersonnaliseeRepository extends CrudRepository<Personne, Long>, PersonneDaoAvecMethodePersonnalisee {} 2013-11-15 Spring Data - 20131114 - sdjpabase 44
  • 45. Spring Data JPA ⦿Ajouter une méthode personnalisée à un DAO ⦿La classe utilisatrice : public class PersonneDaoPersonnaliseeRepositoryTest { @Autowired private PersonneDaoPersonnaliseeRepository personneDaoPersonnaliseeRepository; … @Test public void test() { List<Personne> personneList = this.personneDaoPersonnaliseeRepository.uneMethodePersonnaliseeDeRecherc heParNom(this.personneSauvee.getNom()); } } 2013-11-15 Spring Data - 20131114 - sdjpabase 45
  • 46. Spring Data JPA ⦿Comment bénéficier de l'avantage de l'API Criteria (vérification des requêtes à la compilation) ? ⦿Utiliser des Specification ⦿Intégrer QueryDsl ⦿Inspiré des concepts du Domain Driven Design ⦿Plus d'informations ici : http://spring.io/blog/2011/04/26/advancedspring-data-jpa-specifications-and-querydsl 2013-11-15 Spring Data - 20131114 - sdjpabase 46
  • 47. Spring Data JPA ⦿Principe de l'utilisation des Specification ⦿Créer un objet qui implémente l'interface Specification ⦿Le DAO étend en plus , JpaSpecificationExecutor ⦿Mettre le ou une combinaison de Specification en paramètre des méthodes classiques de Spring Data 2013-11-15 Spring Data - 20131114 - sdjpabase 47
  • 48. Spring Data JPA ⦿ Exemple d'utilisation des Specification 1. On crée des objets Specification : public CustomerSpecifications { public static Specification<Customer> customerHasBirthday() { return new Specification<Customer> { public Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb) { return cb.equal(root.get(Customer_.birthday), today); } }; } public static Specification<Customer> isLongTermCustomer() { return new Specification<Customer> { public Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb) { return cb.lessThan(root.get(Customer_.createdAt), new LocalDate.minusYears(2)); } }; } } 2013-11-15 Spring Data - 20131114 - sdjpabase 48
  • 49. Spring Data JPA ⦿Exemple d'utilisation des Specification 2. Notre DAO étend en plus JpaSpecificationExecutor : public interface CustomerRepository extends JpaRepository<Customer>, JpaSpecificationExecutor {} 3. Le client peut ensuite les utiliser : customerRepository.findAll(hasBirthday()); customerRepository.findAll(isLongTermCustomer()); customerRepository.findAll(where(customerHasBirthday()).and(isLongTermCu stomer())); 2013-11-15 Spring Data - 20131114 - sdjpabase 49
  • 50. Spring Data JPA ⦿Principe de l'utilisation de QueryDsl ⦿On inclut le plugin Maven de QueryDsl ⦿Le DAO étend en plus QueryDslPredicateExecutor 2013-11-15 Spring Data - 20131114 - sdjpabase 50
  • 51. Spring Data JPA ⦿Exemple d'utilisation de QueryDsl 1. Notre DAO étend en plus JpaSpecificationExecutor : public interface CustomerRepository extends JpaRepository<Customer>, QueryDslPredicateExecutor { } 2. Le client peut ensuite les utiliser : BooleanExpression customerHasBirthday = customer.birthday.eq(today); BooleanExpression isLongTermCustomer = customer.createdAt.lt(today.minusYears(2)); customerRepository.findAll(customerHasBirthday.and(isLongTermCustomer)); 2013-11-15 Spring Data - 20131114 - sdjpabase 51
  • 52. Spring Data JPA ⦿Les transactions : ⦿Toutes les méthodes pour récupérer des données sont en readOnly=true. Les autres sont en @Transactional(donc readOnly= false) ⦿@Transactional est configurable (timeout, readOnly, …) ⦿Pour qu’une suite d’opérations soient dans la même transaction, il suffit de mettre @Transactional dans la méthode englobante. Il faudra ajouter <tx:annotation-driven /> dans la configuration 2013-11-15 Spring Data - 20131114 - sdjpabase 52
  • 53. Spring Data JPA ⦿L’intégration de Spring Data avec Spring MVC ⦿Offre quelques facilités : ⦿Récupération automatique des entités ⦿Pagination 2013-11-15 Spring Data – 20131114 - sdjpawebapp 53
  • 54. Spring Data JPA ⦿ La récupération automatique des entités ⦿ Avant, on était obligé, à partir de l’identifiant, de récupérer les entités de la base de données : @Controller @RequestMapping("/welcome/") public class HelloController { @RequestMapping("/voir/{id}") public String voirVelo(@PathVariable("id") final Long id, final Model modele) { Velo veloTrouve = this.veloDao.findOne(id); modele.addAttribute("message", "Modèle de vélo : " + veloTrouve.getModele()); return "basique/fiche"; } } ⦿ C’est très fastidieux 2013-11-15 Spring Data - 20131114 - sdjpawebapp 54
  • 55. Spring Data JPA ⦿ Avec Spring Data, si on met directement en paramètre une entité, celle-ci sera chargée automatiquement : @Controller @RequestMapping("/sdtouch/") public class ControleurUnPeuMieuxAvecSD { @RequestMapping("/voir/{id}") public String voirVelo(@PathVariable("id") final Velo veloTrouve, final Model modele) { modele.addAttribute("message", "Modèle de vélo : " + veloTrouve.getModele()); return "sdtouch/fiche"; } } 2013-11-15 Spring Data - 20131114 - sdjpawebapp 55
  • 56. Spring Data JPA ⦿ Pour cela, il faut modifier un peu le dispatcherServletservlet.xml pour y ajouter un convertisseur : <mvc:annotation-driven conversion-service="conversionService" /> <!-- Nécessaire pour la conversion String (id) vers une entité récupéré par Spring Data (avec findOne()) --> <bean class= "org.springframework.data.repository.support.DomainClassConverter"> <!-- on va ajouter DomainClassConverter à la liste des converters de conversionService --> <constructor-arg ref="conversionService" /> </bean> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" /> 2013-11-15 Spring Data - 20131114 - sdjpawebapp 56
  • 57. Spring Data JPA ⦿Pour la pagination, il faut récupérer les paramètres de la requête HTTP pour récupérer la page à afficher et la taille de la page : @RequestMapping(value="/{page}/{pageSize}", method = RequestMethod.GET) public String printWelcome(final Model modele, @PathVariable("page") final int page, @PathVariable("pageSize") final int pageSize) { Pageable pageable = new PageRequest(page, pageSize); Page<Velo> resultat = this.veloDao.findAll(pageable); return "basique/hello"; } 2013-11-15 Spring Data - 20131114 - sdjpawebapp 57
  • 58. Spring Data JPA ⦿Spring Data améliore un peu la chose : @RequestMapping(method = RequestMethod.GET) public String printWelcome(final Model modele, @PageableDefaults(pageNumber = 0, value = 2)final Pageable pageable) { final Page<Velo> resultatRecherche = this.veloDao.findAll(pageable); modele.addAttribute("velosTrouves", resultatRecherche.getContent()); modele.addAttribute("pagination", resultatRecherche); return "sdtouch/hello"; } 2013-11-15 Spring Data - 20131114 - sdjpawebapp 58
  • 59. Spring Data JPA ⦿Comment s’opère la magie de Spring Data (attention, spoiler) ? 2013-11-15 Spring Data – 20131114 - proxylab 59
  • 60. Spring Data JPA ⦿Comment s’opère la magie de Spring Data ? ⦿Chargement des requêtes au chargement : ⦿Scanne les paquetages mentionnés dans l’applicationContext.xml ⦿Quand Spring trouve un repository, JpaRepositoryFactory va créer un SimpleJpaRepository qui implémente JpaRepository ⦿Il met ensuite cet objet dans un Proxy ⦿Juste avant, il va associer à ce proxy un intercepteur de méthode qui permet la résolution des requêtes personnalisées, nommées, avec @Query, etc. Donc à ce stade, les requêtes sont résolues et en cache ⦿Appel des méthodes des interfaces ⦿Quand une de ces méthodes est appelée, c’est en réalité le proxy qui est appelé ⦿Celui-ci va appeler la méthode correspondante de l’objet SimpleJpaRepository qu’on lui a donné au chargement 2013-11-15 Spring Data - 20131114 - proxylab 60
  • 61. Spring Data JPA ⦿Comment s’opère la magie de Spring Data ? Exemple. ⦿"Spring" : public void injecteDansClient(final Client client) { UnDao dao = (UnDao) Proxy.newProxyInstance(Thread.currentThread(). getContextClassLoader(), new Class[] { UnDao.class }, new ProxyInjecte()); client.setDao(dao); } 2013-11-15 Spring Data - 20131114 - proxylab 61
  • 62. Spring Data JPA ⦿Comment s’opère la magie de Spring Data ? Exemple. ⦿L'InvocationHandler : class ProxyInjecte implements InvocationHandler { private ClasseNonAppeleeParClient classeNonAppeleeParClient = new ClasseNonAppeleeParClient(); public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (method.getName().equals("bambiFaitDodo")) { this.classeNonAppeleeParClient.bambiFaitDodo(); } else if (method.getName().equals("atchoum")) { this.classeNonAppeleeParClient.atchoum(); } return null; } } 2013-11-15 Spring Data - 20131114 - proxylab 62
  • 63. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 63
  • 64. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 64
  • 65. Spring Data Neo4j ⦿Neo4j : une base de données orientée graphe ⦿Cas d'utilisation typique : les réseaux sociaux ⦿Spring Data Neo4j apporte un niveau d’abstraction supplémentaire à la manipulation des graphes 2013-11-15 Spring Data - 20131114 65
  • 66. Spring Data Neo4j ⦿ Neo4j quelques commandes de base ⦿ Démarrage d’une base Neo4j en mémoire : public class Neo4jMain { private final static String DB_PATH = "bdd_neo4j"; public static void main(String[] args) { GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH); registerShutdownHook(graphDb); } private static void registerShutdownHook(final GraphDatabaseService graphDb) { /* Pour que Neo4j s'arrête correctement, même en cas de Ctrl-C */ Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { graphDb.shutdown(); } } ); }} 2013-11-15 Spring Data – 20131114 - neo4jbasique 66
  • 67. Spring Data Neo4j ⦿ Neo4j quelques commandes de base ⦿ Pour créer le graphe, qu’avec des noeuds : Transaction tx = this.graphDb.beginTx(); try { this.acteur = this.graphDb.createNode(); this.acteur.setProperty("nom", "Diesel"); this.acteur.setProperty("prenom", "Vin"); Node noeudFilm = this.graphDb.createNode(); noeudFilm.setProperty(Film.TITRE, "Rapides et dangereux"); this.acteur.createRelationshipTo(noeudFilm, JOUE_DANS); noeudFilm = this.graphDb.createNode();// on utilise les noeuds noeudFilm.setProperty(Film.TITRE, "Trop rapide et trop pas content"); this.acteur.createRelationshipTo(noeudFilm, JOUE_DANS); tx.success(); } finally { tx.finish(); } 2013-11-15 Spring Data – 20131114 - neo4jbasique 67
  • 68. Spring Data Neo4j ⦿Neo4j quelques commandes de base ⦿Pour créer le graphe, en essayant d’utiliser des beans : Transaction tx = this.graphDb.beginTx(); try {… Film film = new Film(this.graphDb.createNode()); film.setTitre("Il faut sauver le soldat Ryan"); this.acteur.createRelationshipTo(film.getNoeud(), JOUE_DANS); tx.success(); } finally { tx.finish(); } 2013-11-15 Spring Data – 20131114 - neo4jbasique 68
  • 69. Spring Data Neo4j ⦿ Neo4j quelques commandes de base ⦿ Et dans le bean Film, on a : public class Film { public static final String TITRE = "TITRE"; private Node noeud; public Film(Node noeud) { this.noeud = noeud; } public Node getNoeud() { return this.noeud; } public String getTitre() { return (String) this.noeud.getProperty(TITRE); } public void setTitre(String nom) { this.noeud.setProperty(TITRE, nom); } } ⦿ La relation doit étendre RelationshipType : public enum JoueDansRelationEnum implements RelationshipType { JOUE_DANS; } 2013-11-15 Spring Data – 20131114 - neo4jbasique 69
  • 70. Spring Data Neo4j ⦿ Neo4j quelques commandes de base ⦿ Pour afficher le contenu du graphe, on peut utiliser un « Traverser » : public void afficheGraphe() { Traverser traverseurDeFilms = getTraverseursFilms(); for (Path path : traverseurDeFilms) { if (path.length() == 0) { System.out.println(path.endNode().getProperty("nom") + " a joué dans les films suivants :"); } else { System.out.println(path.endNode().getProperty(Film.TITRE)); } }} private Traverser getTraverseursFilms() { TraversalDescription td = Traversal.description(). breadthFirst(). relationships(JOUE_DANS). evaluator(Evaluators.all()); return td.traverse(this.acteur); } 2013-11-15 Spring Data – 20131114 - neo4jbasique 70
  • 71. Spring Data Neo4j ⦿ Neo4j quelques commandes de base ⦿ Neo4j a son langage de « requêtage », le Cypher : public void exempleCypher() { String requete = "start n=node("+this.acteur.getId()+") " + "match n-[:JOUE_DANS]->films " + "where films." + Film.TITRE + " =~ 'Trop.*' " + "return n, n.nom, n.prenom, films." + Film.TITRE; ExecutionResult result = this.engine.execute(requete); String rows = ""; for ( Map<String, Object> row : result) { for ( Entry<String, Object> column : row.entrySet() ) { rows += column.getKey() + ": " + column.getValue() + "; "; } rows += "n"; } System.out.println(rows); } ⦿ Affiche : n: Node[13]; n.nom: Diesel; films.TITRE: Trop rapide et trop pas content; n.prenom: Vin; 2013-11-15 Spring Data – 20131114 - neo4jbasique 71
  • 72. Spring Data Neo4j ⦿Ce qu’apporte Spring Data Neo4j ⦿Les nœuds deviennent des beans Java classiques. Pareil pour les relations ⦿Les opérations de base peuvent se faire à partir des interfaces ⦿Une bonne partie des opérations valables pour JPA sont valables pour Neo4j 2013-11-15 Spring Data – 20131114 - sdneo4jbase 72
  • 73. Spring Data Neo4j ⦿S'inclut avec une dépendance Maven : <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-neo4j</artifactId> <version>2.3.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-neo4j-aspects</artifactId> <version>2.3.1.RELEASE</version> </dependency> 2013-11-15 Spring Data – 20131114 - sdneo4jbase 73
  • 74. Spring Data Neo4j ⦿Un exemple de nœud Spring Data Neo4j : @NodeEntity public class Acteur { @GraphId private Long idNoeud; @Indexed(indexType = IndexType.FULLTEXT, indexName="nom") private String nom; private String prenom; public void aJoueDans(Film film) { this.films.add(film); } @RelatedTo(direction=Direction. BOTH, type="aJoueDans") private Set<Film> films; @RelatedToVia private Set<Realisation> realisations; // getters et setters classiques 2013-11-15 public Realisation aRealise(Film film) { Realisation realisation = new Realisation(); realisation.setActeur(this); realisation.setFilm(film); realisations.add(realisation); return realisation; } Spring Data – 20131114 - sdneo4jbase 74
  • 75. Spring Data Neo4j ⦿Les relations deviennent aussi des beans Java classiques : @RelationshipEntity(type="aRealise") public class Realisation { @GraphId private Long id; private Calendar dateRealisation; @StartNode private Acteur acteur; @EndNode private Film film; // getters et setters classiques 2013-11-15 Spring Data – 20131114 - sdneo4jbase 75
  • 76. Spring Data Neo4j ⦿Les DAO sont toujours aussi minimalistes : public interface ActeurDao extends GraphRepository<Acteur> { @Query("start acteur=node({0}) " + "match acteur-[:aRealise]->film " + "return film") Iterable<Film> recupereMoiTousLesFilmsRealisesPar(Acteur acteur); } 2013-11-15 Spring Data – 20131114 - sdneo4jbase 76
  • 77. Spring Data Neo4j ⦿L'utilisation s'en trouve simplifiée : public void setup() { this.acteurDao.deleteAll(); Acteur vinDiesel = new Acteur(); vinDiesel.setNom("Diesel"); vinDiesel.setPrenom("Vin"); vinDiesel.aJoueDans(leFilm("Strays")); vinDiesel.aJoueDans(leFilm("Il faut sauver le soldat Ryan")); vinDiesel.aJoueDans(leFilm("Les Initiés")); final Film multiFacial = leFilm("Multi-Facial"); this.filmDao.save(multiFacial); vinDiesel.aRealise(multiFacial).en(1994); this.acteurDao.save(vinDiesel); } 2013-11-15 Spring Data – 20131114 - sdneo4jbase 77
  • 78. Spring Data Neo4j ⦿D'autres exemples d'utilisation : EndResult<Film> filmsTrouves = this.filmDao.findAll(); EndResult<Film> filmsTrouves = this.filmDao.findAllByPropertyValue("titre", "Strays"); Film filmTrouve = this.filmDao.findByPropertyValue("titre", "Les Initiés"); Iterable<Film> filmsTrouves = this.filmDao.findByTitreContaining("Il"); Acteur vinDiesel = this.acteurDao.findOne(identifiantVinDiesel); final Iterable<Film> filmsTrouves = this.acteurDao.recupereMoiTousLesFilmsRealisesPar(vinDiesel); 2013-11-15 Spring Data – 20131114 - sdneo4jbase 78
  • 79. Spring Data Neo4j ⦿On peut aussi utiliser les Traversers : final Acteur vinDiesel = this.acteurDao.findOne(this.identifiantVinDiesel); TraversalDescription traversalDescription = Traversal.description(). breadthFirst(). evaluator(Evaluators.atDepth(1)); final Iterable<Film> filmsJouesParVinDiesel = this.filmDao.findAllByTraversal(vinDiesel, traversalDescription); 2013-11-15 Spring Data – 20131114 - sdneo4jbase 79
  • 80. Spring Data Neo4j ⦿L'applicationContext.xml : <neo4j:repositories base-package="fr.soat.springdata.neo4j.sdneo4jbase.dao" /> <neo4j:config storeDirectory="data/bdd_neo4j" /> 2013-11-15 Spring Data – 20131114 - sdneo4jbase 80
  • 81. Spring Data Neo4j ⦿La hiérarchie des interfaces Spring Data : findAllByTraver TraversalRepository sal PagingAndSortingRepository CRUDRepository save(U), findOne(Long), findAll(),… IndexRepository findAllByQuery findAllByRange … GraphRepository 2013-11-15 Spring Data – 20131114 - sdneo4jbase 81
  • 82. Spring Data JPA Spring Data Commons Repository CrudRepository PagingAndSortingRepository JpaRepository Pas de méthode save(S), findOne(ID), exists(), findAll(), deleteAll(), … findAll(Sort), findAll(Pageable) flush(), saveAndFlush(T), deleteInBatch(Iterable<T>), … Spring Data JPA 2013-11-15 Spring Data - 20131114 - sdjpabase 82
  • 83. Spring Data Neo4j ⦿D'autres interfaces sont disponibles, comme CypherDslRepository pour exécuter du CypherDsl, SpatialRepository pour les requêtes spatiales 2013-11-15 Spring Data – 20131114 - sdneo4jbase 83
  • 84. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 84
  • 85. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 85
  • 86. Spring Data REST ⦿Spring Data REST simplifie l’exposition des services REST ⦿Pour offrir un service REST, il suffit : ⦿De dire qu’on utilise Spring Data REST pour une source de données particulière (JPA, Neo4j, MongoDB, etc.) ⦿D’étendre une des interfaces de Spring Data ⦿De dire où se situent ces interfaces d’export ⦿De… non, c’est tout 2013-11-15 Spring Data – 20131114 - sdrestws 86
  • 87. Spring Data REST Spring Data REST WebMVC Spring MVC Spring Data JPA Spring Data Neo4j Spring Data MongoDB Spring Data Commons 2013-11-15 Spring Data – 20131114 - sdjpabase 87
  • 88. Spring Data REST ⦿ Dans le pom.xml : <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-rest-webmvc</artifactId> <version>1.0.0.RELEASE</version> </dependency> … et les dépendances vers H2 et Hibernate 2013-11-15 Spring Data - 20131114 - sdrestws 88
  • 89. Spring Data REST ⦿Un brin de folie, le DAO a une annotation à lui : @RestResource(path="chanson") //pour personnaliser un peu la façon dont le service web est appelé public interface ChansonDao extends CrudRepository<Chanson, Long> { } ⦿Le bean Chanson : @Entity public class Chanson { @Id private Long id; private String titre;…} 2013-11-15 Spring Data - 20131114 - sdrestws 89
  • 90. Spring Data REST ⦿Utilisation : mvn clean install jetty:run lance Jetty et le fait écouter sur le port 8080 curl -H "Content-Type: application/json" -d '{"titre":"Get Lucky","id":"2"}' http://localhost:8080/chanson curl -v http://localhost:8080/chanson/2 Renvoie : { "links" : [ { "rel" : "self"; "href" : "http://localhost:8080/chanson/2" } ], "titre" : "Get Lucky" } 2013-11-15 Spring Data - 20131114 - sdrestws 90
  • 91. Spring Data REST ⦿Limites de Spring Data REST 2013-11-15 Spring Data - 20131114 - sdrestws 91
  • 92. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 92
  • 93. Spring Data ⦿Introduction ⦿Spring Data JPA ⦿Spring Data Neo4j ⦿Spring Data Rest ⦿Aperçu de Spring Data MongoDB 2013-11-15 Spring Data - 20131114 93
  • 94. Spring Data MongoDb ⦿ Aperçu de Spring Data MongoDB ⦿ On a un bean : @Document(collection = "menu") // annotations pas nécessaires public class MenuItem { @Id private String id; @Field("itemName") @Indexed private String name; } ⦿ Le répository associé public interface MenuItemRepository extends CrudRepository<MenuItem, String> { public List<MenuItem> findByIngredientsNameIn(String... name); } ⦿ Un exemple d'utilisation menuItemRepository.save(eggFriedRice()); List<MenuItem> peanutItems menuItemRepository.findByIngredientsNameIn("Peanuts"); 2013-11-15 Spring Data - 20131114 94
  • 95. Spring Data - conclusion ⦿Pour aller plus loin : ⦿Le site de Spring Data : http://projects.spring.io/spring-data/ ⦿Le livre sur Spring Data : ⦿http://shop.oreilly.com/product/0636920024767.do ⦿Et ses exemples : https://github.com/springprojects/spring-data-book ⦿Le livre sur Spring Data Neo4j : Good Relationships The Spring Data Neo4j Guide Book ⦿Mes exemples : ⦿https://github.com/xeter/soirees3t 2013-11-15 Spring Data - 20131114 95