After migrating to Spring Boot 3.0 our integration test showed that deleting a user did not work properly.
The User has two properties, where both are defined the same (at least thats what I think, see below).
What I figured is, when I load the User object one of the properties of User are not loaded. Only if I define the property, which can not be loaded, as EAGER. If I now try to delete the User, this does not work because there is still the one property in DB which reference to the User.
I can not figure out whats the problem maybe I am missing something
My User Entity
@Entity
@Data
@Table(name = "user_model")
public class User extends BaseEntity {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
...
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private UserSettings userSettings;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private UserTermsOfUse userTermsOfUse;
...
}
User Terms Of Use which works to load
@Entity
@Table(name = "user_termsofuse")
@Data
public class UserTermsOfUse extends BaseEntity {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "user_id", referencedColumnName = "id")
@ToString.Exclude
private User user;
@Column(name = "accepted_termsofuse")
private String acceptedTermsOfUse;
}
My Settings which does not load:
@Entity
@Table(name = "user_settings")
@Data
public class UserSettings extends BaseEntity {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "user_id", referencedColumnName = "id")
@ToString.Exclude
private User user;
private String language;
private String lastActiveClientId;
}
As you can see in my screenshot, when I load the entity User by ID it only shows the User Terms of Use ant not the User Settings
Just to make clear, they are within the DB :)
Hope Someone can point me to a correct direction
UPDATE
I made a sample project to prove it does not work. The test fails with an NullPonterException
once I try to access the UserSettings
.
This is clearly a bug for hibernate project.
Have opened a ticket for it here with both the bug described in the question from kism3t and also with what seems to be a workaround to bypass the issue.
Have checked the current non stable released versions of hibernate 6.2.0
and the bug is still there. So probably is undetected yet.
For the moment the following workaround seems to bypass the issue
@Entity
public class User {
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
private UserSettings userSettings;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
private UserTermsOfUse userTermsOfUse;
}
If the owning side of the @OneToOne
declares the same fetchType of Lazy
somehow the issue is bypassed.
So it works with
@Entity
public class UserTermsOfUse {
....
@OneToOne(fetch = FetchType.LAZY) // <-------------
private User user;
}
and
@Entity
public class UserSettings {
....
@OneToOne(fetch = FetchType.LAZY) // <-------------
private User user;
}
This was indeed a bug of hibernate project. It is solved in version 6.1.7.Final and future versions.