Springboot2.1.3集成NEO4J
对应NEO4J 服务器版本
neo4j-community-3.5.5
注意:该代码对其余的版本不一定适配
cypher语言学习地址
https://neo4j.com/docs/cypher-manual/3.5/clauses/match/
MAVEN依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.1.3.RELEASE</version>
</dependency>
<!-- add this dependency if you want to use the embedded driver -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<version>3.1.7</version>
</dependency>
<!-- add this dependency if you want to use the HTTP driver -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-http-driver</artifactId>
<version>3.1.7</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<version>3.1.7</version>
</dependency>
</dependencies>
配置
重命名neo4jSessionFactory,防止与已有的sessionFactory命名冲突,固定实体包与接口包扫描路径。因为扫描所有路径的包,发现了有些问题。
import java.util.List;
import org.neo4j.ogm.session.SessionFactory;
import org.neo4j.ogm.session.event.EventListener;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.data.neo4j.Neo4jProperties;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
@Configuration
@EnableNeo4jRepositories(
basePackages = "com.neo4j.repository",
sessionFactoryRef = "neo4jSessionFactory",
transactionManagerRef="neo4jTransaction"
)
@EntityScan(basePackages = "com.neo4j.model")
@EnableTransactionManagement
@EnableConfigurationProperties(Neo4jProperties.class)
public class Neo4jConfiguration {
@Bean
public org.neo4j.ogm.config.Configuration configuration(Neo4jProperties properties) {
return properties.createConfiguration();
}
@Bean("neo4jSessionFactory")
public SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration,
ApplicationContext applicationContext,
ObjectProvider<EventListener> eventListeners) {
SessionFactory sessionFactory = new SessionFactory(configuration,
getPackagesToScan(applicationContext));
eventListeners.stream().forEach(sessionFactory::register);
return sessionFactory;
}
@Bean("neo4jTransaction")
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory,
Neo4jProperties properties,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
return customize(new Neo4jTransactionManager(sessionFactory),
transactionManagerCustomizers.getIfAvailable());
}
private String[] getPackagesToScan(ApplicationContext applicationContext) {
List<String> packages = EntityScanPackages.get(applicationContext)
.getPackageNames();
if (packages.isEmpty() && AutoConfigurationPackages.has(applicationContext)) {
packages = AutoConfigurationPackages.get(applicationContext);
}
return StringUtils.toStringArray(packages);
}
private Neo4jTransactionManager customize(Neo4jTransactionManager transactionManager,
TransactionManagerCustomizers customizers) {
if (customizers != null) {
customizers.customize(transactionManager);
}
return transactionManager;
}
}
application.properties配置
spring.data.neo4j.password=123456
spring.data.neo4j.username=neo4j
spring.data.neo4j.uri=bolt://127.0.0.1:7687
实体定义
用NodeEntity注解
@Data
@NodeEntity(Constants.CODE_MODEL)
public class CodeModel {
@Id
@GeneratedValue
private Long id;
private String projectId;
private String docCode;
}
关系定义
用@RelationshipEntity注解
@Data
@RelationshipEntity(Constants.RELATION)
public class Relation {
@Id
@GeneratedValue
private Long id;
@StartNode
private Neo4jDocIdModel startNode;
@EndNode
private Neo4jDocCodeModel endNode;
}
自定义查询
使用 org.neo4j.ogm.session.Session查询
注意此处参数的设置。
@GetMapping(value = "/list")
public Result<?> queryPageList(
@RequestParam("relationId") String relationId,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
StringBuilder cypher = new StringBuilder();
cypher.append(String.format("MATCH p=(n:%s)-[:%s {relationId: '%s'}]->(m:%s)",
Constants.MODEL,
Constants.RELATION,
relationId,
Constants.CODE_MODEL
));
cypher.append(" where n.tag = {tag} ");
String queryStr = " return n.tag as tag ,m.docCode as docCode skip {skip} limit {limit}";
String countStr = " return count(p) ";
HashMap<String, Object> params = new HashMap<>();
params.put("tag", "P-011");
params.put("skip", (pageNo-1)*pageSize);
params.put("limit", pageSize);
org.neo4j.ogm.model.Result query = neo4jSession.query(cypher + queryStr, params);
long count = neo4jSession.queryForObject(Long.class, cypher + countStr, params);
Iterable<Map<String, Object>> results = query.queryResults();
Page<Map<String, Object>> page = new Page<>();
page.setRecords((List<Map<String, Object>>) results);
page.setTotal(count);
return Result.ok(page);
}
接口里的自定义查询
@Query(""
+ "MATCH (n:Person) WHERE n.name = $name RETURN n "
+ "ORDER BY n.name ASC SKIP $skip LIMIT $limit"
)
Slice<Person> findSliceByName(String name, Pageable pageable);
@Query(
value = ""
+ "MATCH (n:Person) WHERE n.name = $name RETURN n "
+ "ORDER BY n.name ASC SKIP $skip LIMIT $limit",
countQuery = ""
+ "MATCH (n:Person) WHERE n.name = $name RETURN count(n)"
)
Page<Person> findPageByName(String name, Pageable pageable);