developer tip

공유 ID가있는 JPA @OneToOne —이 작업을 더 잘 할 수 있습니까?

copycodes 2020. 12. 1. 08:20
반응형

공유 ID가있는 JPA @OneToOne —이 작업을 더 잘 할 수 있습니까?


변경하지 않으려는 기존 스키마로 작업하고 있습니다. 스키마는 Person과 VitalStats 테이블 사이에 일대일 관계를 가지고 있습니다. 여기서 Person은 기본 키를 가지고 있고 VitalStats는 Person에 대한 기본 키와 외래 키와 동일한 필드를 사용합니다. 즉, 해당 값은 해당 PK의 값입니다. 사람의.

이러한 레코드는 외부 프로세스에 의해 생성되며 내 JPA 코드는 VitalStats를 업데이트 할 필요가 없습니다. 내 개체 모델의 경우 Person 클래스에 VitalStats 멤버가 포함되기를 원하지만 다음과 같습니다.

내가 시도 할 때

@Entity
public class Person{
    private long id;
    @Id
    public long getId(){ return id; }

    private VitalStats vs;
    @OneToOne(mappedBy = “person”)
    public VitalStats getVs() { return vs; }
}

@Entity
    public class VitalStats{
     private Person person;
    @OneToOne
    public Person getPerson() { return person; }
}

VitalStats에 @Entity에서 작동하지 않는 @Id가 없다는 문제가 있습니다. \

내가 시도하면

@Id @OneToOne
public Person getPerson() { return person; }

@Id 문제를 해결하지만 Person이 Serializable이어야합니다. 다시 말씀 드리겠습니다.

VitalStats를 @Embeddable로 만들고 @ElementCollection을 통해 Person에 연결할 수 있지만 요소가 하나만 있다는 것을 알고 있더라도 컬렉션으로 액세스해야합니다. 가능하지만 약간 귀찮고 약간 혼란 스럽습니다.

그렇다면 Person이 Serializable을 구현한다고 말하는 것을 막는 것은 무엇입니까? 이유가있어서 내 코드의 모든 것이 거기에있는 것을 좋아하고 이에 대한 논리를 볼 수 없다는 점을 제외하면 실제로는 아무것도 없습니다. 이로 인해 코드의 가독성이 떨어집니다.

그 동안 VitalStats의 Person 필드를 긴 personId로 바꾸고 VitalStats의 @Id를 만들었으므로 이제 @OneToOne이 작동합니다.

솔직한 문제처럼 보이는 것에 대한 이러한 모든 솔루션은 약간 투박합니다. 그래서 내가 무엇을 놓치고 있는지 또는 누군가가 적어도 Person이 Serializable이어야하는 이유를 설명 할 수 있는지 궁금합니다.

TIA


공유 기본 키를 사용하여 일대일 연결을 매핑하려면 @PrimaryKeyJoinColumn@MapsId주석을 사용 합니다.

Hibernate 참조 문서의 관련 섹션 :

PrimaryKeyJoinColumn

PrimaryKeyJoinColumn 주석은 엔티티의 기본 키가 연관된 엔티티에 대한 외래 키 값으로 사용된다는 것을 말합니다.

MapsId

MapsId 주석은 Hibernate에게 다른 관련 엔티티에서 식별자를 복사하도록 요청합니다. Hibernate 전문 용어에서는 외부 생성기로 알려져 있지만 JPA 매핑이 더 잘 읽고 권장됩니다.

Person.java

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "person_id")
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private VitalStats vitalStats;       
}

VitalStats.java

@Entity
public class VitalStats 
{
    @Id @Column(name="vitalstats_id") Long id;

    @MapsId 
    @OneToOne(mappedBy = "vitalStats")
    @JoinColumn(name = "vitalstats_id")   //same name as id @Column
    private Person person;

    private String stats;
}

개인 데이터베이스 테이블

CREATE TABLE  person (
  person_id   bigint(20) NOT NULL auto_increment,
  name        varchar(255) default NULL,
  PRIMARY KEY  (`person_id`)
) 

VitalStats 데이터베이스 테이블

CREATE TABLE  vitalstats 
(
  vitalstats_id  bigint(20) NOT NULL,
  stats          varchar(255) default NULL,
  PRIMARY KEY  (`vitalstats_id`)
)

제 경우에는 이것이 트릭을 만들었습니다.

부모 클래스 :

public class User implements Serializable {
  private static final long serialVersionUID = 1L;

  /** auto generated id (primary key) */
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(unique = true, nullable = false)
  private Long id;

  /** user settings */
  @OneToOne(cascade = CascadeType.ALL, mappedBy = "user")
  private Setting setting;
}

어린이 클래스 :

public class Setting implements Serializable {
  private static final long serialVersionUID = 1L;

  /** setting id = user id */
  @Id
  @Column(unique = true, nullable = false)
  private Long id;

  /** user with this associated settings */
  @MapsId
  @OneToOne
  @JoinColumn(name = "id")
  private User user;
}

참고 URL : https://stackoverflow.com/questions/6833370/jpa-onetoone-with-shared-id-can-i-do-this-better

반응형