Introdução ao Spring Data Neo4j

Introdução ao Spring Data Neo4j

1. Visão geral

Este artigo éan introduction to Spring Data Neo4j, o popular banco de dados de gráficos.

Spring Data O Neo4j permite o desenvolvimento baseado em POJO para o Neo4j Graph Database e usa conceitos familiares do Spring, como classes de modelo para uso principal da API, e fornece um modelo de programação baseado em anotação.

Além disso, muitos desenvolvedores não sabem realmente se o Neo4j será realmente uma boa opção para suas necessidades específicas; aqui estáa solid overview no Stackoverflow discutindo por que usar o Neo4j e os prós e contras.

2. Dependências do Maven

Vamos começar declarando as dependências do Spring Data Neo4j nopom.xml. Os módulos Spring mencionados abaixo também são necessários para o Spring Data Neo4j:


    org.springframework.data
    spring-data-neo4j
    5.0.1.RELEASE


    org.neo4j
    neo4j-ogm-test
    3.1.2
    test

Essas dependências incluem os módulos necessários para teste também.

Observe que a última dependência tem o escopo definido como 'teste'. Mas também observe que, em um desenvolvimento de aplicativo do mundo real, é mais provável que você tenha um servidor Neo4J completo em execução.

Se queremos usar o servidor incorporado, também precisamos adicionar a dependência:


    org.neo4j
    neo4j-ogm-embedded-driver
    3.1.2

As dependênciasspring-data-neo4j,neo4j-ogm-testeneo4j-ogm-embedded-driver estão disponíveis no Maven Central.

3. Configuração Neo4Jj

A configuração do Neo4j é muito direta e define a configuração de conexão para o aplicativo se conectar ao servidor. Semelhante à maioria dos outros módulos de dados do spring, esta é uma configuração do spring que pode ser definida como XML ou Java.

Neste tutorial, usaremos apenas a configuração baseada em Java:

public static final String URL =
  System.getenv("NEO4J_URL") != null ?
  System.getenv("NEO4J_URL") : "http://neo4j:[email protected]:7474";

@Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
    org.neo4j.ogm.config.Configuration config = new Builder().uri(URL).build();
    return config;
}

@Bean
public SessionFactory getSessionFactory() {
    return new SessionFactory(getConfiguration(),
      "com.example.spring.data.neo4j.domain");
}

@Bean
public Neo4jTransactionManager transactionManager() {
    return new Neo4jTransactionManager(getSessionFactory());
}

Como mencionado acima, a configuração é simples e contém apenas duas configurações. Primeiro - oSessionFactory is referenciando os modelos que criamos para representar os objetos de dados. Em seguida, as propriedades da conexão com os terminais do servidor e as credenciais de acesso.

O Neo4j inferirá a classe do driver com base no protocolo do URI, no nosso caso "http".

Observe que, neste exemplo, as propriedades relacionadas à conexão são configuradas diretamente no servidor; no entanto, em um aplicativo de produção, eles devem ser adequadamente externalizados e fazer parte da configuração padrão do projeto.

4. Repositórios Neo4j

Alinhando com a estrutura do Spring Data, o Neo4j suporta o comportamento de abstração do repositório do Spring Data. Isso significa que o acesso ao mecanismo persistente subjacente é abstraído nosNeo4jRepository embutidos, onde um projeto pode estendê-lo diretamente e usar as operações fornecidas prontas para usar.

Os repositórios são extensíveis por métodos localizadores anotados, nomeados ou derivados. Suporte para repositórios Spring Data Neo4j também são baseados emNeo4jTemplate, então a funcionalidade subjacente é idêntica.

4.1. Criando oMovieRepository &PersonRepository

Usamos dois repositórios neste tutorial para persistência de dados:

@Repository
public interface MovieRepository extends Neo4jRepository {

    Movie findByTitle(@Param("title") String title);

    @Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m")
    Collection
      findByTitleContaining(@Param("title") String title);

    @Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:Person)
      RETURN m.title as movie, collect(a.name) as cast LIMIT {limit}")
    List> graph(@Param("limit") int limit);
}

Como você pode, o repositório contém algumas operações personalizadas, bem como as padrão herdadas da classe base.

Em seguida, temos oPersonRepository mais simples, que tem apenas as operações padrão:

@Repository
public interface PersonRepository extends Neo4jRepository  {
    //
}

Você já deve ter notado quePersonRepository é apenas a interface padrão do Spring Data. Isso ocorre porque, neste exemplo simples, é quase suficiente usar as operações embutidas basicamente porque nosso conjunto de operações está relacionado à entidadeMovie. No entanto, você sempre pode adicionar aqui operações personalizadas que podem envolver operações únicas / múltiplas embutidas.

4.2. Configurando Neo4jRepositories

Como próximo passo, temos que informar ao Spring o repositório relevante, indicando-o na classeNeo4jConfiguration criada na seção 3:

@Configuration
@ComponentScan("com.example.spring.data.neo4j")
@EnableNeo4jRepositories(
  basePackages = "com.example.spring.data.neo4j.repository")
public class MovieDatabaseNeo4jConfiguration {
    //
}

5. O modelo de dados completo

Já começamos a olhar para o modelo de dados, então vamos agora colocar tudo para fora - osMovie, RoleePerson completos. A entidadePerson faz referência à entidadeMovie por meio do relacionamentoRole.

@NodeEntity
public class Movie {

    @Id @GeneratedValue
    Long id;

    private String title;

    private int released;

    private String tagline;

    @Relationship(type="ACTED_IN", direction = Relationship.INCOMING)

    private List roles;

    // standard constructor, getters and setters
}

Observe como anotamosMovie com@NodeEntity para indicar que esta classe está diretamente mapeada para um nó no Neo4j.

@JsonIdentityInfo(generator=JSOGGenerator.class)
@NodeEntity
public class Person {

    @Id @GeneratedValue
    Long id;

    private String name;

    private int born;

    @Relationship(type = "ACTED_IN")
    private List movies;

    // standard constructor, getters and setters
}

@JsonIdentityInfo(generator=JSOGGenerator.class)
@RelationshipEntity(type = "ACTED_IN")
public class Role {

    @Id @GeneratedValue
    Long id;

    private Collection roles;

    @StartNode
    private Person person;

    @EndNode
    private Movie movie;

    // standard constructor, getters and setters
}

Claro, essas duas últimas classes são anotadas de forma semelhante e a referência -movies está ligandoPerson à classeMovie pelo relacionamento “ACTED_IN”.

6. Acesso a dados usando MovieRepository

6.1. Salvar um novo objeto de filme

Vamos salvar alguns dados - primeiro, um novo filme, depois uma pessoa e, é claro, uma função - incluindo todos os dados de relação que temos também:

Movie italianJob = new Movie();
italianJob.setTitle("The Italian Job");
italianJob.setReleased(1999);
movieRepository.save(italianJob);

Person mark = new Person();
mark.setName("Mark Wahlberg");
personRepository.save(mark);

Role charlie = new Role();
charlie.setMovie(italianJob);
charlie.setPerson(mark);
Collection roleNames = new HashSet();
roleNames.add("Charlie Croker");
charlie.setRoles(roleNames);
List roles = new ArrayList();
roles.add(charlie);
italianJob.setRoles(roles);
movieRepository.save(italianJob);

6.2. Recuperando um objeto de filme existente por título

Vamos agora verificar o filme inserido, recuperando-o usando o título definido, que é uma operação personalizada:

Movie result = movieRepository.findByTitle(title);

6.3. Recuperando um objeto de filme existente por uma parte do título

É possível pesquisar para pesquisar um filme existente usando uma parte do título:

Collection result = movieRepository.findByTitleContaining("Italian");

6.4. Recuperando todos os filmes

Todos os filmes podem ser recuperados uma vez e podem ser verificados para a contagem correta:

Collection result = (Collection) movieRepository.findAll();

No entanto, existem vários métodos de busca fornecidos com comportamento padrão que são úteis para os requisitos alfandegários e nem todos são descritos aqui.

6.5. Conte os objetos de filme existentes

Depois de inserir vários objetos de filme, podemos sair da contagem de filmes:

long movieCount = movieRepository.count();

6.6. Excluindo um Filme Existente

movieRepository.delete(movieRepository.findByTitle("The Italian Job"));

Após excluir o filme inserido, podemos procurar o objeto do filme e verificar se o resultado é nulo:

assertNull(movieRepository.findByTitle("The Italian Job"));

6.7. Excluir todos os dados inseridos

É possível excluir todos os elementos no banco de dados, deixando o banco de dados vazio:

movieRepository.deleteAll();

O resultado desta operação remove rapidamente todos os dados de uma tabela.

7. Conclusão

Neste tutorial, examinamos o básico do Spring Data Neo4j usando um exemplo muito simples.

No entanto, o Neo4j é capaz de atender a aplicativos muito avançados e complexos, com um enorme conjunto de relações e redes. E o Spring Data Neo4j também oferece recursos avançados para mapear classes de entidade anotadas para o Neo4j Graph Database.

A implementação dos trechos de código e exemplos acima podem ser encontrados emthe GitHub project - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.