순수하게 J2SE 환경에서 JPA를 사용하면 개발자가 직접 엔티티매니저를 생성하고 트랜잭션도 관리해야한다. 하지만 스프링이나 J2EE 컨테이너 환경에서 JPA를 사용하면 컨테이너가 제공하는 전략을 따라야 한다.
서비스 계층이 끝나는 시점에 트랜잭션이 종료되면서 영속성 컨텍스트도 함께 종료된다.
트랜잭션이 없는 계층(프레젠테이션 계층)에서 기본적으로 엔티티는 준영속 상태이다.
따라서 변경감지와 지연 로딩이 동작하지 않는다.
프레젠테이션 계층과 서비스 계층사이에 파사드 계층을 하나 더 두어 논리적인 의존성 분리
뷰를 위한 프록시 초기화는 이곳에서 담당함
프록시를 초기화하려면 영속성 컨텍스트가 필요하므로 FACADE에서 트랜잭션을 시작해야함
BUT 실용적인 관점에서 호출만하는 위임코드가 많아지는 오버헤드가 있을 수 있음
준영속 상태와 지연 로딩의 문제점
프레젠테이션 계층이 엔티티를 변경할 수 있다는 단점
엔티티를 수정하지 못하게 막자!
interface MemberView {
public String getName();
}
@Entity
class Member implements MemberView {
}
class MemberWrapper {
private Member member;
public MemberWrapper(member) {
this.member = member;
}
//읽기 전용 메소드만 제공
public String getName() {
member.getName();
}
위 방법들은 모두 코드량이 많아진다는 단점이 있음
OSIV를 사용하긴 하지만 트랜잭션은 비즈니스 계층에서만 사용
트랜잭션 없이 읽기
OSIV 주의 사항
컨트롤러에서 엔티티를 수정하고 바로 서비스계층을 호출할 경우 DB에 수정사항이 반영됨.
비즈니스로직을 모두 호출 후에 엔티티를 변경하도록 해야함
OSIV를 사용하지 않는다면 트랜잭션의 생명주기와 영속성 컨텍스트의 생명주기가 같으므로 이런 문제가 생기지 않음.
OSIV 사용 관련 주의점들
OSIV를 사용하면 컨트롤러에서 리포리토리 직접 호출 가능 → 좀 더 유연하고 실용적일 수 있음