문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 다음 판 | 이전 판 | ||
java:jpa:one-to-one [2012/01/09 15:43] kwon37xi [Primary Key 기반 One-To-One] |
java:jpa:one-to-one [2018/06/29 08:41] (현재) kwon37xi [게시판 형태에서 게시글에 대해 One-To-One LazyLoading 구현] |
||
---|---|---|---|
줄 1: | 줄 1: | ||
====== JPA One-To-One ====== | ====== JPA One-To-One ====== | ||
* [[http:// | * [[http:// | ||
- | |||
- | ====== JPA One-To-One ====== | ||
* One-To-One 관계가 정말로 필요한지 고민하라. | * One-To-One 관계가 정말로 필요한지 고민하라. | ||
* [[http:// | * [[http:// | ||
- | ====== Primary Key 기반 One-To-One JPA 2 방식 | + | ===== Primary Key 기반 One-To-One JPA 2 방식 ===== |
- | * **[[http:// | + | * **[[http:// |
+ | * '' | ||
+ | * Hibernate에서 '' | ||
+ | @Entity | ||
+ | class MedicalHistory implements Serializable { | ||
+ | @Id | ||
+ | @Column(name = " | ||
+ | Integer id; | ||
+ | @MapsId | ||
+ | @OneToOne | ||
+ | @JoinColumn(name = " | ||
+ | Person patient; | ||
+ | } | ||
+ | |||
+ | @Entity | ||
+ | class Person { | ||
+ | @Id @GeneratedValue Integer id; | ||
+ | } | ||
+ | </ | ||
+ | * 주의! 양뱡향 매핑의 경우, **부모에 자식값을 설정하고, | ||
===== Primary Key 기반 One-To-One JPA 1 방식===== | ===== Primary Key 기반 One-To-One JPA 1 방식===== | ||
<code java> | <code java> | ||
줄 18: | 줄 35: | ||
@OneToOne(cascade = CascadeType.ALL, | @OneToOne(cascade = CascadeType.ALL, | ||
- | @primaryKeyJoinColumn | + | @PrimaryKeyJoinColumn |
private Child child; | private Child child; | ||
줄 40: | 줄 57: | ||
===== One-To-One 과 Lazy Loading ===== | ===== One-To-One 과 Lazy Loading ===== | ||
* One-To-One 에서는 Lazy Loading이 잘 작동하지 않는다. | * One-To-One 에서는 Lazy Loading이 잘 작동하지 않는다. | ||
- | - 이유는 null 값이 가능한 OneToOne의 경우 프록시 객체로 감쌀 수 없기 때문이다. | + | - **이유는 null 값이 가능한 OneToOne의 경우('' |
- 만약 null 값이 가능한 OneToOne 에 프록시 객체를 넣는다면, | - 만약 null 값이 가능한 OneToOne 에 프록시 객체를 넣는다면, | ||
- 따라서 JPA 구현체는 기본적으로 One-To-One 관계에 Lazy 를 허용하지 않고, 즉시 값을 읽어 들인다. | - 따라서 JPA 구현체는 기본적으로 One-To-One 관계에 Lazy 를 허용하지 않고, 즉시 값을 읽어 들인다. | ||
+ | * [[java: | ||
* 참조 | * 참조 | ||
* [[http:// | * [[http:// | ||
* [[http:// | * [[http:// | ||
+ | * [[http:// | ||
* [[http:// | * [[http:// | ||
- | * **결코 null 일 수 없는 One-To-One 관계**에서는 프록시를 설정하고 Lazy 로 작동하게 만드는 것이 가능하다. **optional=false** 를 지정한다(결코 Null일 수 없다는 뜻). | + | * **결코 null 일 수 없는 One-To-One 관계('' |
* **아래 코드는 잘못되었다. PrimaryKeyJoin 의 경우에는 optional=false 일 경우에 데이터 저장 순서가 꼬여버린다. 정상적인 optional=false가 작동하려면 ForeignKey Join을 해야한다.** | * **아래 코드는 잘못되었다. PrimaryKeyJoin 의 경우에는 optional=false 일 경우에 데이터 저장 순서가 꼬여버린다. 정상적인 optional=false가 작동하려면 ForeignKey Join을 해야한다.** | ||
* <code java> | * <code java> | ||
줄 55: | 줄 74: | ||
</ | </ | ||
* '' | * '' | ||
+ | |||
+ | ===== 게시판 형태에서 게시글에 대해 @ElementCollection을 사용한 LazyLoading 구현 ===== | ||
+ | * Deprecated. see [[java: | ||
+ | * 기본적으로 One-To-One의 LazyLoading이 난잡하므로 @ElementCollection에 Lazy를 이용하되, | ||
+ | <code java> | ||
+ | // Article 이라는 엔티티의 내용(content)를 LazyLoading하는 예제이다. | ||
+ | |||
+ | @ElementCollection(fetch = FetchType.LAZY) | ||
+ | @CollectionTable(name = " | ||
+ | @org.hibernate.annotations.ForeignKey(name=" | ||
+ | @Column(name = " | ||
+ | private List< | ||
+ | |||
+ | public void setContent(String content) { | ||
+ | if (getContentHolder() == null) { | ||
+ | setContentHolder(new ArrayList< | ||
+ | } | ||
+ | |||
+ | getContentHolder().clear(); | ||
+ | getContentHolder().add(content); | ||
+ | } | ||
+ | |||
+ | public String getContent() { | ||
+ | if (getContentHolder() == null || getContentHolder().size() == 0) { | ||
+ | return null; | ||
+ | } | ||
+ | return getContentHolder().get(0); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * 실제 클라이언트는 getCentent(), | ||
+ | * unique=true 조건 때문에 컬렉션임에도 단 한개의 값만 저장할 수 있다. | ||
+ | * 복합키 엔티티일 경우 '' | ||
+ | * 값을 수정할 경우, update 문이 아니라 delete/ | ||
+ | |||
===== 게시판 형태에서 게시글에 대해 One-To-One LazyLoading 구현 ===== | ===== 게시판 형태에서 게시글에 대해 One-To-One LazyLoading 구현 ===== | ||
+ | * Deprecated. see [[java: | ||
+ | * ElementCollection 방식 추천. | ||
* 게시판처럼 내용이 있지만, 목록에서는 내용을 보여주지 않는 경우 JPA 에서 내용 컬럼에 LazyLoading을 적용해도 현재의 JPA 구현체들이 필드 LazyLoading을 구현하지 못해서 결국 제목의 목록만 필요할 때도 내용까지 읽어들인다. | * 게시판처럼 내용이 있지만, 목록에서는 내용을 보여주지 않는 경우 JPA 에서 내용 컬럼에 LazyLoading을 적용해도 현재의 JPA 구현체들이 필드 LazyLoading을 구현하지 못해서 결국 제목의 목록만 필요할 때도 내용까지 읽어들인다. | ||
* 이 경우 해결책은 내용부분을 다른 테이블로 분리하고 One-To-One 관계로 맺은 뒤에 내용 부분에 LazyLoading을 적용하는 것이다. | * 이 경우 해결책은 내용부분을 다른 테이블로 분리하고 One-To-One 관계로 맺은 뒤에 내용 부분에 LazyLoading을 적용하는 것이다. |