Skip to content

Commit 02fa42d

Browse files
mbelladebeikov
authored andcommitted
HHH-17688 Add test for issue
1 parent e8793a8 commit 02fa42d

File tree

2 files changed

+281
-0
lines changed

2 files changed

+281
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
6+
*/
7+
package org.hibernate.orm.test.mapping.generated.delegate;
8+
9+
import java.util.Date;
10+
import java.util.Set;
11+
12+
import org.hibernate.annotations.ColumnDefault;
13+
import org.hibernate.annotations.Generated;
14+
import org.hibernate.annotations.SourceType;
15+
import org.hibernate.annotations.UpdateTimestamp;
16+
import org.hibernate.engine.jdbc.JdbcLogging;
17+
import org.hibernate.engine.spi.SessionImplementor;
18+
import org.hibernate.generator.EventType;
19+
import org.hibernate.internal.CoreMessageLogger;
20+
import org.hibernate.resource.jdbc.ResourceRegistry;
21+
import org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl;
22+
23+
import org.hibernate.testing.logger.LogInspectionHelper;
24+
import org.hibernate.testing.logger.TriggerOnPrefixLogListener;
25+
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
26+
import org.hibernate.testing.orm.junit.DomainModel;
27+
import org.hibernate.testing.orm.junit.Jira;
28+
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
29+
import org.hibernate.testing.orm.junit.SessionFactory;
30+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
31+
import org.junit.jupiter.api.AfterAll;
32+
import org.junit.jupiter.api.BeforeAll;
33+
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.Test;
35+
36+
import org.jboss.logging.Logger;
37+
38+
import jakarta.persistence.Entity;
39+
import jakarta.persistence.GeneratedValue;
40+
import jakarta.persistence.GenerationType;
41+
import jakarta.persistence.Id;
42+
import jakarta.persistence.Inheritance;
43+
import jakarta.persistence.InheritanceType;
44+
45+
import static org.assertj.core.api.Assertions.assertThat;
46+
47+
/**
48+
* @author Marco Belladelli
49+
*/
50+
@DomainModel( annotatedClasses = {
51+
MutationDelegateStatementReleaseTest.IdentityOnly.class,
52+
MutationDelegateStatementReleaseTest.IdentityAndValues.class,
53+
MutationDelegateStatementReleaseTest.BaseEntity.class,
54+
MutationDelegateStatementReleaseTest.ChildEntity.class,
55+
} )
56+
@SessionFactory
57+
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsIdentityColumns.class )
58+
@Jira( "https://hibernate.atlassian.net/browse/HHH-17688" )
59+
public class MutationDelegateStatementReleaseTest {
60+
private TriggerOnPrefixLogListener trigger;
61+
62+
@BeforeAll
63+
public void setUp(SessionFactoryScope scope) {
64+
trigger = new TriggerOnPrefixLogListener( Set.of( "Exception clearing", "Unable to release" ) );
65+
LogInspectionHelper.registerListener(
66+
trigger,
67+
Logger.getMessageLogger(
68+
CoreMessageLogger.class,
69+
ResourceRegistryStandardImpl.class.getName()
70+
)
71+
);
72+
}
73+
74+
@BeforeEach
75+
public void reset() {
76+
trigger.reset();
77+
}
78+
79+
@AfterAll
80+
public void tearDown(SessionFactoryScope scope) {
81+
LogInspectionHelper.clearAllListeners( JdbcLogging.JDBC_MESSAGE_LOGGER );
82+
}
83+
84+
@Test
85+
public void testInsertGeneratedIdentityOnly(SessionFactoryScope scope) {
86+
scope.inTransaction( session -> {
87+
final IdentityOnly entity = new IdentityOnly();
88+
session.persist( entity );
89+
session.flush();
90+
assertNoOrphanStatements( session );
91+
assertThat( entity.getId() ).isNotNull();
92+
assertThat( entity.getName() ).isNull();
93+
} );
94+
95+
assertThat( trigger.wasTriggered() ).as( "Exception encountered while releasing statement" ).isFalse();
96+
}
97+
98+
@Test
99+
public void testInsertGeneratedValuesAndIdentity(SessionFactoryScope scope) {
100+
scope.inTransaction( session -> {
101+
final IdentityAndValues entity = new IdentityAndValues();
102+
session.persist( entity );
103+
session.flush();
104+
assertNoOrphanStatements( session );
105+
assertThat( entity.getId() ).isNotNull();
106+
assertThat( entity.getName() ).isEqualTo( "default_name" );
107+
} );
108+
109+
assertThat( trigger.wasTriggered() ).as( "Exception encountered while releasing statement" ).isFalse();
110+
}
111+
112+
@Test
113+
public void testUpdateGeneratedValuesAndIdentity(SessionFactoryScope scope) {
114+
final Long id = scope.fromTransaction( session -> {
115+
final IdentityAndValues entity = new IdentityAndValues();
116+
session.persist( entity );
117+
session.flush();
118+
return entity.getId();
119+
} );
120+
121+
scope.inTransaction( session -> {
122+
final IdentityAndValues entity = session.find( IdentityAndValues.class, id );
123+
entity.setData( "changed" );
124+
session.flush();
125+
assertNoOrphanStatements( session );
126+
assertThat( entity.getUpdateDate() ).isNotNull();
127+
} );
128+
129+
assertThat( trigger.wasTriggered() ).as( "Exception encountered while releasing statement" ).isFalse();
130+
}
131+
132+
@Test
133+
public void testInsertChildEntity(SessionFactoryScope scope) {
134+
scope.inTransaction( session -> {
135+
final ChildEntity entity = new ChildEntity();
136+
session.persist( entity );
137+
session.flush();
138+
assertNoOrphanStatements( session );
139+
assertThat( entity.getId() ).isNotNull();
140+
assertThat( entity.getName() ).isEqualTo( "default_name" );
141+
assertThat( entity.getChildName() ).isEqualTo( "default_child_name" );
142+
} );
143+
144+
assertThat( trigger.wasTriggered() ).as( "Exception encountered while releasing update statement" ).isFalse();
145+
}
146+
147+
@Test
148+
public void testUpdateChildEntity(SessionFactoryScope scope) {
149+
final Long id = scope.fromTransaction( session -> {
150+
final ChildEntity entity = new ChildEntity();
151+
session.persist( entity );
152+
session.flush();
153+
return entity.getId();
154+
} );
155+
156+
scope.inTransaction( session -> {
157+
final ChildEntity entity = session.find( ChildEntity.class, id );
158+
entity.setData( "changed" );
159+
session.flush();
160+
assertNoOrphanStatements( session );
161+
assertThat( entity.getUpdateDate() ).isNotNull();
162+
assertThat( entity.getChildUpdateDate() ).isNotNull();
163+
} );
164+
165+
assertThat( trigger.wasTriggered() ).as( "Exception encountered while releasing update statement" ).isFalse();
166+
}
167+
168+
private void assertNoOrphanStatements(SessionImplementor session) {
169+
final ResourceRegistry resourceRegistry = session.getJdbcCoordinator()
170+
.getLogicalConnection()
171+
.getResourceRegistry();
172+
assertThat( resourceRegistry.hasRegisteredResources() ).as( "Expected no registered resources" ).isFalse();
173+
}
174+
175+
@Entity( name = "IdentityOnly" )
176+
public static class IdentityOnly {
177+
@Id
178+
@GeneratedValue( strategy = GenerationType.IDENTITY )
179+
private Long id;
180+
181+
private String name;
182+
183+
public Long getId() {
184+
return id;
185+
}
186+
187+
public String getName() {
188+
return name;
189+
}
190+
}
191+
192+
@Entity( name = "IdentityAndValues" )
193+
@SuppressWarnings( "unused" )
194+
public static class IdentityAndValues {
195+
@Id
196+
@GeneratedValue( strategy = GenerationType.IDENTITY )
197+
private Long id;
198+
199+
@Generated( event = EventType.INSERT )
200+
@ColumnDefault( "'default_name'" )
201+
private String name;
202+
203+
@UpdateTimestamp( source = SourceType.DB )
204+
private Date updateDate;
205+
206+
private String data;
207+
208+
public Long getId() {
209+
return id;
210+
}
211+
212+
public String getName() {
213+
return name;
214+
}
215+
216+
public Date getUpdateDate() {
217+
return updateDate;
218+
}
219+
220+
public void setData(String data) {
221+
this.data = data;
222+
}
223+
}
224+
225+
@Entity( name = "BaseEntity" )
226+
@Inheritance( strategy = InheritanceType.JOINED )
227+
@SuppressWarnings( "unused" )
228+
public static class BaseEntity {
229+
@Id
230+
@GeneratedValue( strategy = GenerationType.IDENTITY )
231+
private Long id;
232+
233+
@Generated( event = EventType.INSERT )
234+
@ColumnDefault( "'default_name'" )
235+
private String name;
236+
237+
@UpdateTimestamp( source = SourceType.DB )
238+
private Date updateDate;
239+
240+
@SuppressWarnings( "FieldCanBeLocal" )
241+
private String data;
242+
243+
public Long getId() {
244+
return id;
245+
}
246+
247+
public String getName() {
248+
return name;
249+
}
250+
251+
public Date getUpdateDate() {
252+
return updateDate;
253+
}
254+
255+
public void setData(String data) {
256+
this.data = data;
257+
}
258+
}
259+
260+
@Entity( name = "ChildEntity" )
261+
@SuppressWarnings( "unused" )
262+
public static class ChildEntity extends BaseEntity {
263+
@Generated( event = EventType.INSERT )
264+
@ColumnDefault( "'default_child_name'" )
265+
private String childName;
266+
267+
@UpdateTimestamp( source = SourceType.DB )
268+
private Date childUpdateDate;
269+
270+
public String getChildName() {
271+
return childName;
272+
}
273+
274+
public Date getChildUpdateDate() {
275+
return childUpdateDate;
276+
}
277+
}
278+
}

hibernate-core/src/test/resources/log4j2.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ logger.scanning-coordinator.level=debug
121121
logger.abstract-persistent-collection.name=org.hibernate.collection.spi.AbstractPersistentCollection
122122
logger.abstract-persistent-collection.level=debug
123123

124+
logger.resource-registry-standard.name=org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl
125+
logger.resource-registry-standard.level=debug
126+
124127
logger.cache.name=org.hibernate.cache
125128
logger.cache.level=trace
126129
logger.stat.name=org.hibernate.stat

0 commit comments

Comments
 (0)