Skip to content

Commit 7af0f1c

Browse files
HHH-14413 fix issue that EntityUpdateAction increments version despite veto on update
1 parent 4c9c2a8 commit 7af0f1c

File tree

2 files changed

+97
-21
lines changed

2 files changed

+97
-21
lines changed

hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ public void execute() throws HibernateException {
171171
final SharedSessionContractImplementor session = getSession();
172172
final Object instance = getInstance();
173173

174-
final boolean veto = preUpdate();
174+
if ( preUpdate() ) {
175+
return;
176+
}
175177

176178
final SessionFactoryImplementor factory = session.getFactory();
177179
Object previousVersion = this.previousVersion;
@@ -196,27 +198,24 @@ public void execute() throws HibernateException {
196198
else {
197199
ck = null;
198200
}
199-
200-
if ( !veto ) {
201-
persister.update(
202-
id,
203-
state,
204-
dirtyFields,
205-
hasDirtyCollection,
206-
previousState,
207-
previousVersion,
208-
instance,
209-
rowId,
210-
session
211-
);
212-
}
201+
persister.update(
202+
id,
203+
state,
204+
dirtyFields,
205+
hasDirtyCollection,
206+
previousState,
207+
previousVersion,
208+
instance,
209+
rowId,
210+
session
211+
);
213212

214213
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( instance );
215214
if ( entry == null ) {
216-
throw new AssertionFailure( "possible nonthreadsafe access to session" );
215+
throw new AssertionFailure( "possible non thread safe access to session" );
217216
}
218217

219-
if ( entry.getStatus()==Status.MANAGED || persister.isVersionPropertyGenerated() ) {
218+
if ( entry.getStatus() == Status.MANAGED || persister.isVersionPropertyGenerated() ) {
220219
// get the updated snapshot of the entity state by cloning current state;
221220
// it is safe to copy in place, since by this time no-one else (should have)
222221
// has a reference to the array
@@ -242,12 +241,12 @@ public void execute() throws HibernateException {
242241

243242
final StatisticsImplementor statistics = factory.getStatistics();
244243
if ( persister.canWriteToCache() ) {
245-
if ( persister.isCacheInvalidationRequired() || entry.getStatus()!= Status.MANAGED ) {
246-
persister.getCacheAccessStrategy().remove( session, ck);
244+
if ( persister.isCacheInvalidationRequired() || entry.getStatus() != Status.MANAGED ) {
245+
persister.getCacheAccessStrategy().remove( session, ck );
247246
}
248247
else if ( session.getCacheMode().isPutEnabled() ) {
249248
//TODO: inefficient if that cache is just going to ignore the updated state!
250-
final CacheEntry ce = persister.buildCacheEntry( instance,state, nextVersion, getSession() );
249+
final CacheEntry ce = persister.buildCacheEntry( instance, state, nextVersion, getSession() );
251250
cacheEntry = persister.getCacheEntryStructure().structure( ce );
252251

253252
final boolean put = cacheUpdate( persister, previousVersion, ck );
@@ -270,9 +269,10 @@ else if ( session.getCacheMode().isPutEnabled() ) {
270269

271270
postUpdate();
272271

273-
if ( statistics.isStatisticsEnabled() && !veto ) {
272+
if ( statistics.isStatisticsEnabled() ) {
274273
statistics.updateEntity( getPersister().getEntityName() );
275274
}
275+
276276
}
277277

278278
protected boolean cacheUpdate(EntityPersister persister, Object previousVersion, Object ck) {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.hibernate.event;
2+
3+
import javax.persistence.Entity;
4+
import javax.persistence.Id;
5+
import javax.persistence.Version;
6+
7+
import org.hibernate.event.service.spi.EventListenerRegistry;
8+
import org.hibernate.event.spi.EventType;
9+
import org.hibernate.event.spi.PreUpdateEventListener;
10+
11+
import org.hibernate.testing.TestForIssue;
12+
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
13+
import org.junit.Before;
14+
import org.junit.Test;
15+
16+
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
17+
18+
/**
19+
* @author Nathan Xu
20+
*/
21+
@TestForIssue( jiraKey = "HHH-14413" )
22+
public class PreUpdateEventListenerVetoTest extends BaseCoreFunctionalTestCase {
23+
24+
private static final Long EXAMPLE_ID_VALUE = 1L;
25+
26+
@Override
27+
protected Class<?>[] getAnnotatedClasses() {
28+
return new Class<?>[] { ExampleEntity.class };
29+
}
30+
31+
@Override
32+
protected void afterSessionFactoryBuilt() {
33+
super.afterSessionFactoryBuilt();
34+
EventListenerRegistry registry = sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
35+
registry.appendListeners(
36+
EventType.PRE_UPDATE,
37+
(PreUpdateEventListener) event -> event.getEntity() instanceof ExampleEntity
38+
);
39+
}
40+
41+
@Before
42+
public void setUp() {
43+
doInHibernate( this::sessionFactory, session -> {
44+
ExampleEntity entity = new ExampleEntity();
45+
entity.id = EXAMPLE_ID_VALUE;
46+
entity.name = "old_name";
47+
session.save( entity );
48+
} );
49+
}
50+
51+
@Test
52+
public void testVersionNotTouchedWhenPreUpdateEventVetoed() {
53+
doInHibernate( this::sessionFactory, session -> {
54+
ExampleEntity entity = session.byId( ExampleEntity.class ).load( EXAMPLE_ID_VALUE );
55+
entity.name = "new_name";
56+
session.update( entity );
57+
58+
// without fixing HHH-14413, the following statement would fail due to incremented version
59+
// even though updating has been vetoed
60+
session.delete( entity );
61+
} );
62+
}
63+
64+
@Entity(name = "ExampleEntity")
65+
public static class ExampleEntity {
66+
67+
@Id
68+
Long id;
69+
70+
String name;
71+
72+
@Version
73+
Long version;
74+
75+
}
76+
}

0 commit comments

Comments
 (0)