즉, 영속성 컨텍스트는 EntityManager를 생성할 때 만들어지며 EntityManager를 통해 영속성 컨텍스트에 접근하고 관리합니다.
@Autowired
로 사용할 수 있습니다.@Autowired
private EntityManager entityManager;
Query Method
// Query Method
// 1. Repository 인터페이스에 간단한 네이밍 룰을 이용하여 메소드를 작성하면 메소드 이름을 분석하여 JPQL 쿼리를 실행하는 방법
// ex) findById(), findByName()
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLastname(String lastname);
}
// 2. NamedQuery
// @Entity 클래스에 @NamedQuery 애너테이션을 추가하여 사용
// Member.class
import javax.persistence.*;
@Entity
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member where m.username = :username"
)
public class Member {
...
}
// MemberRepository.interface
public interface MemberRepository extends JpaRepository<Member, Long> {
List<Member> findByUsername(@Param("username") String username);
}
// 3. Query 어노테이션 사용
// @Query 어노테이션을 추가한 뒤 JPQL을 작성한 방식
// 조건이 많아질 경우 메서드 이름만으로 개발하기에 한계 발생할 수 있으므로 실무에서 많이 사용
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.username= :username and m.age = :age")
List<Member> findUser(@Param("username") String username, @Param("age") int age);
}
User findUser1 = entityManager.find("User.class", "1L");
User findUser2 = entityManager.find("User.class", "1L");
System.out.print(findUser1 == findUser2) // Result: true
Dirty Checking의 흐름
1. 트랜잭션을 커밋하면 entityManager의 내부에서 먼저 플러시가 호출됩니다.
2. 엔티티와 스냅샷을 비교하여 변경된 엔티티를 찾습니다.
3. 변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL 저장소에 저장합니다. -> sql 쿼리를 한 번에 보내기 위해 쓰기 지연 저장소를 사용
4. 쓰기 지연 저장소의 SQL을 플러시합니다.
5. 데이터베이스 트랜잭션을 커밋합니다.
Flush와 Commit 차이
- Flush는 쿼리를 DB에 전송하는 역할
- Commit은 Flush를 수행한 뒤 트랜잭션을 끝내는 역할
Flush로 전송된 쿼리는 Rollback이 가능하지만, Commit은 트랜잭션이 끝나기 때문에 Rollback이 불가능합니다.
드디어 영속성컨텍스트에 대해 학습을 시작하셨군요 !
영속성컨텍스트를 잘 활용하면 최적화 및 성능 개선에 큰 도움이 되실듯합니다