[FR] Introduction à Spring Data Neo4j 3.x

76

description

22nd of May - Graph DB Meetup @ Lyon, FR Contents in French this time Details all capabilities offered by Neo4j. More info : http://www.meetup.com/graphdb-Lyon/events/175401022/ Please not all attendants were techies, that's why I felt compelled to remind what Spring is and is not.

Transcript of [FR] Introduction à Spring Data Neo4j 3.x

Page 1: [FR] Introduction à Spring Data Neo4j 3.x
Page 2: [FR] Introduction à Spring Data Neo4j 3.x

$(Graph Meetup)> who am i

Florent Biville (@fbiville)

(Développeur [OSS]|formateur|associé) à

Co-créateur de Spring Meetup Paris (@interface21_ug)

Partenaire @Neo4j depuis 2012 (& formateur Neo4j !)

Page 3: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j - au menu

1. Spring ?

2. Spring Data ?

3. Spring Data Neo4j ?

Page 4: [FR] Introduction à Spring Data Neo4j 3.x

Spring ?

Page 5: [FR] Introduction à Spring Data Neo4j 3.x

Spring

À ses débuts (2003)

Spring == Spring Framework == framework de DI

Page 6: [FR] Introduction à Spring Data Neo4j 3.x

Dependency Injection - brefs rappels

Spring

Page 7: [FR] Introduction à Spring Data Neo4j 3.x

public class InstantMessagingClient implements MessagingClient {

private final InstantMessagingService instantMessagingService;

private final UserSessionService userSessionService;

public InstantMessagingClient(InstantMessagingService instantMessagingService,

UserSessionService userSessionService) {

this.instantMessagingService = instantMessagingService;

this.userSessionService = userSessionService;

}

public void sendMessage(Message message) {

if (userSessionService.isCurrentlyLogged(message.getAuthorName())) {

instantMessagingService.sendMessage(message);

}

}

}

Spring

Page 8: [FR] Introduction à Spring Data Neo4j 3.x

public class InstantMessagingClient implements MessagingClient {

private final InstantMessagingService instantMessagingService;

private final UserSessionService userSessionService;

public InstantMessagingClient(InstantMessagingService instantMessagingService,

UserSessionService userSessionService) {

this.instantMessagingService = instantMessagingService;

this.userSessionService = userSessionService;

}

public void sendMessage(Message message) {

if (userSessionService.isCurrentlyLogged(message.getAuthorName())) {

instantMessagingService.sendMessage(message);

}

}

}

Spring

Page 9: [FR] Introduction à Spring Data Neo4j 3.x

Dependency Injection - idée

Ne pas assembler InstantMessagingClient soi-

même, déléguer plutôt à une brique logicielle tierce.

Spring

Page 10: [FR] Introduction à Spring Data Neo4j 3.x

Dependency Injection - intérêts

Découpler son logiciel d’un “assemblage” particulier de

InstantMessagingClient (ex: assembler un service

de tests pour les tests automatisés)

Spring

Page 11: [FR] Introduction à Spring Data Neo4j 3.x

Dependency Injection - avec Spring Framework

Spring

Page 12: [FR] Introduction à Spring Data Neo4j 3.x

Notion de bean = description d’un “assemblage” = recette

de créations d’objets

Notion de context = groupe de beans

Plusieurs formats de description :

XML (historique), Java, annotations Java

Spring

Page 13: [FR] Introduction à Spring Data Neo4j 3.x

Déclaration de context en XML Déclaration de context en Java

<beans[...]>

<import resource=”classpath:my-services.xml” />

<bean id=”instantMessagingClient” class=”com.

acme.InstantMessagingClient”>

<constructor-arg ref=”instantMsgService” />

<constructor-arg ref=”userSessionService” />

</bean>

</beans>

@Configuration

@Import(MyServiceContext.class)

public class MyProductionContext {

@Bean

public MessagingClient instantMessagingClient

(InstantMessagingService msgService,

UserSessionService userService)

return new InstantMessagingClient(

msgService, userService

);

}

Spring

Page 14: [FR] Introduction à Spring Data Neo4j 3.x

Dependency Injection par annotation

Côté contexte : <component-scan /> (XML) ou @ComponentScan (Java) permet de scanner tout un ensemble de beans sans avoir à les déclarer explicitement.

@Component

public class InstantMessagingClient implements MessagingClient {

[...]

@Autowired // ou @Inject (standard Java EE)

public InstantMessagingClient(InstantMessagingService instantMessagingService,

UserSessionService userSessionService) {

[...]

}

[...]

}

Spring

Page 15: [FR] Introduction à Spring Data Neo4j 3.x

À ses débuts (2003)

Spring == Spring Framework == framework de DI

Devient un standard de facto (vs. le standard officiel J2EE)

Spring

Page 16: [FR] Introduction à Spring Data Neo4j 3.x

Depuis,

Spring = écosystème alternatif|complémentaire à Java EE

Spring

Page 17: [FR] Introduction à Spring Data Neo4j 3.x

Spring

Page 18: [FR] Introduction à Spring Data Neo4j 3.x

La plupart des briques logicielles de l’écosystème Spring

repose sur Spring Framework...

Spring

Page 19: [FR] Introduction à Spring Data Neo4j 3.x

… dont Spring Data !

Spring

Page 20: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data ?

Page 21: [FR] Introduction à Spring Data Neo4j 3.x

Contexte historique

Hégémonie des RDBMS jusqu’à il y a “peu” (NOSQL!).

Impacts côté Java,

hégémonie des ORM (Hibernate, EclipseLink...)

émergence d’un standard (JPA)

Spring Data

Page 22: [FR] Introduction à Spring Data Neo4j 3.x

Philosophie

Concilier

la familiarité des API comme JPA,

la flexibilité de Spring Framework,

les spécificités d’un maximum de stores NOSQL.

Spring Data

Page 23: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Page 24: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Page 25: [FR] Introduction à Spring Data Neo4j 3.x

Objection !

Spring Data

Page 26: [FR] Introduction à Spring Data Neo4j 3.x

Les ORM peuvent s’appuyer

sur le standard SQL commun aux SGDBR.

Spring Data

Page 27: [FR] Introduction à Spring Data Neo4j 3.x

Il n’existe aucun standard partagé par les stores NOSQL.

Spring Data

Page 28: [FR] Introduction à Spring Data Neo4j 3.x

Comment Spring Data peut-il

prétendre à une API homogène

autour de stores NOSQL qui ne le

sont pas ?

Spring Data

Page 29: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Commons - idée

Module parent de tous les modules Spring Data.

Regroupe les traits communs des stores supportés.

Définit les concepts partagés de base.

Spring Data

Page 30: [FR] Introduction à Spring Data Neo4j 3.x

Entité ~ description orientée objet d’un enregistrement

Repository ~ encapsulation des opérations de

requêtage sur une collection d’objets (ici : entités)

Template ~ encapsulation des opérations bas niveau

spécifiques à un service particulier (JdbcTemplate…)

Spring Data

Page 31: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Commons - entités

Spring Data

Page 32: [FR] Introduction à Spring Data Neo4j 3.x

Notion de mapping

représentation objet (entité) <-> représentation du store

chaque module SD implémente son propre mapping

exemples : @NodeEntity (SD Neo4j), @Document (SD Mongo)...

Spring Data

Page 33: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Commons - repositories

Spring Data

Page 34: [FR] Introduction à Spring Data Neo4j 3.x

Encapsule les contrats d’opérations de requêtage

communes à la plupart des stores : écriture, lecture, mise à

jour…

Ces opérations sont réparties dans une hiérarchie d’

interfaces Java.

Spring Data

Page 35: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Repository<T, ID>

Interface “marker” permettant de

déclencher l’inclusion de ses

implémentations

automatiquement et la génération

de méthodes finder

dynamiques.

T = type de l’entité

ID = type de l’identifiant technique

Page 36: [FR] Introduction à Spring Data Neo4j 3.x

Méthodes finder dynamiques

Idée : déduire (au runtime) l’implémentation des

méthodes de Repository par leur signature (merci Ruby on

Rails).

Spring Data

Page 37: [FR] Introduction à Spring Data Neo4j 3.x

public interface PersonRepository extends Repository<Person, Long> {

List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);

List<Person> findByLastnameIgnoreCase(String lastname);

List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

List<Person> findByLastnameOrderByFirstnameAsc(String lastname);

List<Person> findByLastnameOrderByFirstnameDesc(String lastname);

}

Spring Data

Page 38: [FR] Introduction à Spring Data Neo4j 3.x

@Service

public class JdbcPersonService implements PersonService {

private final PersonRepository repository;

@Autowired

public PersonService(PersonRepository repository) {

this.repository = repository;

}

@Transactional

public List<Person> findByLastnameIgnoreCase(String lastName) {

return repository.findByLastnameIgnoreCase(lastName);

}

// [...]

}

Spring Data

Page 39: [FR] Introduction à Spring Data Neo4j 3.x

Méthodes finder dynamiques

Aucune écriture d’implémentation de PersonRepository !

Les développeurs se focalisent sur le code métier

(JdbcPersonService).

Spring Data

Page 40: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Repository<T, ID>

Interface “marker” permettant de

déclencher l’inclusion de ses

implémentations

automatiquement et la génération

de méthodes finder

dynamiques.

T = type de l’entité

ID = type de l’identifiant technique

Page 41: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Repository<T, ID> Définit les opérations

élémentaires sur les entités

(création, lecture, mise à jour,

suppression).

CrudRepository<T, ID>

T = type de l’entité

ID = type de l’identifiant technique

Page 42: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Repository<T, ID>

Introduit des critères de tri &

pagination sur les requêtes de

lecture globale.CrudRepository<T,

ID>

PagingAndSortingRepository<T, ID>T = type de l’entité

ID = type de l’identifiant technique

Page 43: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data

Repository<T, ID>

T = type de l’entité

ID = type de l’identifiant technique

CrudRepository<T, ID>

PagingAndSortingRepository<T, ID>

Chaque module Spring Data (et

chaque développeur!) est ensuite

libre non seulement d’

implémenter mais de spécialiser

ces contrats transverses.

Page 44: [FR] Introduction à Spring Data Neo4j 3.x

Comment Spring Data peut-il

prétendre à une API homogène

autour de stores NOSQL qui ne le

sont pas ?

Spring Data

Page 45: [FR] Introduction à Spring Data Neo4j 3.x

En introduisant

1 API commune minimaliste

Mais aussi des extensions d’

API par type de store !

Spring Data

Page 46: [FR] Introduction à Spring Data Neo4j 3.x

Exemple d’utilisation : Redbasin (article)

Idée : concilier l’immensité des informations disponibles

autour de la recherche de traitements contre le cancer

pour détecter au plus vite les traitements inefficaces.

Utilisation de Spring Data pour

Neo4j/Mongo DB/Redis/Hadoop.

Spring Data

Page 47: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j ?

Page 48: [FR] Introduction à Spring Data Neo4j 3.x

Module fils (historique!) de Commons

dédié à l’interfaçage avec … Neo4j,

fournit des entités, repositories,

templates orientés graphe !

Spring Data Neo4j

Page 49: [FR] Introduction à Spring Data Neo4j 3.x

Version actuelle : 3.1.0.RELEASE.

Depuis 3.0.0.RELEASE (24 février 2014),

Neo4j 2.0 est officiellement supporté.

Spring Data Neo4j

Page 50: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j - mapping & entités

Spring Data Neo4j

Page 51: [FR] Introduction à Spring Data Neo4j 3.x

Deux types d’entités : @NodeEntity, @RelationshipEntity

Deux modes de mapping : simple & avancé

Plusieurs stratégies de représentation des métadonnées de

mapping au sein du graphe.

Spring Data Neo4j

Page 52: [FR] Introduction à Spring Data Neo4j 3.x

Entités@NodeEntity, @RelationshipEntity

Support basique de la JSR-303 (Bean Validation)

Projection de résultats de traversées possible (via

FieldTraversalDescriptionBuilder).

Cycle de vie à la JPA : detached, attached.

Spring Data Neo4j

Page 53: [FR] Introduction à Spring Data Neo4j 3.x

@NodeEntity

public class Person {

@GraphId // Optionnel si utilisation du mapping avancé

private Long nodeId;

@Indexed(unique=true) // Index façon 2.0

private String id;

@Indexed(indexType = IndexType.FULLTEXT, indexName = "people") // Index legacy

@Size(min = 2, max = 50) // JSR-303

private String name;

@RelatedTo(type="OWNS", enforceTargetType=true) // @RelationshipEntity non requise

private Car car;

@RelatedToVia(type="FRIEND_OF", direction=Direction.INCOMING)

private Iterable<Friendship> friendships;

// [...] constructeurs, getters/setters, equals/hashCode

}

Spring Data Neo4j

Page 54: [FR] Introduction à Spring Data Neo4j 3.x

@RelationshipEntity(type = "ACTS_IN")

public class Role {

@GraphId

private Long id;

@EndNode

private Movie movie;

@StartNode

private Actor actor;

private String name; // implicitement persisté (version explicite : @GraphProperty)

@GraphTraversal(traversal=PeopleTraversalBuilder.class, params="persons")

private Iterable<Relationship> peopleRelationships;

// [...] constructeurs, getters/setters, equals/hashCode

}

Spring Data Neo4j

Page 55: [FR] Introduction à Spring Data Neo4j 3.x

Mapping avancé

Idée : intercepter les accès aux entités (classes

annotées @NodeEntity ou @RelationshipEntity) afin de les

enrichir d’informations supplémentaires.

Spring Data Neo4j

Page 56: [FR] Introduction à Spring Data Neo4j 3.x

Mapping avancé

Aspects Neo4jRelationshipBacking et Neo4jNodeBacking.

Introduction d’un champ EntityState (~noeud /

relation sous-jacente) et de méthodes de

persistence (Active Record).

Spring Data Neo4j

Page 57: [FR] Introduction à Spring Data Neo4j 3.x

Mapping simple

Chaque classe entité inclut explicitement un champ

annoté @GraphId (nécessairement de type Long) où sera

persisté l’ID technique des noeuds/relations.

Spring Data Neo4j

Page 58: [FR] Introduction à Spring Data Neo4j 3.x

Mapping, côté graphe

Différentes stratégies de représentation possibles.

Spring Data Neo4j

Noeud <-> @NodeEntity Relation <-> @RelationshipEntity

LabelBasedNodeTypeRepresentationStrategy IndexBasedRelationshipTypeRepresentationStrategy

IndexBasedNodeTypeRepresentationStrategy

SubReferenceNodeTypeRepresentationStrategy NoopRelationshipTypeRepresentationStrategy

NoopNodeTypeRepresentationStrategy

Page 59: [FR] Introduction à Spring Data Neo4j 3.x

Mapping, côté graphe

LabelBased (défaut pour noeuds): chaque noeud se voit

assigner un label correspondant au nom qualifié (ou

aliasé) de son entité Java.

Spring Data Neo4j

Page 60: [FR] Introduction à Spring Data Neo4j 3.x

Mapping, côté graphe

IndexBased (défaut pour rels): un index __types__ est

créé où sont indexés les champs __type__ ajouté

automatiquement aux noeuds/relations

Spring Data Neo4j

Page 61: [FR] Introduction à Spring Data Neo4j 3.x

Mapping, côté graphe

SubReference (legacy): l’arbre d’entités Java est

persisté comme un sous-graphe dans Neo4j. Les

noeuds du graphe s’y lient avec des relations de type

INSTANCE_OF. Il annule le mapping des relations (cf.

Noop).

Spring Data Neo4j

Page 62: [FR] Introduction à Spring Data Neo4j 3.x

Mapping, côté graphe

Noop : ne fait rien (principalement utilisé pour les tests

internes à SDN) :)

Spring Data Neo4j

Page 63: [FR] Introduction à Spring Data Neo4j 3.x

Le mapping entités-graphe est déclenché via l’utilisation

des repositories ou de Neo4jTemplate.

Spring Data Neo4j

Page 64: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j - repositories

Spring Data Neo4j

Page 65: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4jRepository<T,

ID>

CrudRepository<T, ID>

PagingAndSortingRepository<T, ID>

GraphRepository<T>

Outre les opérations de base,

cette interface expose les

opérations d’indexations (pre- et

post-2.0) et de traversée via des

interfaces intermédiaires (non

illustrées ici) comme

findAllByTraversal…T = type de l’entité

ID = type de l’identifiant technique

Page 66: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j// côté repository

public interface TweetRepository extends GraphRepository<Tweet> {

List<Tweet> findByPosterName(String poster);

}// côté service

@Service

@Transactional

public class TwitterService implements SocialService {

@Autowired // préférez par constructeur ou par setter

private TweetRepository tweetRepository;

@Transactional(readOnly = true)

public Tweets findTweetsAuthoredBy(String poster) {

return Tweets.of(tweetRepository.findByPosterName(poster));

}

}

Page 67: [FR] Introduction à Spring Data Neo4j 3.x

Il est également possible de définir des requêtes Cypher

particulières (toujours pas d’implémentation à écrire !)

public interface UserRepository extends GraphRepository<User> {

@Query( "MATCH (me:User {user:{name}})-[:POSTED]->(tweet)-[:MENTIONS]->(user)" +

" WHERE me <> user " +

" RETURN distinct user")

Set<User> suggestFriends(@Param("name") String user);

}

Spring Data Neo4j

Page 68: [FR] Introduction à Spring Data Neo4j 3.x

Il existe aussi d’autres repositories tels que

SpatialRepository (requêtes géospatiales),

CypherDslRepository<T> pour utiliser le DSL Cypher

Java et des intégrations avec QueryDSL (voire de les

combiner).

Spring Data Neo4j

Page 69: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j - template

Spring Data Neo4j

Page 70: [FR] Introduction à Spring Data Neo4j 3.x

Encapsule l’API Neo4j avec une gestion implicite des

transactions (et une optimisation des requêtes HTTP en

mode REST).

Permet la manipulation des entités et offre un système

basique d’écoute d’événements (Spring Framework) :

{Before|After}{Save|Delete}Event

Spring Data Neo4j

Page 71: [FR] Introduction à Spring Data Neo4j 3.x

Spring Data Neo4j - cross-store persistence

Spring Data Neo4j

Page 72: [FR] Introduction à Spring Data Neo4j 3.x

Permet de persister une partie des informations portée par

les entités dans Neo4j et l’autre dans un SGDBR (via JPA).

Spring Data Neo4j

Page 73: [FR] Introduction à Spring Data Neo4j 3.x

L’entité ne sera persistée dans le graphe qu’une fois

persistée dans le SGDBR (ID JPA assigné). Un champ

FOREIGN_ID (FQN + ID JPA) est ensuite ajouté au noeud

du graphe.

Les aspects de SDN rendent les champs annotés

@GraphProperty transients pour JPA.

Spring Data Neo4j

Page 74: [FR] Introduction à Spring Data Neo4j 3.x

@Entity // JPA

@NodeEntity(partial = true) // Spring Data Neo4j

public class User {

@Id

@GeneratedValue(strategy = GenerationType.TABLE, generator = "id_gen")

@TableGenerator(name = "id_gen", table = "SEQUENCE", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "SEQ_GEN", allocationSize = 1)

private Long id; // ID JPA

private String name;

@GraphProperty

@Indexed

String nickname;

@RelatedToVia(type = "recommends", elementClass = Recommendation.class)

Iterable<Recommendation> recommendations;

}

Spring Data Neo4j

Page 75: [FR] Introduction à Spring Data Neo4j 3.x

Conclusion

Page 76: [FR] Introduction à Spring Data Neo4j 3.x

?Ça continue sur Twitter (@fbiville, @LateraIThoughts, @Neo4jFr),

le Google Groups Neo4jFR,

les meetups… ;-)