ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JPA @OneToOne 매핑이 안된다고? Unique
    Jpa 2020. 11. 4. 09:24

    JPA @OneToOne 매핑이 안된다고?

    Introduction

    JPA를 사용하면서 @OneToOne 어노테이션을 많이 보고 사용했을 것이다. 이 글에서는 OneToOne 어노테이션을 사용했는데도, 데이터가 한개가 아닌 2개가 들어가서 @OneToMany로 들어가는 일이 있거나, 그런 궁금증을 가지신 분들이 보면 도움이 될 수 있다고 생각한다.

    * 이 글은 JPA,, Database 사전지식이 있다는 가정하에 서술하였습니다.

    * 환경(Intelli j, h2 database)

    Situation

    1. 두개의 1대1 양방향 관계의 엔티티가 있습니다. (Son, Parent)

    @Entity
    
    @Table
    
    public class Son {
    
       @Id
    
       @Column
    
       private String name;
    
    
       @Column
    
       Integer age;
    
    
       @JoinColumn
    
       @OneToOne
    
       private  Parent parent;
    
    }

    2. 각자의 엔티티를 사용해서, Son 객체 2개를 생성해서 똑같은 부모 Foreign키를 사용해보겠습니다.

    @Entity
    
    @Table
    
    public class Parent {
    
       @Id
    
       @Column
    
       private String name;
    
    
       @Column
    
       private Integer age;
    
    
       @OneToOne(mappedBy = "parent")
    
       @JoinColumn
    
       private Son son;
    
    }

    3. 구동결과

    ```java
    public class FamilyService {

    public static void main(String[] args) {

       EntityManagerFactory emf =  Persistence.createEntityManagerFactory("hello");
    
    
       EntityManager em = emf.createEntityManager();
    
    
       EntityTransaction tx = em.getTransaction();
    
       tx.begin();
    
    
       Parent parent = new Parent();
    
       parent.setName("엄마");
    
    
       Son son1 = new Son();
    
       Son son2 = new Son();
    
    
       son1.setName("아들1");
    
       son1.setAge(11);
    
       son1.setParent(parent);
    
       parent.setSon(son1);
    
    
       son2.setName("아들2");
    
       son2.setAge(10);
    
       son2.setParent(parent);
    
    
       em.persist(parent);
    
       em.persist(son1);
    
       em.persist(son2);
    
       tx.commit();
    
    
    
       em.close();
    
       emf.close();

    }

    }

    • 이상하게 너무 잘돌아간다. (아들1과 아들2는 알고보니 형제였던거임)

    • Hibernate 를 보면 OneToOne 을 비웃기라도 한듯이 너무 잘들어 간다.

    사실 정상적인 구동 결과이다. DB자체에다가, 물리적으로 제약을 걸어준 것도 아니고, 자바입장에서도 객체 레퍼런스값을 집어넣는데 문제가 생길 이유도 명분도 없다.

    근데 이왕 어노테이션 까지 붙였으면 Hibernate 가 영속성 컨텍스트나 1차캐시 안에서 무언가 해줄거라고 생각했던 내 착각이었다.

    결론적으로 ORM에서 말하는 1:1 , 1:N 관계라는 것은 관계형 데이터베이스 기준의 관계이다.

    특히 1:1 같은 경우에는 필요에 따라 적절하게 제약조건을 걸어줘야 한다.

    • DB 에다가 물리적으로 걸어줘야하나?

    (그냥 디비에다가 걸어주면 되고)

    • 아니면 Hibernate 에서 해결할 방법이 있을까?

    보면 알듯이 조인컬럼에다가 unique 제약 조건이 걸 수 있는데, 친절한건지 unique가 false가 되어있다.

    이걸 True로 바꿔주고 다시 기동해보면

    객체에 참조값 다 들어가고 persist 하기전 트렌젝션 커밋에서 바로 unique 제약조건 걸려서 오류가 뜬다.

    Service에 Exception을 해야했는데 귀찮아서 안했지만 아마 Exception 띄우고 진행하면 rollback 이 될거다.

    댓글

Designed by Tistory.