如果你是 Java 或 Spring Boot 开发者,这篇教程将从零基础开始,逐步深入,帮助你构建一个完整的 Spring Data Neo4j 应用。我们将使用实际代码示例,基于官方文档和可靠来源(如 Spring 官方指南和 Neo4j 开发者资源)。教程假设你有基本的 Java 和 Spring Boot 知识,但会逐步解释所有概念。
教程结构:
Neo4j 的优势在于遍历关系的速度远超关系型数据库,尤其在深度查询时。
SDN 的关键特性:
neo4j console,默认地址 bolt://localhost:7687,用户 neo4j/neo4j(首次需修改密码)。<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=your_password
如果使用嵌入式 Neo4j(测试用),添加:
spring.neo4j.database=neo4j # 默认数据库
启动应用:运行 main 方法,Spring Boot 会自动配置 Neo4jTemplate 和 Neo4jClient。
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
@Node("Person") // 标签为 :Person
public class Person {
@Id // 主键
private Long id;
private String name;
private Integer age;
// Getters, Setters, Constructors...
}
@Node:指定节点标签。@Id:主键,支持 Long、String 或 UUID。简单关系示例:在 Person 中添加朋友关系:
import org.springframework.data.neo4j.core.schema.Relationship;
@Node("Person")
public class Person {
@Id private Long id;
private String name;
@Relationship(type = "KNOWS", direction = Relationship.Direction.OUTGOING)
private List<Person> friends; // 一对多关系
}
复杂关系:创建一个 RelationshipEntity:
import org.springframework.data.neo4j.core.schema.RelationshipId;
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
import org.springframework.data.neo4j.core.schema.TargetNode;
@RelationshipProperties
public class Roles {
@RelationshipId private Long id;
private String role; // 关系属性
@TargetNode private Movie movie; // 目标节点
}
然后在 Actor 类中使用:
@Node("Actor")
public class Actor {
@Id private Long id;
private String name;
@Relationship(type = "ACTED_IN")
private List<Roles> roles;
}
@GeneratedValue:
@Id @GeneratedValue
private UUID uuid;
或自定义生成器。
import org.springframework.data.neo4j.repository.Neo4jRepository;
public interface PersonRepository extends Neo4jRepository<Person, Long> {
// 自动提供 save, findById, findAll, delete 等方法
}
使用:
@Service
public class PersonService {
@Autowired private PersonRepository repository;
public Person savePerson(Person person) {
return repository.save(person);
}
}
List<Person> findByName(String name);
List<Person> findByAgeGreaterThan(Integer age);
这会自动转换为 Cypher 查询,如 MATCH (p:Person) WHERE p.age > $age RETURN p。
@Query:
@Query("MATCH (p:Person)-[:KNOWS]->(f:Person) WHERE p.name = $name RETURN f")
List<Person> findFriendsByName(@Param("name") String name);
@Autowired Neo4jTemplate template;
public List<Person> findComplex() {
return template.findAll("MATCH (p:Person) WHERE p.age > 30 RETURN p", Person.class);
}
@Transactional
public void updatePerson(Long id, String newName) {
Person person = repository.findById(id).orElseThrow();
person.setName(newName);
repository.save(person);
}
public interface PersonSummary {
String getName();
Integer getAge();
}
@Query("MATCH (p:Person) RETURN p.name AS name, p.age AS age")
List<PersonSummary> getSummaries();
@EnableNeo4jAuditing,然后在实体中使用 @CreatedDate、@LastModifiedBy 等。
@DataNeo4jTest
class PersonRepositoryTest {
@Autowired PersonRepository repository;
@Test
void testSave() {
// ...
}
}
嵌入式 Neo4j 通过 Testcontainers 支持。
spring.neo4j.database=mydb
@Index 注解创建索引。@Node("User")
public class User {
@Id @GeneratedValue private Long id;
private String username;
@Relationship(type = "FOLLOW", direction = OUTGOING)
private Set<User> follows;
@Relationship(type = "POSTED", direction = OUTGOING)
private List<Post> posts;
}
@Node("Post")
public class Post {
@Id @GeneratedValue private Long id;
private String content;
private LocalDateTime createdAt;
}
public interface UserRepository extends Neo4jRepository<User, Long> {
@Query("MATCH (u:User)-[:FOLLOW*1..3]->(f:User) WHERE u.id = $id RETURN f")
List<User> findFriendsOfFriends(@Param("id") Long id);
}