エンティティEmployee
の複合プライマリキーを次のように構成しました
Employee.Java:
@Entity
@Table(name="employee")
@Proxy(lazy=false)
@IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private EmployeeId employeeId;
private Person person;
private Branch branch;
private boolean isActive;
public Employee() {
}
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name="person", column = @Column(name="person_id")),
@AttributeOverride(name="branch", column = @Column(name="branch_id"))})
public EmployeeId getEmployeeId() {
return employeeId;
}
public void setEmployeeId(EmployeeId employeeId) {
this.employeeId = employeeId;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="person_id")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="branch_id")
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
@Column(name="is_active")
public boolean getIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
}
EmployeeId.Java:
@Embeddable
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Person person;
private Branch branch;
public EmployeeId() {
}
public EmployeeId(Person argPerson, Branch argbranch) {
this.person = argPerson;
this.branch = argbranch;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="person_id", insertable=false, updatable=false)
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="branch_id", insertable=false, updatable=false)
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
}
クラスorg.springframework.orm.hibernate5.LocalSessionFactoryBean
を使用してSessionFactory
Beanを作成し、すべてのhbm.xml
をMappingLocations
としてマップしました。
私のコードは次のエラーをスローします:
Caused by: Java.lang.IllegalArgumentException: expecting IdClass mapping
at org.hibernate.metamodel.internal.AttributeFactory$3.resolveMember(AttributeFactory.Java:971)
at org.hibernate.metamodel.internal.AttributeFactory$5.resolveMember(AttributeFactory.Java:1029)
at org.hibernate.metamodel.internal.AttributeFactory.determineAttributeMetadata(AttributeFactory.Java:451)
at org.hibernate.metamodel.internal.AttributeFactory.buildIdAttribute(AttributeFactory.Java:128)
at org.hibernate.metamodel.internal.MetadataContext.buildIdClassAttributes(MetadataContext.Java:337)
at org.hibernate.metamodel.internal.MetadataContext.applyIdMetadata(MetadataContext.Java:269)
at org.hibernate.metamodel.internal.MetadataContext.wrapUp(MetadataContext.Java:190)
at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.Java:219)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.Java:296)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.Java:476)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:707)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.Java:723)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.Java:504)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.Java:488)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFac
このエラーを回避するにはどうすればよいですか? spring-orm-4.3.1-RELEASE
とhibernate-core-5.2.0.Final
を使用しています。
更新
サンプルプロジェクトを作成しましたが、実行中に次のエラーが表示されます...
Caused by: org.hibernate.AnnotationException: Property of @IdClass not found in entity sample.domain.Employee: employee
コードを参照してください: https://www.dropbox.com/s/axr8l01iqh0qr29/idclass-using-hibernate5.tar.gz?dl=
私が間違ったことは何ですか?ここに入力してください
複合キーマッピングは、IdClassまたはEmbeddableで実行できます。 IdClassを使用する場合は、@ Idを使用してEmployeeのフィールドに注釈を付ける必要があります。
@IdClass(EmployeeId.class)
class Person{
@Id
private Person person;
@Id
private Branch branch;
}
Embeddedを複合キーとして使用する場合は、Personから@IdClass(EmployeeId.class)注釈を削除してください。また、Personクラスのpersonおよびbranchフィールドは、Embeddedクラスで定義されているため必要ありません。
あなたの状況は JPA 2.1仕様 の章2.4.1派生IDに対応する主キーに対応しています。
Employee
のIDは、Person
およびBranch
のIDから派生します。どちらのコードも表示されていないため、単純な主キーがあると仮定します。その関係では、Person
とBranch
は「親エンティティ」であり、Employee
は「依存」エンティティです。
Employee
のIDは、IdClass
またはEmbeddedId
のいずれかを使用してマップできますが、両方を同時に使用することはできません。
2.4.1.1派生IDの仕様の章を参照してください。
IdClass
を使用する場合:
Idクラスの属性の名前と依存エンティティクラスのId属性は、次のように対応する必要があります。
- エンティティークラスの
Id
属性とidクラスの対応する属性は同じ名前でなければなりません。...
- エンティティの
Id
属性が親エンティティとの多対1または1対1の関係である場合、idクラスの対応する属性は(...)親のId
属性の型である必要がありますエンティティ。
したがって、クラスは次のようになります(ゲッター、セッター、余分な注釈などは省略されます)
@Entity
@IdClass(EmployeeId.class)
public class Employee {
@Id
@ManyToOne
private Person person;
@Id
@ManyToOne
private Branch branch;
}
public class EmployeeId {
private Long person; // Corresponds to the type of Person ID, name matches the name of Employee.person
private Long branch; // Corresponds to the type of Branch ID, name matches the name of Employee.branch
}
EmbeddedId
を使用する場合:
依存エンティティが埋め込みIDを使用してそのプライマリキーを表す場合、リレーションシップ属性に対応する埋め込みIDの属性は、親エンティティのプライマリキーと同じタイプである必要があり、適用される
MapsId
アノテーションで指定する必要があります関係属性。リレーションシップ属性が対応する埋め込みID内の属性の名前を指定するには、value
アノテーションのMapsId
要素を使用する必要があります。
そして、コードは次のようになります。
@Entity
public class Employee {
@EmbeddedId
private EmployeeId id;
@ManyToOne
@MapsId("personId") // Corresponds to the name of EmployeeId.personId
private Person person;
@ManyToOne
@MapsId("branchId") // Corresponds to the name of EmployeeId.branchId
private Branch branch;
}
@Embeddable
public class EmployeeId {
private Long personId; // Corresponds to the type of Person ID
private Long branchId; // Corresponds to the type of Branch ID
}
IdClassは埋め込み可能として定義されるべきではありません-
@Entity
@Table(name="employee")
@IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@ManyToOne
private Person person;
@Id
@ManyToOne
private Branch branch;
private boolean isActive;
public Employee() { }
//....
}
そして-
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Person person;
private Branch branch;
public EmployeeId() {}
public EmployeeId(Person argPerson, Branch argbranch) {
this.person = argPerson;
this.branch = argbranch;
}
}
コメントを読む-JPAオブジェクトのPersonとBranchではなく、person_idとbranch_idにEmployeeをマップすることを提案できますか?これにより、hbm設定が正しいかどうかをテストできます。また、この問題から情報が欠落していると思うので、hbm configを投稿することをお勧めします
そのため、テーブルは次のようになります-
@Entity
@Table(name="employee")
@IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long personId;
@Id
private Long branchId;
private boolean isActive;
public Employee() { }
//....
}
そして-
そして-
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private Long branchId;
public EmployeeId() {}
public EmployeeId(Person argPerson, Branch argbranch) {
this.person = argPerson;
this.branch = argbranch;
}
}
への変更:
@Entity
@Table(name = "employee")
@Proxy(lazy = false)
@IdClass(EmployeeId.class)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private EmployeeId id;
private Person person;
private Branch branch;
private boolean isActive;
public Employee() {
}
@EmbeddedId
@AttributeOverrides({@AttributeOverride(name = "person", column = @Column(name = "person_id") ),
@AttributeOverride(name = "branch", column = @Column(name = "branch_id") )})
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id")
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "branch_id")
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
@Column(name = "is_active")
public boolean getIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
}
このリンクはあなたを助けることができます JPA-@ManytoOneのEmbeddedId
埋め込みIDクラス内で定義されたリレーションシップマッピングはサポートされていません。次に、このようにembeddedIdクラスを変更する必要があります。
@Embeddable
public class EmployeeId implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private Long branchId;
public EmployeeId() {
}
public EmployeeId(Long argPerson, Long argbranch) {
this.personId = argPerson;
this.branchId = argbranch;
}
@Column(name = "person_id")
public Long getPersonId() {
return personId;
}
public void setPersonId(Long personId) {
this.personId = personId;
}
@Column(name = "branch_id")
public Long getBranchId() {
return branchId;
}
public void setBranchId(Long branchId) {
this.branchId = branchId;
}
}
ID
を保持するクラスに@IdClass
注釈を付けます。 this postで答えを確認してください
JPAコンポジット主キー
エンティティの複数のフィールドまたはプロパティにマップされる複合主キークラスを指定します。
主キークラスのフィールドまたはプロパティの名前と、エンティティの主キーフィールドまたはプロパティは対応している必要があり、それらのタイプは同じである必要があります。
答えはここにあります。説明を読んでください。 ここにリンクの説明を入力してください
(サンプルコード)
@Entity
@Table(name = "EMP_PROJECT")
@IdClass(ProjectAssignmentId.class)
public class ProjectAssignment {
@Id
@Column(name = "EMP_ID", insertable = false, updatable = false)
private int empId;
@Id
@Column(name = "PROJECT_ID", insertable = false, updatable = false)
private int projectId;
@ManyToOne
@JoinColumn(name = "EMP_ID")
Professor employee;
@ManyToOne
@JoinColumn(name = "PROJECT_ID")
Project project;
....
}
public class ProjectAssignmentId implements Serializable {
private int empId;
private int projectId;
...
}