2016-07-27 89 views
23

我爲我的實體Employee配置複合主鍵如下java.lang.IllegalArgumentException異常:期待IdClass映射

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-RELEASEhibernate-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=0

我做了什麼錯?請提供您的輸入這裏

+0

會發生什麼事,如果你刪除@IdClass?它應該仍然正常工作 – valepu

+0

刪除@IdClass註釋後,我也得到了與上面相同的錯誤。 sessionFactory bean創建時是否缺少映射? – Achaius

+0

我嘗試了以下5個ansers。但是我仍然得到相同的錯誤。我正在使用spring-4.3.2.RELEASE和hibernate-5.2.0.Final。 – Achaius

回答

1

更改爲:

@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; 
} 

} 
+0

我試過這個答案。但觀察上面提到的同樣的錯誤 – Achaius

1

的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; 
    } 
} 

閱讀您的評論 - 我可以做建議您將Employee映射到person_id和branch_id,而不是JPA對象Person和Branch?這將讓我們測試您的hbm配置是否正確。 ID還建議發佈您的HBM的配置,因爲我認爲這是信息從這個問題缺少

所以該表將類似於 -

@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; 
    } 
} 
+0

我試着用你的答案。但仍然如上所述得到相同的錯誤。 – Achaius

+0

如果您的OneToMany映射或IdClass或配置 – farrellmr

+0

感謝您的回覆@farrellmr,您可以嘗試以上來縮小問題的範圍。我們需要ManyToOne映射在一個人和分支對象不是一個長/整數字段..請讓我們知道有沒有什麼可能..我有我的應用程序相同的問題... – SST

3

組合鍵映射可以使用IdClass或Embeddable完成。如果你想使用IdClass,你必須用@Id在Employee中註釋你的字段。

@IdClass(EmployeeId.class) 
    class Person{ 
    @Id 
    private Person person; 
    @Id 
    private Branch branch; 
    } 

如果您要使用嵌入式作爲組合鍵,請從Person中刪除@IdClass(EmployeeId.class)註釋。您也不需要Person類中的person和branch字段,因爲這些字段是在Embedded類中定義的。

+0

我試過了你的建議。再次發現相同的問題 – Achaius

0

提及@IdClass註解與持有ID的類。 檢查答案在this發佈

2

你的情況對應的章節2.4.1主鍵對應派生身份的JPA 2.1 Specification

Employee的身份來源於PersonBranch的身份。你沒有顯示任何一個的代碼,所以我會假設他們有簡單的主鍵。在這種關係中,PersonBranch是「父實體」,而Employee是「從屬」實體。

可以使用IdClassEmbeddedId來映射Employee的ID,而不是兩者同時映射。

請參閱章節2.4.1.1導出身份的規範

如果你想使用IdClass,則:

The names of the attributes of the id class and the Id attributes of the dependent entity class must correspond as follows:

  • The Id attribute in the entity class and the corresponding attribute in the id class must have the same name.

...

  • If an Id attribute in the entity is a many-to-one or one-to-one relationship to a parent entity, the corresponding attribute in the id class must be of (...) the type of the Id attribute of the parent entity.

所以你的類看起來像這樣(的getter,setter方法,多餘的註釋等略)

@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,那麼:

If the dependent entity uses an embedded id to represent its primary key, the attribute in the embedded id corresponding to the relationship attribute must be of the same type as the primary key of the parent entity and must be designated by the MapsId annotation applied to the relationship attribute. The value element of the MapsId annotation must be used to specify the name of the attribute within the embedded id to which the relationship attribute corresponds.

而且代碼如下所示:

@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 
} 
+0

謝謝@Adam Michalik嘗試了您的答案,但仍然得到相同的錯誤。任何其他建議 – Achaius

0

此鏈接可以幫助你嵌入的ID類中定義 JPA - EmbeddedId with @ManytoOne

關係映射不會supported.Then您需要更改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; 
    } 
} 
0

JPA複合主鍵

Specifies a composite primary key class that is mapped to multiple fields or properties of the entity.

The names of the fields or properties in the primary key class and the primary key fields or properties of the entity must correspond and their types must be the same.

答案在這裏。爲你閱讀說明。 enter link description here

(示例代碼)

@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; 
    ... 
}