Skip to content

Commit ad6af3a

Browse files
NathanQingyangXubeikov
authored andcommitted
HHH-14413 fix issue that EntityUpdateAction increments version despite veto on update
1 parent 86ad83f commit ad6af3a

File tree

2 files changed

+105
-21
lines changed

2 files changed

+105
-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: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
10+
import org.hibernate.testing.TestForIssue;
11+
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
12+
import org.junit.Before;
13+
import org.junit.Test;
14+
15+
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
16+
import static org.junit.Assert.assertEquals;
17+
18+
/**
19+
* @author Nathan Xu
20+
* @author Tassilo Karge
21+
*/
22+
@TestForIssue( jiraKey = "HHH-14413" )
23+
public class PreUpdateEventListenerVetoTest extends BaseCoreFunctionalTestCase {
24+
25+
private static final Long EXAMPLE_ID_VALUE = 1L;
26+
27+
@Override
28+
protected Class<?>[] getAnnotatedClasses() {
29+
return new Class<?>[] { ExampleEntity.class };
30+
}
31+
32+
@Override
33+
protected void afterSessionFactoryBuilt() {
34+
super.afterSessionFactoryBuilt();
35+
EventListenerRegistry registry = sessionFactory().getServiceRegistry().getService( EventListenerRegistry.class );
36+
registry.appendListeners(
37+
EventType.PRE_UPDATE,
38+
event -> true
39+
);
40+
}
41+
42+
@Before
43+
public void setUp() {
44+
doInHibernate( this::sessionFactory, session -> {
45+
ExampleEntity entity = new ExampleEntity();
46+
entity.id = EXAMPLE_ID_VALUE;
47+
entity.name = "old_name";
48+
session.save( entity );
49+
} );
50+
}
51+
52+
@Test
53+
public void testVersionNotChangedWhenPreUpdateEventVetoed() {
54+
55+
doInHibernate( this::sessionFactory, session -> {
56+
ExampleEntity entity = session.byId( ExampleEntity.class ).load( EXAMPLE_ID_VALUE );
57+
58+
entity.name = "new_name";
59+
session.update( entity );
60+
61+
final Long versionBeforeFlush = entity.version;
62+
63+
session.flush();
64+
65+
final Long versionAfterFlush = entity.version;
66+
67+
assertEquals( "The entity version must not change when update is vetoed", versionBeforeFlush, versionAfterFlush );
68+
69+
} );
70+
}
71+
72+
@Entity(name = "ExampleEntity")
73+
public static class ExampleEntity {
74+
75+
@Id
76+
Long id;
77+
78+
String name;
79+
80+
@Version
81+
Long version;
82+
83+
}
84+
}

0 commit comments

Comments
 (0)