Java Hibernate:如何将嵌入式对象与父对象级联';s自动生成的ID作为外键
问题: 在Hibernate(JPA2.0)中,当我创建父对象时,如何创建具有@OneToOne关系的嵌入式对象 期望值: 当我创建一个用户时,我希望它自动创建相应的属性,并将用户自动生成的Java Hibernate:如何将嵌入式对象与父对象级联';s自动生成的ID作为外键,java,mysql,hibernate,jpa,one-to-one,Java,Mysql,Hibernate,Jpa,One To One,问题: 在Hibernate(JPA2.0)中,当我创建父对象时,如何创建具有@OneToOne关系的嵌入式对象 期望值: 当我创建一个用户时,我希望它自动创建相应的属性,并将用户自动生成的id作为属性的对象id 现实: 尝试创建用户时,出现以下异常: javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transi
id
作为属性的对象id
现实:
尝试创建用户时,出现以下异常:
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.api.user.PropertyEntity.objectId
数据库表:
我有两个MySQL表:users
和properties
users
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | foo | bar |
+----+----------+----------+
| 2 | goo | baz |
+----+----------+----------+
| 3 | woo | hah |
+----+----------+----------+
properties
+----+-----------+-------------+---------+-----------+
| id | object_id | object_type | propkey | propvalue |
+----+-----------+-------------+---------+-----------+
| 1 | 1 | user | sso | true |
+----+-----------+-------------+---------+-----------+
| 2 | 1 | user | ssoid | foobar |
+----+-----------+-------------+---------+-----------+
| 3 | 2 | user | sso | false |
+----+-----------+-------------+---------+-----------+
| 4 | 2 | user | ssoid | null |
+----+-----------+-------------+---------+-----------+
| 5 | 3 | user | sso | false |
+----+-----------+-------------+---------+-----------+
| 6 | 3 | user | ssoid | null |
+----+-----------+-------------+---------+-----------+
Java实体:
一个用户可以有多个属性,但每个属性都与该用户有@OneToOne关系,并且该关系是单向的(即用户创建其属性,而不是相反)
Java中的用户
实体如下所示:
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "username", nullable = false)
private String userName;
@Column(name = "password", nullable = false)
private String password;
@OneToOne
@Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE })
@JoinColumnsOrFormulas(value={
@JoinColumnOrFormula(column=
@JoinColumn(name = "id", referencedColumnName = "object_id", insertable=false, updatable=false, nullable = false)
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="object_type", value="'user'")
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="propkey", value="'sso'")
)
})
private PropertyEntity isSso;
@OneToOne
@Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE })
@JoinColumnsOrFormulas(value={
@JoinColumnOrFormula(column=
@JoinColumn(name = "id", referencedColumnName = "object_id", insertable=false, updatable=false, nullable = false)
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="object_type", value="'user'")
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="propkey", value="'ssoid'")
)
})
private PropertyEntity ssoId;
// Getters & Setters
}
@Entity
@Table(name = "properties")
public class PropertyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "object_id", nullable = false)
private Integer objectId;
@Column(name = "object_type", nullable = false)
private String objectType;
@Column(name = "propkey", nullable = false)
private String name;
@Column(name = "propvalue", nullable = false)
private String value;
// Getters & Setters
}
属性
实体如下所示:
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "username", nullable = false)
private String userName;
@Column(name = "password", nullable = false)
private String password;
@OneToOne
@Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE })
@JoinColumnsOrFormulas(value={
@JoinColumnOrFormula(column=
@JoinColumn(name = "id", referencedColumnName = "object_id", insertable=false, updatable=false, nullable = false)
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="object_type", value="'user'")
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="propkey", value="'sso'")
)
})
private PropertyEntity isSso;
@OneToOne
@Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE })
@JoinColumnsOrFormulas(value={
@JoinColumnOrFormula(column=
@JoinColumn(name = "id", referencedColumnName = "object_id", insertable=false, updatable=false, nullable = false)
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="object_type", value="'user'")
),
@JoinColumnOrFormula(formula=
@JoinFormula(referencedColumnName="propkey", value="'ssoid'")
)
})
private PropertyEntity ssoId;
// Getters & Setters
}
@Entity
@Table(name = "properties")
public class PropertyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "object_id", nullable = false)
private Integer objectId;
@Column(name = "object_type", nullable = false)
private String objectType;
@Column(name = "propkey", nullable = false)
private String name;
@Column(name = "propvalue", nullable = false)
private String value;
// Getters & Setters
}
与大多数与Hibernate注释相关的问题一样,我解决了这个问题,完全消除了它们,并采用了老式的方式(在事务中分别查询创建/更新用户,然后创建/更新每个用户属性记录)
如果有人有一个Hibernate解决方案可以使用,我很乐意接受这个答案。为什么不能用用户的地图替换您的PropertyEntity,并将其作为
@MappedCollection
存储在PropertyEntity
表中?这将消除所有这些麻烦,是一个更干净的设计。每个用户都有自己的属性映射,并且映射不能有重复的键。我知道这似乎没有什么帮助,但你似乎试图强迫Hibernate去做一些它不是设计用来做的事情。您是否在别处使用属性实体
?什么“嵌入”对象?我看不到。没有@Embeddedusage@JamesMassey谢谢你的回复!我开始阅读@MappedCollection上的文档,但有一种感觉,它可能在这里不起作用。也许你可以举个例子?我正在处理一个遗留数据库,properties
表用于存储的不仅仅是user
属性,因此出现了object\u type
列。@NeilStockton我选择了“嵌入式”一词来描述PropertyEntity
对象包含在UserEntity
对象中的事实,不知道@Embedded注释。我想,这个词选得不好。抱歉,如果这引起了任何混乱。