neo4j 图数据库 springboot集成
1.springboot集成工程 ermp.neo4j
1 引入pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>3.2.10</version>
</dependency>
2 配置直接采用driver驱动版本,采用bolt方式进行连接
配置文件:
spring.data.neo4j.uri=bolt+routing://168.63.118.1:7687
spring.data.neo4j.uris=bolt+routing://168.63.118.2:7687,bolt+routing://168.63.118.3:7687
spring.data.neo4j.username=ermp
spring.data.neo4j.password=ermp_2020_ZNFK
spring.data.neo4j.blotUri=bolt://168.63.118.1
采用一主两从的数据存储结构配置
3 将dirver驱动交给spring管理
@Value("${spring.data.neo4j.blotUri}")
private String uri;
@Value("${spring.data.neo4j.username}")
private String username;
@Value("${spring.data.neo4j.password}")
private String password;
@Bean
public Driver createDriver() {
Config config =getConfig(ServerAddress.of( "168.63.118.1", 7687 ),
ServerAddress.of( "168.63.118.2", 7687 ), ServerAddress.of( "168.63.118.3", 7687 ));
return GraphDatabase.driver( uri, AuthTokens.basic( username, password ), config );
}
private Config getConfig(ServerAddress...addresses){
return Config.builder().withResolver(address -> new HashSet<>( Arrays.asList( addresses ) ) ).build();
}
2 数据增删改
neo4j提供了几种数据写法。
1 简单的数据连接:
@Autowired
private Driver driver;
@Test
public void test_1(){
demoService.demoQuery();
}
@Test
public void test_2(){
List<Record> list = driver.session().run("match(stu:Student) return (stu)").list();
list.forEach(o-> System.out.println(o.asMap().get("stu")));
}
直接以驱动写入cypher语句的方式进行对库的操作,#{}可传入参数。
2 封装式写法 --类似jpa(推荐):
@Repository
public interface UserRepository extends Neo4jRepository<UserNode,Long> {
@Query("MATCH (n) WHERE id(n) = :#{#userNode.nodeId} SET n.name = :#{#userNode.name},n.age = :#{#userNode.age},n.sex = :#{#userNode.sex} RETURN n")
UserNode updateByNode(@Param("userNode") UserNode userNode);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private KnowRepository knowRepository;
@Override
public UserNode create(UserNode userNode) {
return userRepository.save(userNode);
}
@Override
public void deleteById(Long id) {
userRepository.deleteById(id);
}
@Override
public void deleteAll() {
userRepository.deleteAll();
}
@Override
public Optional<UserNode> findById(long id) {
return userRepository.findById(id);
}
@Override
public List<UserNode> findByName(String name) {
Iterator<UserNode> iterator = userRepository.findAll().iterator();
return IteratorUtils.toList(iterator);
}
@Override
public List<UserNode> findAll() {
return (List<UserNode>) userRepository.findAll();
}
@Override
public Know addIKnows(UserNode fromNode, UserNode toNode) {
Know newKnow = new Know(fromNode,toNode);
return knowRepository.save(newKnow);
}
@Override
public UserNode updateByNode(UserNode userNode) {
return userRepository.updateByNode(userNode);
}
@Override
public void deleteKnowByNodeId(long fromId, long toId) {
knowRepository.deleteByNodeId(fromId,toId);
}
关系映射绑定:Relationship--RelationshipEntity 两个注解的映射
/*注意这个地方:并不是说加了这个注解,然后下面实现了addKnows这个方法在以后调用addKnows
就可以实现关系的增加,这是不对的,我看了很多教程没有说明。这个addKnows方法,只有在节点未被
添加之前,调用该方法添加关系,然后再调用UserService中的create方法,这样关系才会同时被添加到图
数据库中。如果想实现两个已有节点之间增加关系,需要单独实现*/
@Relationship(type = "xing" ,direction = Relationship.OUTGOING)
private Set<UserNode> knows = new HashSet<>();
@RelationshipEntity(type = "know")
@Data
public class Know {
@Id
@GeneratedValue
private Long id;
@StartNode
private UserNode from;
@EndNode
private UserNode to;
public Know(UserNode from, UserNode to) {
this.from = from;
this.to = to;
}
}
这样就可以完成java对neo4j的所有操作。
3 关系效率
@Test
public void addUserNode3() {
long currentTimeMillis = System.currentTimeMillis();
/*ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS
, new ArrayBlockingQueue(40));
threadPoolExecutor.execute(new UserTestThread());*/
for(int i=1;i<10000;i++){
UserNode userNode3=new UserNode();
userNode3.setAge(18+i);
userNode3.setKnows(null);
userNode3.setName("张三"+i);
userNode3.setSex("男");
userService.create(userNode3);
UserNode userNode=new UserNode();
userNode.setAge(18+i);
userNode.setKnows(null);
userNode.setName("李四"+i);
List<UserNode> byName = userService.findByName("张三" + (i - 1));
Set<UserNode> userNodes = new HashSet<>(byName);
userNode.setKnows(userNodes);
userNode.setSex("男");
UserNode userNode1 = userService.create(userNode);
log.info("userNode1:{}",userNode1);
userNodes.forEach(o->userService.addIKnows(o, userNode1));
}
long currentTimeMillis2 = System.currentTimeMillis();
log.info("共耗时 ==== {}",currentTimeMillis2-currentTimeMillis);
}
插入一万条数据,耗时122s,大概一秒一千条。
这种测试效率有点不准确。
4 实施方案
项目初始化时间需要很长:
csv导入不如neo4j-import
但neo4j-import初始化步骤有些复杂,需要谨慎使用
将事实和关系单独插入,先插事实元素,对应关系映射单独写。
实施作业前需要数据清洗(很重要)

浙公网安备 33010602011771号