Neo4j框架学习之三项目整合

java api操作

​ java api操作neo4j框架类似于创建jdbc连接(图数据也是数据库嘛)

public static void main(String[] args) {
          //获取neo4j的驱动
          Driver driver = GraphDatabase.driver("bolt://172.16.2.207:7687", AuthTokens.basic("neo4j", "neo4j123"));
          Session session = null;
          Transaction transaction = null;
          try {
              //获取会话 connection
              session = driver.session();
              //开启事务
              transaction = session.beginTransaction();
              //创建Statement
              Statement query = new Statement(
                      "CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)",
                      Values.parameters("message", "testDriver"));

              StatementResult result = transaction.run(query);
              //提交事务
              transaction.success();
              String greeting = result.single().get(0).asString();
              System.out.println(greeting);
          }catch (Exception e){
              //事务回滚
              transaction.rollbackAsync();
          }
          finally {
              //关闭相关资源
              if(session.isOpen()){
                  session.close();
              }
              if(transaction.isOpen()){
                  transaction.close();
              }
              driver.close();
          }
      }

springBoot整合neo4j

相关配置

依赖

springBoot版本:2.1.5.RELEASE

<dependency> 
	<groupId>org.springframework.boot</groupId> 
	<artifactId>spring-boot-starter-data-neo4j</artifactId> 
</dependency>

配置

# neo4j配置 
spring:
  data:
    Neo4j:
      uri: bolt://172.16.2.207:7687
      username: neo4j
      password: neo4j123

例子

​ neo4j数据库使用类似于spring-data的JPA,设置实体(Entity)、Dao层(Repository)

设置实体

//任务对象
@Data
@NodeEntity(label = "Person")
public class Person {
    @Id
    @GeneratedValue
    private Long id;

    @Property(name = "name")
    private String name;

    @Property(name = "title")
    private String title;
}

//关系
@Data
@RelationshipEntity
public class Relation {
    @Id
    @GeneratedValue
    private Long id;

    @Property(name = "name")
    private String name;

    /**
     * 关系方向 StartNode -指向-> EndNode
     */
    @StartNode
    private Person from;

    @EndNode
    private Person to;
}
  • @NodeEntity:标明是一个节点实体
  • @RelationshipEntity:标明是一个关系实体
  • @Id:实体主键
  • @Property:实体属性
  • @GeneratedValue:实体属性值自增
  • @StartNode:开始节点(可以理解为父节点)
  • @EndNode:结束节点(可以理解为子节点)

dao层

dao层可以继承org.springframework.data.neo4j.repository.Neo4jRepository接口,这个接口有基础的curd相关接口,对于其他复杂sql我们可以使用@Query 编写一些复杂的语句

@Repository
public interface PersonRepository extends Neo4jRepository<Person,Long> {

    @Query("MATCH p=(n:Person) RETURN p")
    List<Person> selectAll();

    @Query("MATCH(p:Student{name:{name}}) return p")
    Person findByName(String name);
    
    @Query(
            "MERGE (p:Person { name:{0}})"+
                    "SET p.title = {1}"+
                    "RETURN p")
    Person merge(String name,String title);
}

service服务层

public class PersonServiceImpl implements PersonService {
    @Resource
    private PersonRepository personRepository;
    @Override
    public boolean save(Person person) {
        boolean susFlag = true;
        try{
            personRepository.save(person);
        }catch (Exception e){
            log.error("保存person数据失败,异常信息:",e);
            susFlag = false;
        }
        return susFlag;
    }

    @Override
    public List<Person> selectAll() {
        return personRepository.selectAll();
    }

    @Override
    public Person findByName(String name) {
        return personRepository.findByName(name);
    }
}

单元测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Neo4jApplication.class)
@WebAppConfiguration
@Slf4j
public class PersonTest {
    @Resource
    private PersonService personService;
    @Test
    public void savePersonTest(){
        Person person = new Person();
        person.setName("小猪妖");
        person.setTitle("大王待我很不错");
        personService.save(person);
    }
    @Test
    public void queryOne(){
        Person person = personService.findByName("小猪妖");
        log.info("查询出来的学生信息:{}", JsonUtil.obj2str(person));
    }
    @Test
    public void queryList(){
        List<Person> personList = personService.selectAll();
        log.info("查询出来的学生信息:{}", JsonUtil.obj2str(personList));
    }
}

springBoot整合原理

​ 通过spring自动装配,会加载spring-boot-autoconfig下的spring.factories中的自动装配类,其中自动装配类有很多,与neo4j有关自动装配类有两个Neo4jDataAutoConfiguration、Neo4jRepositoriesAutoConfiguration。

自动装配类描述
Neo4jDataAutoConfiguration配置与neo4j有关的SqlSessionFactory、事务管理TransactionManager
Neo4jRepositoriesAutoConfiguration类似于spring JPA的支持
SqlSessionFactory是创建SqlSession的工厂类
SqlSessionneo4j执行一次图数据库操作(读写)的会话
TransactionManagerneo4j的事务管理,同mysql数据库一样也支持开启事务、提交和回滚

neo4j事务

​ neo4j框架的默认隔离级别为–>读已提交:每次事务只能看到已经提交的数据。

默认neo4j每次cypher语句都会开始事务,对于复杂业务多个cypher可以借助spring的事务管理器去控制事务(硬编码的形式也可)

配置事务管理器

@Configuration
@EnableTransactionManagement
@EnableNeo4jRepositories(basePackages = {"com.xiu.study.neo4j.repository"})
@EntityScan(basePackages = {"com.xiu.study.neo4j.domain"} )
@DependsOn("sessionFactory")
public class TransactionAspect {
    /**
     * 定义neo4j事务管理器
     * @param sessionFactory
     * @return neo4j事务管理器
     */
    @Bean("neo4jTransactionManager")
    public Neo4jTransactionManager neo4jTransactionManager(SessionFactory sessionFactory) {
        return new Neo4jTransactionManager(sessionFactory);
    }
}

那么只需要在需要添加事务的服务方式上使用Spring的@Transactional()即可。

neo4j事务与mysql事务冲突处理

​ 当项目中同时需要使用mysql框架和neo4j框架同时因为使用spring的事务管理无法支持多个数据源的事务处理,默认生效的是mysql事务,所有我们需要显示的配置多个事务管理器放入spring容器,在使用时候需要显示的指明使用哪种类型的事务管理器去管理事务。示例如下:

@Configuration
@EnableTransactionManagement
@EnableNeo4jRepositories(basePackages = {"com.xiu.study.neo4j.repository"})
@EntityScan(basePackages = {"com.xiu.study.neo4j.domain"} )
@DependsOn("sessionFactory")
public class TransactionAspect {
    /**
     * 定义mysql事务管理器,必须有transactionManager作为默认事务管理器
     */
    @Bean("transactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 定义neo4j事务管理器
     */
    @Bean("neo4jTransactionManager")
    public Neo4jTransactionManager neo4jTransactionManager(SessionFactory sessionFactory) {
        return new Neo4jTransactionManager(sessionFactory);
    }
}

使用neo4j @Transactional注解中显示的指定使用 neo4jTransactionManager 事务管理器。

@Transactional(value="neo4jTransactionManager",rollbackFor = Exception.class)
@Override
public boolean save(Person person) {
    boolean susFlag = true;
    personRepository.save(person);
    //模拟错误,查看事务回滚情况
    int i = 1/0;
    person.setName("乌鸦");
    personRepository.save(person);
    return susFlag;
}

版权声明:本文为liushangzaibeijing原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。