Présentation spring data Matthieu Briend

96
Spring Data 2022-10-27 Spring Data - 20131114 1

description

 

Transcript of Présentation spring data Matthieu Briend

Page 1: Présentation spring data  Matthieu Briend

2023-04-10 1

Spring Data

Spring Data - 20131114

Page 2: Présentation spring data  Matthieu Briend

2023-04-10 2

Spring Data

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

Spring Data - 20131114

Page 3: Présentation spring data  Matthieu Briend

2023-04-10 3

Spring Data

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

Spring Data - 20131114

Page 4: Présentation spring data  Matthieu Briend

2023-04-10 4

Spring Data - Introduction

⦿Utilité du pattern DAO ?⦿Hétérogénéité des bases de données

Spring Data - 20131114

Page 5: Présentation spring data  Matthieu Briend

2023-04-10 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, …

Spring Data - 20131114

Page 6: Présentation spring data  Matthieu Briend

2023-04-10 6

Spring Data

Spring Data – 20131114

API de manipulation de la source de données

(JPA, Neo4j, MongoDB, etc.)

Source de données

Spring DataManipule

Page 7: Présentation spring data  Matthieu Briend

2023-04-10 7

Spring Data Gemfire

Spring Data

Spring Data – 20131114

Spring Data Commons

Spring Data JPA Spring Data Neo4j

Spring Data MongoDB

Page 8: Présentation spring data  Matthieu Briend

2023-04-10 8

Spring Data

⦿Utilisé sur un projet chez SFR⦿Motivations

Spring Data - 20131114

Page 9: Présentation spring data  Matthieu Briend

2023-04-10 9

Spring Data

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

Spring Data - 20131114

Page 10: Présentation spring data  Matthieu Briend

2023-04-10 10

Spring Data

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

Spring Data - 20131114

Page 11: Présentation spring data  Matthieu Briend

2023-04-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

Spring Data - 20131114 - sdjpabase

Page 12: Présentation spring data  Matthieu Briend

2023-04-10 12

Spring Data JPA

Spring Data - 20131114 - sdjpabase

JPA

Hibernate EclipseLink

JDBC

BDD

Spring DataManipule

Se base sur

Page 13: Présentation spring data  Matthieu Briend

2023-04-10 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>

Spring Data - 20131114 - sdjpabase

Page 14: Présentation spring data  Matthieu Briend

2023-04-10 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> {

}

Spring Data - 20131114 - sdjpabase

Nom de l'entité qu'on manipule

Type de l'identifiant de l'entité

Page 15: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 16: Présentation spring data  Matthieu Briend

2023-04-10 16

Spring Data JPA

Spring Data - 20131114 - sdjpabase

Repository

CrudRepository

PagingAndSortingRepository

JpaRepository

findAll(Sort), findAll(Pageable)

flush(), saveAndFlush(T), deleteInBatch(Iterable<T>), …

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

Pas de méthodeSpring Data Commons

Spring Data JPA

Page 17: Présentation spring data  Matthieu Briend

2023-04-10 17

Spring Data JPA

⦿ CrudRepository :public interface PersonneDao extends CrudRepository<Personne, Long> {}

public class PersonneDaoTest {@Autowiredprivate 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());…

}

Spring Data - 20131114 - sdjpabase

Page 18: Présentation spring data  Matthieu Briend

2023-04-10 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 paginationAssert.assertEquals(10, personnes.getTotalElements()); //nb total d'éléments récupérablesAssert.assertEquals(4, personnes.getTotalPages()); // nombre de pagesAssert.assertTrue(personnes.hasContent());

…}}

Spring Data - 20131114 - sdjpabase

Page 19: Présentation spring data  Matthieu Briend

2023-04-10 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);}

Spring Data - 20131114 - sdjpabase

Page 20: Présentation spring data  Matthieu Briend

2023-04-10 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);

Spring Data - 20131114 - sdjpabase

Page 21: Présentation spring data  Matthieu Briend

2023-04-10 21

Spring Data JPA

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

Spring Data - 20131114 - sdjpabase

Logique Mot-clé Spring Data

GREATER_THAN 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

NOT_IN NotIn, IsNotIn

NOT_LIKE NotLike, IsNotLike

REGEX Regex, MatchesRegex, Matches

… …

Page 22: Présentation spring data  Matthieu Briend

2023-04-10 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 « sous-

proprié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);

Spring Data - 20131114 - sdjpabase

Page 23: Présentation spring data  Matthieu Briend

2023-04-10 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);

Spring Data - 20131114 - sdjpabase

Page 24: Présentation spring data  Matthieu Briend

2023-04-10 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);

Spring Data - 20131114 - sdjpabase

Page 25: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 26: Présentation spring data  Matthieu Briend

2023-04-10 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);}

Spring Data - 20131114 - sdjpabase

Page 27: Présentation spring data  Matthieu Briend

2023-04-10 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")@Modifyingpublic int metAJourNom(@Param("nom")String nom,

@Param("id") Long id);

⦿On peut nommer les paramètres avec @Param

Spring Data - 20131114 - sdjpabase

Page 28: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 29: Présentation spring data  Matthieu Briend

2023-04-10 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)

Spring Data - 20131114 - sdjpabase

Page 30: Présentation spring data  Matthieu Briend

2023-04-10 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 SpringSpring Data - 20131114 - sdjpabase

Page 31: Présentation spring data  Matthieu Briend

2023-04-10 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" />

Spring Data - 20131114 - sdjpabase

Page 32: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 33: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 34: Présentation spring data  Matthieu Briend

2023-04-10 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.DaoCommunAuxAutresDaoFactoryBean"/>

Spring Data - 20131114 - sdjpabase

Page 35: Présentation spring data  Matthieu Briend

2023-04-10 35

Spring Data JPA

⦿Ajouter une méthode personnalisée pour tous les DAO⦿Un FactoryBean devra être créé :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); }…

Spring Data - 20131114 - sdjpabase

Page 36: Présentation spring data  Matthieu Briend

2023-04-10 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 }}}

Spring Data - 20131114 - sdjpabase

Page 37: Présentation spring data  Matthieu Briend

2023-04-10 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 :@NoRepositoryBeanpublic interface DaoCommunAuxAutresDao<T, ID extends Serializable> extends JpaRepository<T, ID>{ List<T> uneMethodeDeRechercheCommuneATousLesDaoParLExemple(T exemple);}

Spring Data - 20131114 - sdjpabase

Page 38: Présentation spring data  Matthieu Briend

2023-04-10 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(); }}

Spring Data - 20131114 - sdjpabase

Page 39: Présentation spring data  Matthieu Briend

2023-04-10 39

Spring Data JPA

⦿Ajouter une méthode personnalisée pour tous les DAO⦿Un Repository quelconque :public interface AutrePersonneDao

extends DaoCommunAuxAutresDao<Personne, Long>{}

Spring Data - 20131114 - sdjpabase

Page 40: Présentation spring data  Matthieu Briend

2023-04-10 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.uneMethodeDeRechercheCommuneATousLesDaoParLExemple(this.personneSauvee);   }}

Spring Data - 20131114 - sdjpabase

Page 41: Présentation spring data  Matthieu Briend

2023-04-10 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));

Spring Data - 20131114 - sdjpabase

Page 42: Présentation spring data  Matthieu Briend

2023-04-10 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);}

Spring Data - 20131114 - sdjpabase

Page 43: Présentation spring data  Matthieu Briend

2023-04-10 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(); }

}

Spring Data - 20131114 - sdjpabase

Page 44: Présentation spring data  Matthieu Briend

2023-04-10 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 {}

Spring Data - 20131114 - sdjpabase

Page 45: Présentation spring data  Matthieu Briend

2023-04-10 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.uneMethodePersonnaliseeDeRechercheParNom(this.personneSauvee.getNom()); }}

Spring Data - 20131114 - sdjpabase

Page 46: Présentation spring data  Matthieu Briend

2023-04-10 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/advanced-spring-data-jpa-specifications-and-querydsl

Spring Data - 20131114 - sdjpabase

Page 47: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 48: Présentation spring data  Matthieu Briend

2023-04-10 48

Spring Data JPA

⦿ Exemple d'utilisation des Specification1. 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)); } }; }}

Spring Data - 20131114 - sdjpabase

Page 49: Présentation spring data  Matthieu Briend

2023-04-10 49

Spring Data JPA

⦿Exemple d'utilisation des Specification2. 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(isLongTermCustomer()));

Spring Data - 20131114 - sdjpabase

Page 50: Présentation spring data  Matthieu Briend

2023-04-10 50

Spring Data JPA

⦿Principe de l'utilisation de QueryDsl⦿On inclut le plugin Maven de QueryDsl⦿Le DAO étend en plus

QueryDslPredicateExecutor

Spring Data - 20131114 - sdjpabase

Page 51: Présentation spring data  Matthieu Briend

2023-04-10 51

Spring Data JPA

⦿Exemple d'utilisation de QueryDsl1. 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));

Spring Data - 20131114 - sdjpabase

Page 52: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpabase

Page 53: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data – 20131114 - sdjpawebapp

Page 54: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdjpawebapp

Page 55: Présentation spring data  Matthieu Briend

2023-04-10 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"; }}

Spring Data - 20131114 - sdjpawebapp

Page 56: Présentation spring data  Matthieu Briend

2023-04-10 56

Spring Data JPA

⦿Pour cela, il faut modifier un peu le dispatcherServlet-servlet.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" />

Spring Data - 20131114 - sdjpawebapp

Page 57: Présentation spring data  Matthieu Briend

2023-04-10 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";}

Spring Data - 20131114 - sdjpawebapp

Page 58: Présentation spring data  Matthieu Briend

2023-04-10 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";}

Spring Data - 20131114 - sdjpawebapp

Page 59: Présentation spring data  Matthieu Briend

2023-04-10 59

Spring Data JPA

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

Spring Data – 20131114 - proxylab

Page 60: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - proxylab

Page 61: Présentation spring data  Matthieu Briend

2023-04-10 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);}

Spring Data - 20131114 - proxylab

Page 62: Présentation spring data  Matthieu Briend

2023-04-10 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;

}}

Spring Data - 20131114 - proxylab

Page 63: Présentation spring data  Matthieu Briend

2023-04-10 63

Spring Data

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

Spring Data - 20131114

Page 64: Présentation spring data  Matthieu Briend

2023-04-10 64

Spring Data

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

Spring Data - 20131114

Page 65: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114

Page 66: Présentation spring data  Matthieu Briend

2023-04-10 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();}

} );}}

Spring Data – 20131114 - neo4jbasique

Page 67: Présentation spring data  Matthieu Briend

2023-04-10 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();}

Spring Data – 20131114 - neo4jbasique

Page 68: Présentation spring data  Matthieu Briend

2023-04-10 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();}

Spring Data – 20131114 - neo4jbasique

Page 69: Présentation spring data  Matthieu Briend

2023-04-10 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;}

Spring Data – 20131114 - neo4jbasique

Page 70: Présentation spring data  Matthieu Briend

2023-04-10 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);

}

Spring Data – 20131114 - neo4jbasique

Page 71: Présentation spring data  Matthieu Briend

2023-04-10 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;

Spring Data – 20131114 - neo4jbasique

Page 72: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data – 20131114 - sdneo4jbase

Page 73: Présentation spring data  Matthieu Briend

2023-04-10 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>

Spring Data – 20131114 - sdneo4jbase

Page 74: Présentation spring data  Matthieu Briend

2023-04-10 74

Spring Data Neo4j

⦿Un exemple de nœud Spring Data Neo4j :

Spring Data – 20131114 - sdneo4jbase

@NodeEntitypublic class Acteur {

@GraphIdprivate Long idNoeud;@Indexed(indexType =

IndexType.FULLTEXT, indexName="nom")

private String nom;private String prenom;

@RelatedTo(direction=Direction.BOTH, type="aJoueDans")

private Set<Film> films;@RelatedToViaprivate Set<Realisation>

realisations;// getters et setters classiques

public void aJoueDans(Film film) {

this.films.add(film);}

public Realisation aRealise(Film film) {

Realisation realisation = new Realisation();

realisation.setActeur(this);

realisation.setFilm(film);

realisations.add(realisation);return realisation;

}

Page 75: Présentation spring data  Matthieu Briend

2023-04-10 75

Spring Data Neo4j

⦿Les relations deviennent aussi des beans Java classiques :

Spring Data – 20131114 - sdneo4jbase

@RelationshipEntity(type="aRealise")public class Realisation {

@GraphIdprivate Long id;

private Calendar dateRealisation;

@StartNodeprivate Acteur acteur;

@EndNodeprivate Film film;// getters et setters classiques

Page 76: Présentation spring data  Matthieu Briend

2023-04-10 76

Spring Data Neo4j

⦿Les DAO sont toujours aussi minimalistes :

Spring Data – 20131114 - sdneo4jbase

public interface ActeurDao extends GraphRepository<Acteur> {

@Query("start acteur=node({0}) " + "match acteur-[:aRealise]->film " + "return film")

Iterable<Film> recupereMoiTousLesFilmsRealisesPar(Acteur acteur);}

Page 77: Présentation spring data  Matthieu Briend

2023-04-10 77

Spring Data Neo4j

⦿L'utilisation s'en trouve simplifiée :

Spring Data – 20131114 - sdneo4jbase

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);}

Page 78: Présentation spring data  Matthieu Briend

2023-04-10 78

Spring Data Neo4j

⦿D'autres exemples d'utilisation :

Spring Data – 20131114 - sdneo4jbase

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);

Page 79: Présentation spring data  Matthieu Briend

2023-04-10 79

Spring Data Neo4j

⦿On peut aussi utiliser les Traversers :

Spring Data – 20131114 - sdneo4jbase

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);

Page 80: Présentation spring data  Matthieu Briend

2023-04-10 80

Spring Data Neo4j

⦿L'applicationContext.xml :

Spring Data – 20131114 - sdneo4jbase

<neo4j:repositories base-

package="fr.soat.springdata.neo4j.sdneo4jbase.dao" /><neo4j:config storeDirectory="data/bdd_neo4j" />

Page 81: Présentation spring data  Matthieu Briend

2023-04-10 81

Spring Data Neo4j

⦿La hiérarchie des interfaces Spring Data :

Spring Data – 20131114 - sdneo4jbase

CRUDRepository

GraphRepository

PagingAndSortingRepository

IndexRepository

TraversalRepository

findAllByQueryfindAllByRange…

findAllByTraversal

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

Page 82: Présentation spring data  Matthieu Briend

2023-04-10 82

Spring Data JPA

Spring Data - 20131114 - sdjpabase

Repository

CrudRepository

PagingAndSortingRepository

JpaRepository

findAll(Sort), findAll(Pageable)

flush(), saveAndFlush(T), deleteInBatch(Iterable<T>), …

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

Pas de méthodeSpring Data Commons

Spring Data JPA

Page 83: Présentation spring data  Matthieu Briend

2023-04-10 83

Spring Data Neo4j

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

Spring Data – 20131114 - sdneo4jbase

Page 84: Présentation spring data  Matthieu Briend

2023-04-10 84

Spring Data

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

Spring Data - 20131114

Page 85: Présentation spring data  Matthieu Briend

2023-04-10 85

Spring Data

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

Spring Data - 20131114

Page 86: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data – 20131114 - sdrestws

Page 87: Présentation spring data  Matthieu Briend

2023-04-10 87

Spring Data REST

Spring Data – 20131114 - sdjpabase

Spring Data Commons

Spring Data JPA Spring Data Neo4j

Spring Data MongoDB

Spring Data REST WebMVC

Spring MVC

Page 88: Présentation spring data  Matthieu Briend

2023-04-10 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

Spring Data - 20131114 - sdrestws

Page 89: Présentation spring data  Matthieu Briend

2023-04-10 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 :@Entitypublic class Chanson { @Id private Long id;

private String titre;…}

Spring Data - 20131114 - sdrestws

Page 90: Présentation spring data  Matthieu Briend

2023-04-10 90

Spring Data REST

⦿Utilisation :mvn clean install jetty:run lance Jetty et le fait écouter sur le port 8080curl -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"}

Spring Data - 20131114 - sdrestws

Page 91: Présentation spring data  Matthieu Briend

2023-04-10 91

Spring Data REST

⦿Limites de Spring Data REST

Spring Data - 20131114 - sdrestws

Page 92: Présentation spring data  Matthieu Briend

2023-04-10 92

Spring Data

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

Spring Data - 20131114

Page 93: Présentation spring data  Matthieu Briend

2023-04-10 93

Spring Data

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

Spring Data - 20131114

Page 94: Présentation spring data  Matthieu Briend

2023-04-10 94

Spring Data MongoDb

⦿Aperçu de Spring Data MongoDB⦿On a un bean :@Document(collection = "menu") // annotations pas nécessairespublic 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'utilisationmenuItemRepository.save(eggFriedRice());List<MenuItem> peanutItems menuItemRepository.findByIngredientsNameIn("Peanuts");

Spring Data - 20131114

Page 95: Présentation spring data  Matthieu Briend

2023-04-10 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/spring-projects/spring-data-book

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

Spring Data - 20131114

Page 96: Présentation spring data  Matthieu Briend

2023-04-10 96

Spring Data

Spring Data - 20131114

Des questions ?