Reputation: 3987
Question:
In Hibernate (JPA 2.0), how can I create embedded objects with @OneToOne relationships when I create the parent object?
Expectation:
When I create a User, I expect it to automatically create the appropriate Properties with the User's auto-generated id
as the Property's object_id
.
Reality:
When I try to create a User, I get the following exception:
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.api.user.PropertyEntity.objectId
Database Tables:
I have two MySQL tables: users
and 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 Entities:
A User can have multiple properties, but each property has a @OneToOne relationship with that User and the relationship is unidirectional (i.e. a User creates its Properties, not the other way around).
The User
entity in Java looks like this:
@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
}
The Property
entity looks like this:
@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
}
Upvotes: 0
Views: 1198
Reputation: 3987
Like most issues related to Hibernate annotations, I resolved this by eliminating them altogether and doing it the old fashioned way (making separate queries in my transaction for creating/updating a user and then creating/updating each user property record).
If anyone has a Hibernate solution that works, I'm happy to accept that answer.
Upvotes: -1