java.lang.IllegalArgumentException:期待 IdClass 映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38613755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 03:35:28  来源:igfitidea点击:

java.lang.IllegalArgumentException: expecting IdClass mapping

javaspring-4sessionfactoryhibernate-5.xspring-orm

提问by Achaius

I have configured composite primary key for my entity Employeeas follows

我已经为我的实体配置了复合主键,Employee如下所示

Employee.java:

员工.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:

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

I created a SessionFactorybean using class org.springframework.orm.hibernate5.LocalSessionFactoryBeanand mapped all hbm.xmlas a MappingLocations.

SessionFactory使用 class创建了一个beanorg.springframework.orm.hibernate5.LocalSessionFactoryBean并将所有映射hbm.xmlMappingLocations.

My code throws the following error:

我的代码抛出以下错误:

Caused by: java.lang.IllegalArgumentException: expecting IdClass mapping
at org.hibernate.metamodel.internal.AttributeFactory.resolveMember(AttributeFactory.java:971)
at org.hibernate.metamodel.internal.AttributeFactory.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

How can I avoid this error? I am using spring-orm-4.3.1-RELEASEand hibernate-core-5.2.0.Final.

我怎样才能避免这个错误?我正在使用spring-orm-4.3.1-RELEASEhibernate-core-5.2.0.Final

Update

更新

I have created a sample project and I am getting the following error while running...

我创建了一个示例项目,运行时出现以下错误...

Caused by: org.hibernate.AnnotationException: Property of @IdClass not found in entity sample.domain.Employee: employee

Refer the code: https://www.dropbox.com/s/axr8l01iqh0qr29/idclass-using-hibernate5.tar.gz?dl=0

参考代码:https: //www.dropbox.com/s/axr8l01iqh0qr29/idclass-using-hibernate5.tar.gz?dl=0

What I did wrong? Kindly provide your inputs here

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

回答by Adam Michalik

Your situation corresponds to the chapter 2.4.1 Primary Keys Corresponding to Derived Identitiesof the JPA 2.1 Specification.

你的情况对应的章节2.4.1主键对应派生身份的的JPA 2.1规范

The identity of Employeeis derived from identities of Personand Branch. You haven't shown the code of either of them, so I'll assume they have simple primary keys. In that relationship, Personand Branchare "parent entities" and Employeeis a "dependant" entity.

的身份Employee从身份得到的就是PersonBranch。您尚未显示其中任何一个的代码,因此我假设它们具有简单的主键。在这种关系中,PersonBranch是“父实体”并且Employee是“依赖”实体。

The ID of Employeemay be mapped using either IdClassor EmbeddedId, not both at the same time.

的 IDEmployee可以使用IdClass或映射EmbeddedId,而不是同时使用。

See chapter 2.4.1.1 Specification of Derived Identities.

请参阅第2.4.1.1派生身份的规范

If you want to use IdClass, then:

如果你想使用IdClass,那么:

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

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

...

  • If an Idattribute 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 Idattribute of the parent entity.

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

  • Id在实体类属性,在ID类对应的属性必须具有相同的名称。

...

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

So your classes would look like this (getters, setters, superfluous annotations etc. omitted)

所以你的类看起来像这样(省略了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
}

If you use EmbeddedId, then:

如果您使用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 MapsIdannotation applied to the relationship attribute. The valueelement of the MapsIdannotation must be used to specify the name of the attribute within the embedded id to which the relationship attribute corresponds.

如果依赖实体使用嵌入的id来表示其主键,则关系属性对应的嵌入id中的属性必须与父实体的主键类型相同,并且必须由MapsId应用于关系的注解指定属性。注释的value元素MapsId必须用于指定关系属性对应的嵌入 id 中的属性名称。

And the code would look like this:

代码如下所示:

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

回答by shalama

A composite key mapping can be either done with an IdClass or an Embeddable. If you want to use an IdClass you have to annotate your fields in Employee with @Id.

复合键映射可以通过 IdClass 或 Embeddable 完成。如果您想使用 IdClass,您必须使用 @Id 在 Employee 中注释您的字段。

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

If you want to use an Embedded as a composite key please remove the @IdClass(EmployeeId.class) annotation from Person. You also don't need the person and branch field in your Person class because those are defined in your Embedded class.

如果您想使用 Embedded 作为复合键,请从 Person 中删除 @IdClass(EmployeeId.class) 注释。您也不需要 Person 类中的 person 和 branch 字段,因为它们是在您的 Embedded 类中定义的。

回答by Sirsendu

Change to:

改成:

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

}

回答by farrellmr

The IdClass shouldnt be defined as Embeddable -

IdClass 不应该被定义为 Embeddable -

@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() { }
   //....
}

And -

和 -

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

Read your comment - Can I make a suggestion that you map Employee to person_id and branch_id, and not the JPA objects Person and Branch? This will let us test if your hbm config is correct. Id also suggest posting your hbm config as I think there is information missing from this problem

阅读您的评论 - 我能否建议您将 Employee 映射到 person_id 和 branch_id,而不是 JPA 对象 Person 和 Branch?这将让我们测试您的 hbm 配置是否正确。我还建议发布您的 hbm 配置,因为我认为此问题缺少信息

So the table will be similar to -

所以表格将类似于 -

@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() { }
   //....
}

And -

和 -

And -

和 -

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

回答by Akash Mishra

Mention @IdClassannotation with the class which holds the ID. Check the answer at thispost

提起@IdClass注释与持有类ID。检查这个帖子的答案

回答by SEY_91

This link could help you JPA - EmbeddedId with @ManytoOne

此链接可以帮助您 JPA - EmbeddedId with @ManytoOne

Relationship mappings defined within an embedded id class are not supported.Then you need to change the embeddedId class like this

不支持在嵌入式 id 类中定义的关系映射。那么您需要像这样更改 embeddingId 类

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

回答by Byeon0gam

JPA Composite Primary Key

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.

指定映射到实体的多个字段或属性的复合主键类。

主键类中的字段或属性的名称与实体的主键字段或属性的名称必须对应,并且它们的类型必须相同。

The answer is in here. read description for you. enter link description here

答案就在这里。为您阅读说明。在此处输入链接描述

(Sample code)

(示例代码)

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