So I was trying to get some unidirectional one-to-one mapping the last day and after some testing I decided to try out the other approach. Is stumbled upon a problem when I tried to persist my entities. I can't find a way to force hibernate to populate my foreign key field with reference back and forth at the same time. It sets them only one way and not the other:
Item ---> ItemInfo (I populate info field manually in constructor)
Item <-x- ItemInfo (hibernate doesn't set item field on persist)
so when I try to persist Item
entity I get exception from @MapsId
: attempted to assign id from null one-to-one property [by.test.hm.ItemInfo.item]
My tables:
t_item_info(item_id)
references t_item(id)
field. Only t_item(id)
column is auto incremented
my classes:
@Entity
@Table(name = "t_item")
class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(mappedBy = "item", cascade = CascadeType.ALL,
fetch = FetchType.LAZY, orphanRemoval = true, optional = false)
private ItemInfo info;
private String name;
}
and the other one:
@Entity
@Table(name = "t_item_info")
class ItemInfo {
@Id
private Long itemId;
@MapsId
@OneToOne
@JoinColumn(name = "item_id", referencedColumnName = "id")
private Item item;
private String descr;
}
How I create and persist objects:
Item item = new Item(
null,
new ItemInfo(null, "Somde description"),
"Some name"
);
itemRepo.save(item);
Exception:
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property [by.test.hm.ItemInfo.item] at org.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:87) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:115) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113)
I tried a lot of things. Switching side where I declare mappedBy from Item
to ItemInfo
in which case everything just stops working because ItemInfo
tries to get persisted first. I tried all possible combinations of optional = false\true
and nullable = false\true
and nothing seems to work =(
I know I can set the references manually an exception will be gone, and I know I can use @PostPersist
to set it but i'm looking for answer when hibernate does this for me automatically
PS: I posted similar question regarding unidirectional mapping and I'm new around here so I hope I did nothing wrong when created a new question for similar issue
@Entity
@Table(name = "t_item")
class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(mappedBy = "item", cascade = CascadeType.ALL,
fetch = FetchType.LAZY, orphanRemoval = true, optional=false)
private ItemInfo info;
@Column(name="name)
private String name;
// Getters and setters omitted for brevity
private void setItemInfo(ItemInfo info) {
if (info == null) {
if (this.info != null) {
this.info.setInfo(null);
}
} else {
info.setInfo(this);
}
this.info = info;
}
@Entity
@Table(name = "t_item_info")
class ItemInfo {
@Id
private Long itemId;
@OneToOne
@MapsId
@JoinColumn(name="item_id)
private Item item;
@Column(name="description")
private String description;
// Getters and setters omitted for brevity
}
Out of topic, but your classes have same name.
Try the above code ..............