열심히 JPA를 공부하고 SpringData 및 JpaRepository 내용을 정리해본다.
Spring Data는 Spring 프레임워크에서 데이터 액세스 계층을 간편하게 개발할 수 있도록 도와주는 프로젝트이다. 다양한 데이터베이스 및 데이터 저장소와 통합되어 데이터 액세스 코드를 표준화하고 단순화하는 목적으로 만들어진 덕분에, 개발자는 일관된 방식으로 다양한 데이터 소스에 액세스 할 수 있다. 아주 고맙다!
감상: 다양하다.
• 강력한 리포지토리 및 사용자 지정 객체 매핑 추상화 --> ORM을 말하는 것
• 리포지토리 메서드 이름에서 동적 쿼리 파생 --> 메서드명만 작성하면 여러 쿼리가 날아가는것
• 기본 속성을 제공하는 구현 도메인 기본 클래스 --> @Entity 등 사용해서 기본 속성 부여 가능
• 명료한 추적기능 지원(생성일시, 마지막 변경일시, 생성자, 마지막 변경자) --> Auditing 기능
• 사용자 지정 리포지토리 코드 통합 가능성
• JavaConfig 및 사용자 지정 XML 네임스페이스를 통한 간편한 Spring 통합 --> 쓸 일 x
• Spring MVC 컨트롤러와의 고급 통합 --> 해이시옷? 하이퍼링크?
• 교차 스토어 지속성에 대한 실험적 지원 --> 사용x
// 변경 전
@Repository
public class UserRepository {
@PersistenceContext
EntityManager entityManager;
public User insertUser(User user) {
entityManager.persist(user);
return user;
}
public User selectUser(Long id) {
return entityManager.find(User.class, id);
}
}
// 변경 후
public interface UserRepository extends JpaRepository<User, Long> {
}
JpaRepository 는 기본적으로 모든 기능을 제공하기 때문에 리스크가 있을 수 있다.
따라서, 아래와 같은 방법으로 원하는 기능 메소드만 구현하도록 제한할 수 있다.
@RepositoryDefinition
을 인터페이스에 붙이는법가장 많이 쓰이는 방법으로, 이 어노테이션을 붙이면 BeanDefinition 에 직접 접근하여 프로그래밍으로 주입받을 구현체 메소드들을 지정해서 요청할 수 있다.
@RepositoryDefinition(domainClass = Comment.class, idClass = Long.class)
public interface CommentRepository {
Comment save(Comment comment);
List<Comment> findAll();
}
상위 인터페이스 개념을 하나 더 만들어서 열어줄 메소드만 선언해준다.
@NoRepositoryBean
public interface MyRepository<T, ID extends Serializable> extends Repository<T, ID> {
<E extends T> E save(E entity);
List<T> findAll();
}
delete() 메서드를 예시로 들어보자.
delete() 메소드의 내부 기능의 경우 delete 호출시 영속성 상태인지 확인한다.
영속상태면 그대로 remove, 비영속 상태면 find해오고, 준영속(detached) 상태면 merge해서 다시 조회해온다.
이렇게 하는 이유는 casecade, orphanremoval 도 사용하기 위함이다. 하지만 그 때문에 delete의 성능이 그렇게 좋진 않다.
만약 casecade, orphanremoval 가 작동 할 필요가 없다면 오버라이딩(커스터마이징)해서 사용 할 수 있다.
@Repository
@Transactional
public class MyRepositoryImpl implements MyRepository {
@Autowired
EntityManager entityManager;
@Override
public void delete(User user) {
entityManager.remove(user);
}
}
simpleJPA의 remove가 아닌 remove를 있는 그대로 호출한것아라 확인과정 없이 바로 삭제 쿼리가 날아간다.
이렇게 delete를 만들어줬을 때, 아래와같이 선택해서 사용하도록 뜬다.