프록시란
정처기공부할때 디자인패턴에서 공부했던부분이다. 다른 객체에 대한 인터페이스 역할을 하는 객체를 말한다. 실제 객체에 대한 접근을 제어하거나 추가적인 기능을 제공한다. 객체의 구조를 변경하지 않고 기능을 확장하거나 제어할 수 있게 해준다.
역할로는
1. 접근제어 : 클라이언트가 실제 객체에 직접 접근하는것을 제어함. 권한이 있는 사용자만 접근하게 한다.
2. 성능향상 : 실제 객체에 대한 접근을 지연시켜서 시스템의 성능을 최적화 할 수 있다. 불필요한 객체 생성이나 DB접근을 피할 수 있다.
EntityManager의 두가지 메서드
1. em.find() : DB에서 실제 엔티티를 조회. 메서드가 실행될 때 즉시 쿼리를 실행한다.
즉시 로딩. 엔티티가 없을 때 null을 반환 한다.
EntityManager em = entityManagerFactory.createEntityManager();
Product product = em.find(Product.class, productId);
if (product != null) {
System.out.println("Product name: " + product.getName());
} else {
System.out.println("Product not found.");
}
2. em.getReference() : DB조회를 미루는 프록시 엔티티 객체 조회. 프록시 객체를 반환하여 쿼리를 바로 실행하지않고 실제 쓰일때 쿼리를 실행하여 지연로딩을 수행한다.
지연 로딩. 엔티티가 없을 때 데이터 접근시점에 예외발생함.
EntityManager em = entityManagerFactory.createEntityManager();
Product productProxy = em.getReference(Product.class, productId);
// 데이터에 접근할 때 실제로 쿼리 실행
try {
System.out.println("Product name: " + productProxy.getName());
} catch (EntityNotFoundException e) {
System.out.println("Product not found.");
}
%주의%
프록시 객체는 처음 사용 할 때 한번만 초기화된다.
프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는게 아니다. 초기화 되면 프록시객체를 통해 실제 엔티티에 접근이 가능하다.
User user1 = new User();
user1.setName("thKim");
em.persist(user1);
em.flush();
em.clear();
User u1 = em.find(User.class, user1.getId());
System.out.println("u1 = " + u1.getClass());
User reference = em.getReference(User.class, user1.getId());
System.out.println("reference = " + reference.getClass());
실행결과 :
u1 = class jpa.User
reference = class jpa.User
왜이런 결과가 나올까? 영속성 컨텍스트에 찾는 엔티티가 있으면 em.getReference() 호출해도 실제 엔티티를 반환하기 때문이다.
지연로딩
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "product", fetch = FetchType.LAZY)
private List<Order> orders;
...
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id")
private Product product;
...
}
@OneToMany, @ManyToOne... 이 애너테이션들에 fetchType을 Lazy로 설정해준다.
즉시로딩
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 즉시 로딩 설정
@OneToMany(mappedBy = "product", fetch = FetchType.EAGER)
private List<Order> orders;
...
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 즉시 로딩은 기본값
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "product_id")
private Product product;
...
}
FetchType.EAGER 를 명시해주면 즉시로딩을 사용할 수 있다.
'Java > ORM' 카테고리의 다른 글
JAVA ORM - JPA(JPQL) (0) | 2024.08.08 |
---|---|
JAVA ORM - JPA(영속성 전이, 임베디드타입, 값타입 컬렉션) (0) | 2024.08.07 |
JAVA ORM - JPA(상속을 매핑?) (0) | 2024.08.05 |
JAVA ORM - JPA(연관관계 매핑2) (0) | 2024.08.03 |
JAVA ORM - JPA(연관관계 매핑) (0) | 2024.08.01 |