임베디드 타입
- 새로운 값 타입을 직접 정의할 수 있음
- JPA 는 임베디드 타입이라 함
- 기본 값 타입을 모아 만들어서 복합 값 타입이라 부름
- int,String 과 같은 값 타입
임베디드 타입 장점
- 재사용성
- 높은 응집도
- 해당 값 타입만 사용하는 의미 있는 메소드 생성 가능
- 임베디드 타입을 포함한 모든 값 타입은 값 타입을 소유한 엔티티에 생명주기를 의존
임베디드 타입 사용 방법
- @Embeddable : 값 타입 정의하는 곳에 표시
- @Embedded : 값 타입 사용하는 곳에 표시
- 기본 생성자 필수
임베디드 타입과 테이블 매핑
: 임베디드 타입을 쓴것과 안 쓴것의 회원 테이블은 이전과 똑같음을 알 수 있습니다.
- 테이블은 데이터를 다루는 개념이기에 변경되지 않도록 설계하는 것이 좋습니다.
- 엔티티의 경우 메소드까지 신경을 써야하므로 공통 기능은 묶어서 사용하는게 사용성이 더 좋습니다.
임베디드 타입과 테이블 매핑
- 임베디드 타입은 엔티티의 값일 뿐입니다.
- 임베디드 타입을 사용하기 전과 후에 매핑하는 테이블은 같습니다.
- 객체와 테이블을 아주 세밀하게 매핑하는 것이 가능합니다. ( 프로젝트가 커질 수록 세밀한게 좋다 )
- 잘 설계한 ORM 애플리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많습니다.
임베디드 타입과 엔티티
- 임베디드 타입 멤버 안에 엔티티 객체도 들어 올 수 있습니다
- PhoneNumber 라는 임베디드 객체는 PhoneEntity 라는 엔티티를 가질 수 있음
사용 예시
- 회원 테이블의 [ Address ( city, street, zipcode ) ] , [ WorkPeriod ( Order, Send, ArriveDateTIme ) ] 임베디드 타입을 정의
발생오류
1. EntityManagerFactory 빈을 등록 안한 오류 <해결완료>
[ 기존 코드 ]
@Bean
public EntityManager getEm() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory();
return emf.createEntityManager();
}
[ 수정 코드 ]
@Bean
public EntityManagerFactory getEmf() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("5xik");
return emf;
}
@Bean
public EntityManager getEm() {
EntityManagerFactory emf = getEmf();
EntityManager em = emf.createEntityManager();
return em;
}
2. 테이블이 업데이트 되지 않는 오류 < 해결완료 >
<property name="hibernate.hbm2ddl.auto" value="update" />
3. 커밋 시기를 save 함수 내에서 작동하도록 변경 < 해결완료 >
[ 기존 코드 ]
테스트 코드에서 의존성 주입받은 EntityManager 를 통해 커밋을 해주는 방식을 사용하기 위해 시도
-> 트랜잭션호출 생성 함수에서 NPE 발생
[ 수정 코드 ]
public Member save(Member member) {
tx.begin();
try {
em.persist(member);
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
//em.close();
}
//mf.close();
return member;
}
@Test
@Commit
void insertData() {
Member member = new Member();
member.setName("test");
member.setPhonenumber("01011");
member.setAddress(new Address("city","street","10000"));
member.setWorkPeriod(new WorkPeriod());
Member save = repository.save(member);
}
- member 객체를 테스트 코드에서 만듬
- save 함수 내부에서 begin ~ persist ~ commit 과정을 거침으로써 테스트코드에서는 이에 대한 코드를 작성할 일이 없음
임베디드 타입으로 선언한 값들이 정상적으로 들어오는 것을 알 수 있음
값 타입 공유 참조
임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험함
[ 예시 ]
@Test
@Commit
void insertData() {
Address address = new Address("city","str","10000");
//공유 객체
Member member = new Member();
member.setName("test");
member.setPhonenumber("01011");
// member.setAddress(new Address("city","street","10000"));
member.setAddress(address);
member.setWorkPeriod(new WorkPeriod());
Member member2 = new Member();
member2.setName("test");
member2.setPhonenumber("01011");
member2.setAddress(address);
member2.getAddress().setCity("geoje"); // 수정
Member save = repository.save(member);
Member save2 = repository.save(member2);
}
- address 라는 객체를 공유해서 사용
- member2 에 address 를 수정
- member1 에 address 도 수정됨을 볼 수 있음
[ 해결 방법 ]
1) 각각의 객체에 new Address 로 생성자를 통해 할당 해줌
member.setAddress(new Address("city","street","10000"));
member2.setAddress(new Address("city2","street2","20000"));
2) 불변 객체로 생성
- setter 부분을 private 로 선언해서 외부에서 수정할 수 없게 만들어주는 방법
'JPA(MySQL,H2Database)' 카테고리의 다른 글
Database not found, either pre-create it or allow remote database creation (not recommended in secure environments) [90149-200] 90149/90149 (0) | 2022.12.16 |
---|---|
오류가 발생하지 않았는데 H2 Database 에 테이블이 올라오지 않을 경우 (0) | 2022.10.10 |
SQL 내장함수 (0) | 2022.08.05 |
JPQL 와 JPQL의 테스트 코드 작성 (0) | 2022.07.29 |
EntityManager (0) | 2022.07.29 |