Reputation: 7218
I have the following stack:
I have been writing a few tests to ensure that when a RuntimeException is thrown the current transaction is rolled back on the database but also on the transactional 2LC.
I have found found some odd results which I was hoping someone could explain.
If I use an @Entity annotated with @Cache(usage=CacheConcurrencyStrategy.TRANSACTIONAL) with a String @Id I see the results I expect when I assign the id and save the entity:
sessionFactory.getCache().containsEntity(MyEntity.class, myIdentifier)
However, if I repeat these tests using an @Entity
which has a generated @Id
(MySQL auto-incrementing long property) as shown:
@Id
@GeneratedValue
private long id;
I find that the entity is never put in the 2LC, regardless of any exceptions thrown.
I have done some debugging and it seems to be down to the different code paths in AbstractSaveEventListener#performSaveOrReplicate
. For an assigned @Id
useIdentityColumn is false and so we instantiate and execute a EntityInsertAction which then puts the new entity in the 2LC.
Conversely, if the @Id
is generated by MySQL we find that the useIdentityColumn is true and we instantiate and execute an EntityIdentityInsertAction. This contains commented out code regarding the 2LC as shown:
//TODO: this bit actually has to be called after all cascades!
//but since identity insert is called *synchronously*,
// instead of asynchronously as other actions, it isn't
/*if ( persister.hasCache() && !persister.isCacheInvalidationRequired() ) {
cacheEntry = new CacheEntry(object, persister, session);
persister.getCache().insert(generatedId, cacheEntry);
}*/
Is there any reason for this? Should the cache insert be done elsewhere? Is this a bug?
If anyone can shed any light on this difference and how this should work I would be very grateful.
I have posted this question over on the Hibernate forums but haven't had much interest.
Upvotes: 1
Views: 230