@MappedSuperclass
public class BaseEntity{
@Column(name = "INSERT_MEMBER")
private String createdBy;
//위 방법으로 하면 해당 테이블 이름을 INSERT_MEMBER로 생성함
private LocalDateTime createDate;
private String lastmodifiedBy;
private LocalDateTime lastModifiedDate;
}
위와 같이 공통으로 사용하는 컬럼의 base entity를 생성함
- 상속관계 매핑이 아니다.
- 엔티티가 x (baseEntity 테이블이 생성되는게 아님)
- 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공
- 조회, 검색 불가
- 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
- 테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑정보를 모으는 역활
- @Entity 클래스는 엔티티나 @MappedSuperclass로 지정한 클래스만 상속 가능
식별 관계 vs 비식별 관계
- 식별관계 식별 관계는 부모 테이블의 기본 키를 내려받아서 자식 테이블의 기본 키 + 왜래키로 사용하는 관계다.
- 비식별 관계 비식별 관계는 부모 테이블의 기본 키를 받아서 자식 테이블의 외래 키로만 사용하는 관계다.
필수적 비식별 관계: 외래 키에 NULL을 허용하지 않는다. 연관관계를 필수적으로 맺어야 한다. 선택적 비식별 관계: 외래 키에 NULL을 허용한다. 연관관계를 맺을지 말지 선택할 수 있다.
JPA는 영속성 컨텍스트에 엔티티를 보관할 때 엔티티의 식별자를 키로 사용한다. 그리고 식별자를 구분하기 위해 equals와 hashCode를 기본으로 사용해서 동등성을 비교를 한다. 만약 식별자 필드가 2개 이상이면 별도의 식별자 클래스를 만들고 그곳에 equals와 hashCode를 구현해야 한다.JPA는 복합 키를 지원하기 위해 @IdClass와 @EmbeddedId 2가지 방법을 지원한다.
@IdClass
@Entity
@Getter
@Setter
@IdClass(ParentId.class)
public class Parent {
@Id
@Column(name = "PARENT_ID1")
private String id1;
@Id
@Column(name = "PARENT_ID2")
private String id2;
private String name;
}
public class ParentId implements Serializable {
private String id1;
private String id2;
public ParentId() {
}
public ParentId(String id1, String id2) {
this.id1 = id1;
this.id2 = id2;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
}
@Entity
public class Child {
@Id
private String id;
@ManyToOne
@JoinColumns({@JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
@JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")})
private Parent parent;
}
실행코드
@Component
public class jpaRunner implements ApplicationRunner {
@Autowired
private EntityManagerFactory emf;
@PersistenceContext
private EntityManager entityManager;
@Transactional
@Override
public void run(ApplicationArguments args) throws Exception {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
logic(em);
tx.commit();
} catch (Exception e) {
System.out.println("error" + e);
tx.rollback();
}
}
private void logic(EntityManager em) {
Parent parent = new Parent();
parent.setId1("myId1");
parent.setId2("myId2");
parent.setName("parentName");
em.persist(parent);
ParentId parentId = new ParentId("myId1", "myId2");
Parent findParent = em.find(Parent.class, parentId);
}
}
실행결과
idClass 사용 조건
- 식별자 클래스의 속성명과 엔티티에서 사용하는 식별자의 속성명이 같아야 한다.
- Serializable 인터페이스를 구현해야 한다.
- equals, hashCode를 구현해야 한다.
- 기본 생성자가 있어야 한다.
- 식별자 클래스는 public이어야 한다.
@EmbeddedId
Idclass보다 좀더 객체지향적인 방법
@Entity
@Getter
@Setter
public class Parent {
@EmbeddedId
private ParentId id;
private String name;
}
@Embeddable
public class ParentId implements Serializable {
@Column(name = "PARENT_ID1")
private String id1;
@Column(name = "PARENT_ID2")
private String id2;
public ParentId (){
}
public ParentId(String id1, String id2) {
super();
this.id1 = id1;
this.id2 = id2;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
}
@Entity
public class Child {
@Id
private String id;
@ManyToOne
@JoinColumns({@JoinColumn(name = "PARENT_ID1", referencedColumnName = "PARENT_ID1"),
@JoinColumn(name = "PARENT_ID2", referencedColumnName = "PARENT_ID2")})
private Parent parent;
}
실행결과
EmbeddedId 조건
- Embeddable 어노테이션을 붙여줘야 한다.
- Serializable 인터페이스를 구현해야 한다.
- equals, hashCode를 구현해야 한다.
- 기본 생성자가 있어야 한다.
- 식별자 클래스는 public이어야 한다.
💡 복합 키에는 @GenerateValue를 사용할 수 없다. 복합 키를 구성하는 여러 컬럼 중 하나에도 사용 할 수 없다.
'SPRING > JPA' 카테고리의 다른 글
[JPA]객체지향쿼리 (0) | 2022.02.09 |
---|---|
[JPA]스프링 데이터 Common:커스텀 리포지토리 (0) | 2022.01.21 |
[JPA] 프록시 (0) | 2022.01.21 |
[JPA]객체지향 쿼리 심화 (0) | 2022.01.21 |
[JPA]NamedQuery (0) | 2022.01.21 |