W8D3(2) - JPA

고급 매핑

JPA는 RDB의 테이블과 매핑된 객체(Entity)를 객체답게 사용할 수 있도록 여러가지 고급 매핑 전략을 제공해줍니다.

1. 상속관계매핑

(1) 조인테이블 전략

  • Item을 상속받고 있는 Car, Furniture, Food 객체

  • 부모 클래스에는 @Inheritance를 쓰고 전략을 적어준다

  • 데이터가 잘 저장되는지 테스트 해보기

@Slf4j
@SpringBootTest
public class ImproveMappingTest {

    @Autowired
    private EntityManagerFactory emf;

    @Test
    void inheritance_test(){
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Food food = new Food();
        food.setPrice(2000);
        food.setStockQuantity(200);
        food.setChef("백종원");
         entityManager.persist(food);

         transaction.commit();
    }
 }

  • 실행결과를 보면 item과 food 둘다 insert문이 들어가는 것을 확인할수있음

(2) 싱글테이블 전략

  • Single_TABLE 전략으로 바꿔준다
  • 싱글테이블 전략은 하나의 테이블에 모든 정보를 담고 있기 때문에 각 객체를 구분해 줄수 있는 정보 필요 (@DiscriminationColum)
  • DiscriminatorValue는 부모객체에서 명시해준 DTYPE 컬럼에 값으로 들어감
 @Test
    void inheritance_test(){
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Food food = new Food();
        food.setPrice(2000);
        food.setStockQuantity(200);
        food.setChef("백종원");
         entityManager.persist(food);

         transaction.commit();
    }
  • 결과와 데이터베이스를 확인해보면 하나의 테이블로 생성되는 것을 볼수있음
  • Food를 저장했기때문에 데이터베이스의 DTYPE 컬럽에 food 값으로 저장

2. @MappedSupserclass

  • 공통으로 사용하는 필드들을 관리로 할때 공통 엔테티로 뽑아서 자주 사용

@Test
    void mapped_super_class_test(){
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Order order = new Order();
        order.setUuid(UUID.randomUUID().toString());
        order.setOrderStatus(OrderStatus.OPENED);
        order.setMemo("---");
        order.setOrderDatetime(LocalDateTime.now());

        //
        order.setCreatedBy("ChaeWon");
        order.setCratedAt(LocalDateTime.now());

        entityManager.persist(order);
        transaction.commit();
    }

3. 식별자 클래스

  • pk값을 하나가아니라 복합키로 구분해야할때 사용

  • 어떤값을 식별자로 써서 equals 돌려야할지 모르기때문에 런타임에러

  • JPA에서 식별자를 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야 한다.

public class Member {
	@Id
	private String id1;
	@Id
	private String id2; // runtime error
}

(1) @IdClass

@Getter
@Setter
@Entity
@IdClass(ParentId.class)
public class Parent {
    @Id
    private String id1;
    @Id
    private String id2;
}

@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable {
    private String id1;
    private String id2;
}
@Test
void multi_key_test() {
    EntityManager entityManager = emf.createEntityManager();
    EntityTransaction transaction = entityManager.getTransaction();

    transaction.begin();

    Parent parent = new Parent();
    parent.setId1("id1");
    parent.setId2("id2");
    entityManager.persist(parent);

    transaction.commit();

    Parent entity = entityManager.find(Parent.class, new ParentId("id1", "id2"));
    log.info("{}, {}", entity.getId1(), entity.getId2());
}
  • Serializable 인터페이스를 구현해야 한다.
  • eqauls, hashCode를 구현해야 한다.
  • 기본 생성자가 있어야 한다.
  • 식별자 클래스는 public 이어야 한다.

@EmbeddedId

@Getter
@Setter
@Entity
public class Parent2 {
    @EmbeddedId
    private ParentId2 id;
}

@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class ParentId2 implements Serializable {
    private String id1;
    private String id2;
}
 @Test
    void id_test(){
        EntityManager entityManager = emf.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        transaction.begin();

        Parent parent = new Parent();
        parent.setId(new ParentId("id1", "id2"));

        entityManager.persist(parent);
        transaction.commit();

        entityManager.clear();
        Parent parent1 = entityManager.find(Parent.class, new ParentId("id1", "id2"));
        log.info("{}, {}", parent1.getId().getId1(), parent1.getId().getId2());
    }

    }
  • Serializable 인터페이스를 구현해야 한다.
  • eqauls, hashCode를 구현해야 한다.
  • 기본 생성자가 있어야 한다.
  • 식별자 클래스는 public 이어야 한다.
  • @Embeddable 애노테이션이 있어야 한다.

좋은 웹페이지 즐겨찾기