java.lang.IllegalArgumentException: expecting IdClass mapping

我已为我的实体配置了复合主键,如下所示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;
    }

}

员工 id.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;
    }
}

我使用类创建了一个bean,并将其全部映射为.SessionFactoryorg.springframework.orm.hibernate5.LocalSessionFactoryBeanhbm.xmlMappingLocations

我的代码引发以下错误:

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

我做错了什么?请在此处提供您的意见


答案 1

您的情况对应于 JPA 2.1 规范的 2.4.1 章“对应于派生身份的主键”。

的恒等式派生自 和 的恒等式。您尚未显示其中任何一个的代码,因此我假设它们具有简单的主键。在该关系中,并且是“母实体”并且是“依赖”实体。EmployeePersonBranchPersonBranchEmployee

的 ID 可以使用 或 映射,而不是同时映射两者。EmployeeIdClassEmbeddedId

请参阅第 2.4.1.1 章 派生标识的规范

如果要使用 ,则:IdClass

id 类的属性名称和依赖实体类的 Id 属性必须如下所示:

  • 实体类中的属性和 id 类中的相应属性必须具有相同的名称。Id

...

  • 如果实体中的属性与父实体是多对一或一对一关系,则 id 类中的相应属性必须是 (...) 父实体的属性类型。IdId

所以你的类看起来像这样(省略了getter,setters,多余的注释等)

@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 中的属性必须与父实体的主键具有相同的类型,并且必须由应用于关系属性的批注指定。必须使用批注的元素来指定关系属性所对应的嵌入 ID 中的属性的名称。MapsIdvalueMapsId

代码将如下所示:

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

答案 2

可以使用 IdClass 或嵌入式完成复合键映射。如果要使用 IdClass,则必须使用@Id在 Employee 中注释字段。

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

如果要使用嵌入式作为复合键,请从 Person 中删除 @IdClass(EmployeeId.class) 注释。在 Person 类中也不需要人员和分支字段,因为它们是在嵌入式类中定义的。


推荐