Idclass vs EmbeddedId

김민지·2022년 10월 24일
0

JPA

목록 보기
12/27

비식별child - 복합키parent을 idclass를 이용하여 구현

@Entity
@Getter
public class DeIdenChild {
    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumns({@JoinColumn(name = "id1"), @JoinColumn(name="id2") })
    private Parent parent;

    private String name;

    public void setParent(Parent parent){
        this.parent = parent;
    }
}
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@IdClass(ParentId.class)
public class Parent {
    @Id
    private Long id1;
    @Id
    private Long id2;
    private String name;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class ParentId implements Serializable {
    private Long id1;
    private Long id2;
    @Override
    public int hashCode() {
        return Objects.hash(id1, id2);
    }
    @Override
    public boolean equals(Object obj) {
        if(obj==this) return true;
        else{
            if(obj==null || obj.getClass()!= this.getClass()) return false;
            ParentId p = (ParentId) obj;
            return id1.equals(p.id1) && id2.equals(p.id2);
        }
    }
}

식별복합키child - 단일키parent을 idclass를 이용하여 구현

@AllArgsConstructor
@Getter
@NoArgsConstructor
public class ChildId implements Serializable {
    public Long parent;
    public Long child_id;
    @Override
    public int hashCode() {
        return Objects.hash(parent, child_id);
    }

    @Override
    public boolean equals(Object obj) {
        if(obj==this) return true;
        else{
            if(obj==null || obj.getClass()!= this.getClass()) return false;
            ChildId c = (ChildId) obj;
            return parent.equals(c.parent) && child_id.equals(c.child_id);
        }
    }
}
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@IdClass(ChildId.class)
public class IdenChild {
    @Id
    @ManyToOne
    @JoinColumn(name = "parent_id")
    public Parent parent; //이거 왜 퍼블릭이어야하지
    @Id
    private Long child_id;
    //private ChildId childId; Property of @IdClass not found in entity jpaStudy.ex.entity.IdenChild: child_id
    private String name;
}
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Parent {
    @Id
    @Column(name = "parent_id")
    private Long id;
    private String name;
}
@Test
	@Commit
	@Transactional
	public void 식별비식별테스트(){
		ChildId id = new ChildId(1L, 2L);
		IdenChild child = IdenChild.builder().name("child1").child_id(id.getChild_id()).build();
		Parent parent = new Parent();
		parent.setId(id.getParent());
		child.setParent(parent);
		em.persist(parent);
		em.persist(child);
	}


비식별child - 복합키parent을 embeddedid를 이용하여 구현

@Entity
@Setter
@Getter
public class DeIdenChild {
    @Id
    private Long id;

    @JoinColumns({
            @JoinColumn(name = "id1"),
            @JoinColumn(name = "id2")
    }
    )
    @ManyToOne
    private Parent parent;


    private String name;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Embeddable
public class ParentId implements Serializable {
    private Long id1;
    private Long id2;
    @Override
    public int hashCode() {
        return Objects.hash(id1, id2);
    }

    @Override
    public boolean equals(Object obj) {
        if(obj==this) return true;
        else{
            if(obj==null || obj.getClass()!= this.getClass()) return false;
            ParentId p = (ParentId) obj;
            return id1.equals(p.id1) && id2.equals(p.id2);
        }
    }
}
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Parent {
    @EmbeddedId
    private ParentId id;
    private String name;
}
@Test
	@Transactional
	@Commit
	public void 식별비식별테스트(){
		ParentId id = new ParentId(7l,8l);
		Parent parent = new Parent(id,"name1");
		DeIdenChild child = new DeIdenChild();
		child.setId(5l);
		em.persist(parent);
		child.setParent(parent);
		child.setName("name2");
		em.persist(child);
	}

에러 : detached entity passed to perist

에러분석
generatedvalue로 id값이 생성됐는데 전 그걸까먹고 id값을 setting해줬어요
그랬더니 detached entity passed to perist 라는 오류가떴어요
준영속엔티티를 영속화시키려고해서 발생하는오류잖아요?
왜 이런 오류가뜨는걸까요? id생성전략은 sequence예요
sequence는 다음과 같이 동작해요
<<persist 를 호출하면 sequence 를 가져옵니다.
가져온 Sequence 를 id 에 할당하고 (영속성 상태), transaction 이 commit 될 때, insert 쿼리를 날립니다.>>
근데 이러면 제가 set을 해도 새로운 id에 덮어씌여져야하는거아닌가요?
https://velog.io/@flre_fly/JPA-%EC%A7%88%EB%AC%B8-%EB%AA%A8%EC%9D%8C

식별복합키child - 단일키parent을 embeddeid를 이용하여 구현

    • childId에 embeddable어노테이션 선언
  • serializeable 상속받고 hashcode, equals구현
  • child에 childId타입의 변수를 선언하고 @EmbeddedId를 선언
  • 식별관계를 위해 식별관계인 필드위에 @mapsId("childid의 어떤 필드인지")를 선언해준다
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Parent {
    @Id
    @GeneratedValue
    @Column(name = "parent_id")
    private Long id;
    private String name;
}
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class IdenChild {
    @EmbeddedId
    private ChildId childId;
    @MapsId("parentId")
    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
    private String name;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Embeddable
public class ChildId  implements Serializable {
    private Long childId;
    private Long parentId;
    @Override
    public int hashCode() {
        return Objects.hash(childId, parentId);
    }
    @Override
    public boolean equals(Object obj) {
        if(obj==this) return true;
        else{
            if(obj==null || obj.getClass()!= this.getClass()) return false;
            ChildId c = (ChildId) obj;
            return childId.equals(c.childId) && parentId.equals(c.parentId);
        }
    }
}
@Test
	@Transactional
	@Commit
	public void 식별비식별테스트(){
		Parent parent = new Parent();
		parent.setName("부모");
		em.persist(parent);
		ChildId id = new ChildId(1l, parent.getId());
		IdenChild child = new IdenChild();
		child.setParent(parent);
		child.setChildId(id);
		child.setName("child1");
		em.persist(child);
	}
profile
안녕하세요!

0개의 댓글