Reputation: 127
I do as @Tony answered in Hibernate one to zero or one mapping.
I have a class FileMeta
.
@Entity
@Inheritance
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 30)
@DiscriminatorValue("FileMeta")
public class FileMeta {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected long id;
...SOME ATTRIBUTES...
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "FK_GARBAGE")
@NotFound(action = NotFoundAction.IGNORE)
protected Garbage garbage;
@Enumerated(EnumType.ORDINAL)
private FileT type;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "FK_SHARE")
@NotFound(action = NotFoundAction.IGNORE)
private Share share;
...METHODS...
}
And a class Share
.
@Entity
public class Share {
@Id
@GeneratedValue(generator = "shareForeignGenerator")
@GenericGenerator(
name = "shareForeignGenerator",
strategy = "foreign",
parameters = @Parameter(name = "property", value = "fileMeta")
)
private Long id;
...SOME ATTRIBUTES...
@OneToOne(mappedBy = "share")
@PrimaryKeyJoinColumn
@NotFound(action = NotFoundAction.IGNORE)
private FileMeta fileMeta;
...METHODS...
}
And when I tried to fill my FileMeta
with Share
:
Share share = new Share();
share.setFileMeta(fileMeta);
fileMeta.setShare(share);
fileMetaRepository.save(fileMeta);
I received exception: attempted to assign id from null one-to-one property
I followed into Hibernate
. And noticed that, in generator
method, the associatedObject
is not my given Share
object at all, but a new Share
object instantiated by a EventSource
In DefaultMergeEventListener.java
,
if ( copyCache.containsKey( entity ) ) {
persister.setIdentifier( copyCache.get( entity ), id, source );
}
else {
( (MergeContext) copyCache ).put( entity, source.instantiate( persister, id ), true ); //before cascade!
}
The copyCache
sensed that entity
(i.e my given Share
object) is not in copyCache
, and instantiated a new Share
object, which doesn't have a FileMeta
reference obviously.
I've completely confused.
Upvotes: 1
Views: 2816
Reputation: 7495
The solution was mentioned in the comments to the question. It's given below for convenience.
You can use @OneToOne(optional = true)
or simply @OneToOne
since default value of optional
is true
.
If you want to enforce 1 to 1 relationship, specify @OneToOne(optional = false)
.
Upvotes: 2