Going "behind Hibernate's back" to update foreign key values without an associated entity
Updated: I wound up "solving" the problem by doing the opposite! I now have the entity reference field set as read-only (insertable=false updatable=false), and the foreign key field read-write. This means I need to take special care when saving new entities, but on querying, the entity properties get resolved for me.
I have a bidirectional one-to-many association in my domain model, where I'm using JPA annotations and Hibernate as the persistence provider. It's pretty much your bog-standard parent/child configuration, with one difference being that I want to expose the parent's foreign key as a separate property of the child alongside the reference to a parent instance, like so:
@Entity
public class Child {
@Id @GeneratedValue
Long id;
@Column(name="parent_id", insertable=false, updatable=false)
private Long parentId;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="parent_id")
private Parent parent;
private long timestamp;
}
@Entity
public class Parent {
@Id @GeneratedValue
Long id;
@OrderBy("timestamp")
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<Child> children;
}
This works just fine most of the time, but there are many (legacy) cases when I'd like to put an invalid value in the parent_id column without having to create a bogus Parent first.
Unfortunately, Hibernate won't save values assigned to the parentId
field due to insertable=false, updatable=false
, which it requires when the same column is mapped to multiple properties. Is there any nice way to "go behind开发者_如何学Python Hibernate's back" and sneak values into that field without having to drop down to JDBC or implement an interceptor?
Thanks!
Whats wrong about a bogus Parent? There is a neat way to do it in one place:
public void setParent(Parent parent) {
this.parent = parent;
this.parentId = parent == null ? null : parent.getId();
}
public void setParentId(Long parentId) {
final Parent parent;
if (parentId == null) {
parent = null;
} else {
parent = new Parent();
parent.setId(parentId);
}
setParent(parent);
}
Have you looked into setting the ManyToOne on the child inverse=true, instead of telling the property value to be un-insertable/updatable? If the inverse=true does what it used to, it'll make the Child entity "not the source of truth" for the relationship.. It'll still read the column, but not write it.. I think. It's been a while since I've been in this situation.
精彩评论