I have an interesting case that might be a critical bug in Hibernate - or not?
I tested it using Hibernate 6.6.9.Final, but it also happens with 6.4.
I have the following entities:
public class DirectoryObject
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@OneToOne
@JoinColumn(name = "DIRECTORY_OBJECT_DATA_ID")
private DirectoryObjectData data;
}
public class DirectoryObjectData
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@OneToOne
@JoinColumn(name = "DIRECTORY_OBJECT_ID")
private DirectoryObject object;
}
@EntityListeners({DirectoryObjectAssignmentEntityListener.class})
public class DirectoryObjectAssignment
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "PARENT_DIRECTORY_OBJECT_ID")
private DirectoryObject parent;
@ManyToOne(optional = false)
@JoinColumn(name = "CHILD_DIRECTORY_OBJECT_ID")
private DirectoryObject child;
}
So the DirectoryObject and DirectoryObjectData entities both have FKs to each other. This means that an UPDATE statement is necessary after persisting both.
The DirectoryObjectAssignmentEntityListener executes a query to load totally unrelated entities (in our real application a Cache is loaded) in the same entity manager/transaction. To achieve using the same entity manager in the test case template I had to store it in a ThreadLocal.
The test case does the following:
- Persists a bunch of DirectoryObject entities
- Persists a bunch of related DirectoryObjectData entities
- It connects the two together by setting them in each other
- Persists a bunch of DirectoryObjectAssignment entities
- Step 4 calls the entity listener, which executes an unrelated query in the same entity manager/transaction
Result: The data from step 3 is missing, DirectoryObject#data is simply NULL. The UPDATE statements are never executed.
When adding a flush() between steps 3 and 4 this does not happen. When removing step 5 this does not happen. When executing step 5 in a new transaction this does not happen.
I was able to create a reproducer:
Why is this happening? Do you think it’s a bug?