我创建了一个具有如下所示的复合ID的实体:
@Entity
@IdClass(CompId.class)
public class CompEntity {
@Id
@ManyToOne(optional = false)
private AccountEntity account;
@Id
@ManyToOne(optional = false)
private ProductEntity product;
...
}
CompId看起来像这样:
public class CompId implements Serializable {
private Long account;
private Long product;
}
帐户和产品都使用自动生成的简单Long ID。
在单元测试中,一切正常。在运行服务器中,当我尝试保存新的CompEntity时,我收到以下错误:
org.springframework.dao.InvalidDataAccessApiUsageException: Can not set java.lang.Long field CompId.product to ProductEntity_$$_jvstd2f_36; nested exception is java.lang.IllegalArgumentException: Can not set java.lang.Long field CompId.product to ProductEntity_$$_jvstd2f_36
据我了解jpa和在线示例,这应该有用,所以我不知道出了什么问题。
我很感激任何建议。
EDIT1:
以下是ProductEntity和AccountEntity
@Entity
public class AccountEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
@Entity
public class ProductEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
编辑2:
CompEntity的存储库
public interface CompRepository extends JpaRepository<CompEntity, CompId> {
...
}
答案 0 :(得分:0)
您需要在关系上使用@JoinColumn来指定要在该实体中引用的列。
@Entity
@IdClass(CompId.class)
public class CompEntity {
@Id
@ManyToOne(optional = false)
@JoinColumn(name = "account_id")
private AccountEntity account;
@Id
@ManyToOne(optional = false)
@JoinColumn(name = "product_id")
private ProductEntity product;
}
答案 1 :(得分:0)
@IdClass用于在休眠实体中创建组合键。
如果父类具有单个键,则在子对象的@IdClass中使用单个键的数据类型。
示例:
//Parent
@Entity
@Table(name = "GROUP")
public class Group implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "GROUP_ID")
private Long groupId;
...
}
//Child
@Entity
@Table(name = "RECORD")
@IdClass(RecordId.class)
public class Record implements Serializable {
@Id
@Column(name = "FIELD_ID")
private Long fieldId;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="GROUP_ID") //Join Column is just for naming purposes
private Group group;
...
}
//Composite Id for Record
public class RecordId implements Serializable {
private Long fieldId;
//Use the @Id datatype from Group
private Long group;
//Getters, Setters, and Constructor omitted for space
}
如果父类具有复合Id类,则将复合Id类用作子对象@IdClass中的数据类型。
示例:
//Parent
@Entity
@Table(name = "GROUP")
@IdClass(GroupId.class)
public class Group implements Serializable {
@Id
@Column(name = "GROUP_ID")
private Long groupId;
@Id
@Column(name = "GROUP_NAME")
private String groupName
...
}
//Composite Id for Group
public class GroupId implements Serializable {
private Long groupId;
//Use the @Id datatype from Group
private String groupName;
//Getters, Setters, and Constructor omitted for space
}
//Child
@Entity
@Table(name = "RECORD")
@IdClass(RecordId.class)
public class Record implements Serializable {
@Id
@Column(name = "FIELD_ID")
private Long fieldId;
/*
* JoinColumns is just used for naming columns:
* -(name) indicates the column to create in this table Record
* -(referencedColumnName) indicates the corresponding column in the parent Group
*/
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="GROUP_ID", referencedColumnName="GROUP_ID"),
@JoinColumn(name="GROUP_NAME", referencedColumnName="GROUP_NAME")
})
private Group group;
...
}
//Composite Id for Record
public class RecordId implements Serializable {
private Long fieldId;
//Use the @IdClass for the datatype because the parent has a composite key.
private GroupId group;
//Getters, Setters, and Constructor omitted for space
}
我投入了赏金,发现我没有在孩子的@IdClass中为父母使用正确的数据类型。我在此答案中加入了创建@IdClass的规则,希望对其他人有所帮助。
P.S。
我最初创建的@IdClass错误,是前几天我头痛的原因。
//Composite Id for Record
public class RecordId implements Serializable {
private Long fieldId;
/*
* WRONG WAY
*
* The cause of my error was due to the wrong dataype being used in this child
@IdClass.
*/
private Group group;
//Getters, Setters, and Constructor omitted for space
}