Hibernate OneToOne: forced to choose between option = false or cascade?

To keep the transferred data small, I created two objects for my files in the database. fileheader

save some general information about files and fileblob

, including fileId

blob. Often I only need to ask a general one fileinformations

.

So I need to load fileblobs

lazily.

As I learned in this discussion and this discussion , this can be achieved with optional = false

. It works great to load fileblobs

lazily. Unfortunately, this affects the cascade conservation.

So here is my attribute in Fileh.class

for blob:

@OneToOne(mappedBy = "fileh", targetEntity = Fileblob.class, fetch = FetchType.LAZY, optional = false)
@org.hibernate.annotations.Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK })
private Fileblob fileblob;

      

If now save a fileh

with attached fileblob

, this error is thrown:

org.hibernate.id.IdentifierGenerationException: Thrown empty identifier for: class Fileblob

if i change from "identity" to "increment" strategy this error comes up:

ERROR SqlExceptionHelper:147 - Cannot add or update a child row: a foreign key constraint fails (`CORE`.`FILEBLOB`, CONSTRAINT

      

FKFILEBLOB412557

FOREIGN KEY ( ID

) REFERENCES fileh

( ID

)) Request: insert into CORE. fileblob

( fileblob

, ID

) values ​​(?,?)

So there is a problem with generating id ... If I now disable cascading save my attribute looks like this.

@OneToOne(mappedBy = "fileh", targetEntity = Fileblob.class, fetch = FetchType.LAZY, optional = false)
private Fileblob fileblob;

      

To save now I have to call

persistentSession.saveOrUpdate(fileh);
persistentSession.saveOrUpdate(fileblob);

      

This is not only what should be done CascadeType.SAVE_UPDATE

? Why does this work for "manual cascading" but not automatically?

Ps: To complete my example here, copy at fileblob.class

@PrimaryKeyJoinColumn   
@OneToOne(targetEntity=Fileh.class, fetch=FetchType.LAZY)   
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK}) 
@JoinColumns({ @JoinColumn(name="`ID`", referencedColumnName="`ID`", unique=true, nullable=false) })    
private Fileh fileh;

@Column(name="`ID`", nullable=false, insertable=false, updatable=false, unique=true)    
@Id 
@GeneratedValue(generator="FILEBLOB_FILEHID_GENERATOR") 
@org.hibernate.annotations.GenericGenerator(name="FILEBLOB_FILEHID_GENERATOR", strategy="foreign", parameters=@org.hibernate.annotations.Parameter(name="property", value="fileh")) 
private int filehId;

      

+3


source to share


2 answers


Well, first I would use JPA cascading instead of hibernate one:

@OneToOne(mappedBy = "fileh", fetch = FetchType.LAZY, optional = false)
private Fileblob fileblob;

      



And Fileblob, I think your config might be a little simpler without these generators, etc. (assuming the id should actually be a foreign key pointing to Fileh.id).

@Column(name="`ID`", nullable=false, unique=true)    
@Id 
private int filehId;

@JoinColumn(name = "id", referencedColumnName = "id")
@OneToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@MapsId
private Fileh fileh;

      

+1


source


I ran into the same problem and have been trying to solve it for days! It turns out that this is a problem that has been in the Hibernate bug system for over 2 years now!

While the answer here helps solve the problem, we are forced to abandon the use of Persist Cascade from the parent Entity (downside as well as mappedBy side )



Please see this link: https://hibernate.atlassian.net/browse/HHH-9670

If you would like to apply lazy loading to a OneToOne relationship and can execute the Persist cascade as usual, please leave a comment to show your concern about the issue!

+1


source







All Articles