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.
2. $(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 !)
3. Spring Data Neo4j - au menu
1. Spring ?
2. Spring Data ?
3. Spring Data Neo4j ?
7. 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
8. 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
9. Dependency Injection - idée
Ne pas assembler InstantMessagingClient soi-
même, déléguer plutôt à une brique logicielle tierce.
Spring
10. 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
12. 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
13. 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
14. 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
15. À ses débuts (2003)
Spring == Spring Framework == framework de DI
Devient un standard de facto (vs. le standard officiel J2EE)
Spring
21. 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
26. Les ORM peuvent s’appuyer
sur le standard SQL commun aux SGDBR.
Spring Data
27. Il n’existe aucun standard partagé par les stores NOSQL.
Spring Data
28. Comment Spring Data peut-il
prétendre à une API homogène
autour de stores NOSQL qui ne le
sont pas ?
Spring Data
29. 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
30. 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
32. 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
34. 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
35. 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
36. 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
38. @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
39. Méthodes finder dynamiques
Aucune écriture d’implémentation de PersonRepository !
Les développeurs se focalisent sur le code métier
(JdbcPersonService).
Spring Data
40. 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
41. 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
42. 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
43. 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.
44. Comment Spring Data peut-il
prétendre à une API homogène
autour de stores NOSQL qui ne le
sont pas ?
Spring Data
45. En introduisant
1 API commune minimaliste
Mais aussi des extensions d’
API par type de store !
Spring Data
46. 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
48. Module fils (historique!) de Commons
dédié à l’interfaçage avec … Neo4j,
fournit des entités, repositories,
templates orientés graphe !
Spring Data Neo4j
49. Version actuelle : 3.1.0.RELEASE.
Depuis 3.0.0.RELEASE (24 février 2014),
Neo4j 2.0 est officiellement supporté.
Spring Data Neo4j
51. 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
52. 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
53. @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
54. @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
55. 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
56. 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
57. 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
58. 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
59. 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
60. 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
61. 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
62. Mapping, côté graphe
Noop : ne fait rien (principalement utilisé pour les tests
internes à SDN) :)
Spring Data Neo4j
63. Le mapping entités-graphe est déclenché via l’utilisation
des repositories ou de Neo4jTemplate.
Spring Data Neo4j
65. Spring Data Neo4j
Repository<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
66. 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));
}
}
67. 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
68. 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
70. 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
72. 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
73. 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
74. @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