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
java.lang.IllegalArgumentException: expecting IdClass mapping
提问by Achaius
I have configured composite primary key for my entity Employee
as 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 SessionFactory
bean using class org.springframework.orm.hibernate5.LocalSessionFactoryBean
and mapped all hbm.xml
as a MappingLocations
.
我SessionFactory
使用 class创建了一个beanorg.springframework.orm.hibernate5.LocalSessionFactoryBean
并将所有映射hbm.xml
为MappingLocations
.
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-RELEASE
and hibernate-core-5.2.0.Final
.
我怎样才能避免这个错误?我正在使用spring-orm-4.3.1-RELEASE
和hibernate-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 Employee
is derived from identities of Person
and Branch
. You haven't shown the code of either of them, so I'll assume they have simple primary keys. In that relationship, Person
and Branch
are "parent entities" and Employee
is a "dependant" entity.
的身份Employee
从身份得到的就是Person
和Branch
。您尚未显示其中任何一个的代码,因此我假设它们具有简单的主键。在这种关系中,Person
和Branch
是“父实体”并且Employee
是“依赖”实体。
The ID of Employee
may be mapped using either IdClass
or 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
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 theId
attribute 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
MapsId
annotation applied to the relationship attribute. Thevalue
element of theMapsId
annotation 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
回答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;
...
}