Neo4j와 Spring Boot 시작하기 Getting Started with Neo4j and Spring Boot
Getting Started with Neo4j and Spring Boot
Neo4j is a graph database that excels at handling connected data. Spring Data Neo4j provides seamless integration with Spring Boot, making it straightforward to work with graph data using familiar Spring patterns.
1. Dependencies
Add the Spring Data Neo4j starter to pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
For Gradle:
implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
2. Configuration
Configure the connection in application.yml:
spring:
neo4j:
uri: bolt://localhost:7687
authentication:
username: neo4j
password: your-password
For local development, run Neo4j with Docker:
docker run -d \
--name neo4j \
-p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/your-password \
neo4j:5
Port 7474 serves the browser interface, 7687 is for Bolt protocol connections.
3. Defining Nodes
Create an entity class with @Node:
@Node
public class Person {
@Id
@GeneratedValue
private Long id;
private String name;
private Integer age;
@Relationship(type = "FRIEND_OF", direction = Direction.OUTGOING)
private List<Person> friends = new ArrayList<>();
// constructors, getters, setters
}
The @Relationship annotation defines edges in the graph. Direction matters—OUTGOING means this person has friends, INCOMING would mean others consider this person a friend.
4. Repository
Spring Data Neo4j repositories work like JPA repositories:
public interface PersonRepository extends Neo4jRepository<Person, Long> {
Optional<Person> findByName(String name);
@Query("MATCH (p:Person)-[:FRIEND_OF]->(f:Person) WHERE p.name = $name RETURN f")
List<Person> findFriendsOf(String name);
}
Derived query methods work out of the box. For complex traversals, use @Query with Cypher.
5. Basic Cypher Queries
Cypher is Neo4j’s query language. A few essential patterns:
Create a node:
CREATE (p:Person {name: 'Alice', age: 30})
Create a relationship:
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:FRIEND_OF]->(b)
Find friends of friends:
MATCH (p:Person {name: 'Alice'})-[:FRIEND_OF]->()-[:FRIEND_OF]->(fof)
WHERE fof <> p
RETURN DISTINCT fof.name
The arrow syntax ()-[]->() represents traversal direction. Variable-length paths use *: [:FRIEND_OF*2] means exactly 2 hops.
6. Service Layer
@Service
@Transactional
public class PersonService {
private final PersonRepository repository;
public PersonService(PersonRepository repository) {
this.repository = repository;
}
public Person create(String name, int age) {
Person person = new Person(name, age);
return repository.save(person);
}
public void addFriend(String personName, String friendName) {
Person person = repository.findByName(personName)
.orElseThrow(() -> new RuntimeException("Person not found"));
Person friend = repository.findByName(friendName)
.orElseThrow(() -> new RuntimeException("Friend not found"));
person.getFriends().add(friend);
repository.save(person);
}
public List<Person> getFriends(String name) {
return repository.findFriendsOf(name);
}
}
The @Transactional annotation ensures relationship modifications are atomic.
7. When to Use Neo4j
Graph databases shine for:
- Social networks (friends, followers, connections)
- Recommendation engines (users who bought X also bought Y)
- Fraud detection (finding suspicious patterns in transactions)
- Knowledge graphs and hierarchies
For simple CRUD with no complex relationships, a relational database is simpler. Neo4j adds value when queries involve traversing multiple relationship levels.
8. Conclusion
Spring Data Neo4j provides a clean abstraction over Neo4j. Define nodes with @Node, relationships with @Relationship, and use repositories for basic operations. For complex graph traversals, Cypher queries offer full control.
댓글남기기