Skip to content

Commit 3f252df

Browse files
committed
[#1770] Add test for iniailizing field after fetching it
1 parent 225236f commit 3f252df

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

integration-tests/bytecode-enhancements-it/src/test/java/org/hibernate/reactive/it/LazyBasicFieldTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
package org.hibernate.reactive.it;
77

88
import org.hibernate.LazyInitializationException;
9+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
10+
import org.hibernate.cfg.Configuration;
11+
12+
import org.hibernate.testing.SqlStatementTracker;
913

1014
import io.smallrye.mutiny.Uni;
1115
import java.util.Collection;
1216
import java.util.List;
1317
import java.util.concurrent.TimeUnit;
1418

19+
import org.junit.jupiter.api.BeforeEach;
1520
import org.junit.jupiter.api.Test;
1621

1722
import io.vertx.junit5.Timeout;
@@ -25,6 +30,33 @@
2530
*/
2631
@Timeout(value = 10, timeUnit = TimeUnit.MINUTES)
2732
public class LazyBasicFieldTest extends BaseReactiveIT {
33+
34+
private static SqlStatementTracker sqlTracker;
35+
36+
@Override
37+
protected Configuration constructConfiguration() {
38+
Configuration configuration = super.constructConfiguration();
39+
40+
// Construct a tracker that collects query statements via the SqlStatementLogger framework.
41+
// Pass in configuration properties to hand off any actual logging properties
42+
sqlTracker = new SqlStatementTracker( LazyBasicFieldTest::selectQueryFilter, configuration.getProperties() );
43+
return configuration;
44+
}
45+
46+
@BeforeEach
47+
public void clearTracker() {
48+
sqlTracker.clear();
49+
}
50+
51+
@Override
52+
protected void addServices(StandardServiceRegistryBuilder builder) {
53+
sqlTracker.registerService( builder );
54+
}
55+
56+
private static boolean selectQueryFilter(String s) {
57+
return s.toLowerCase().startsWith( "select " );
58+
}
59+
2860
@Override
2961
protected Collection<Class<?>> annotatedEntities() {
3062
return List.of( Crew.class );
@@ -51,6 +83,31 @@ public void testFetchBasicField(VertxTestContext context) {
5183
);
5284
}
5385

86+
@Test
87+
public void testFetchBasicFieldAlsoInitializesIt(VertxTestContext context) {
88+
final Crew emily = new Crew();
89+
emily.setId( 21L );
90+
emily.setName( "Emily Jackson" );
91+
emily.setRole( "Passenger" );
92+
emily.setFate( "Unknown" );
93+
94+
test( context, getMutinySessionFactory()
95+
.withTransaction( session -> session.persist( emily ) )
96+
.chain( () -> getMutinySessionFactory()
97+
.withSession( session -> session
98+
.find( Crew.class, emily.getId() )
99+
.call( crew -> session.fetch( crew, Crew_.role )
100+
.invoke( role -> assertThat( role ).isEqualTo( emily.getRole() ) ) )
101+
.invoke( () -> sqlTracker.clear() )
102+
.call( crew -> session.fetch( crew, Crew_.role )
103+
.invoke( role -> {
104+
// No select query expected, the previous fetch must have initialized the role attribute
105+
assertThat(sqlTracker.getLoggedQueries()).hasSize( 0 );
106+
assertThat( role ).isEqualTo( emily.getRole() );} )
107+
) ) )
108+
);
109+
}
110+
54111
@Test
55112
public void testTransparentLazyFetching(VertxTestContext context) {
56113
final Crew emily = new Crew();
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.testing;
7+
8+
import org.hibernate.boot.registry.StandardServiceInitiator;
9+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
10+
import org.hibernate.engine.jdbc.internal.Formatter;
11+
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
12+
import org.hibernate.reactive.provider.Settings;
13+
import org.hibernate.service.spi.ServiceRegistryImplementor;
14+
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Properties;
19+
import java.util.function.Predicate;
20+
21+
/**
22+
* Track sql queries.
23+
* <p>
24+
* Check {@link #registerService(StandardServiceRegistryBuilder)} to register an instance of this class.
25+
* It's not thread-safe.
26+
* </p>
27+
* @see #registerService(StandardServiceRegistryBuilder)
28+
*/
29+
public class SqlStatementTracker extends SqlStatementLogger {
30+
31+
private final Predicate<String> filter;
32+
33+
private final List<String> statements = new ArrayList<>();
34+
35+
public SqlStatementTracker(Predicate<String> predicate) {
36+
this.filter = predicate;
37+
}
38+
39+
public SqlStatementTracker(Predicate<String> predicate, Properties properties) {
40+
super(
41+
toBoolean( properties.get( Settings.SHOW_SQL ) ),
42+
toBoolean( properties.get( Settings.FORMAT_SQL ) ),
43+
toBoolean( properties.get( Settings.HIGHLIGHT_SQL ) ),
44+
toLong( properties.get( Settings.LOG_SLOW_QUERY ) )
45+
);
46+
this.filter = predicate;
47+
}
48+
49+
private static boolean toBoolean(Object obj) {
50+
return Boolean.parseBoolean( (String) obj );
51+
}
52+
53+
private static long toLong(Object obj) {
54+
if ( obj == null ) {
55+
return 0;
56+
}
57+
return Long.parseLong( (String) obj );
58+
}
59+
60+
@Override
61+
public void logStatement(String statement, Formatter formatter) {
62+
addSql( statement );
63+
super.logStatement( statement, formatter );
64+
}
65+
66+
private void addSql(String sql) {
67+
if ( filter.test( sql ) ) {
68+
statements.add( sql );
69+
}
70+
}
71+
72+
public List<String> getLoggedQueries() {
73+
return statements;
74+
}
75+
76+
public void clear() {
77+
statements.clear();
78+
}
79+
80+
/**
81+
* Register the current sql tracker to the {@link StandardServiceRegistryBuilder}.
82+
*
83+
* @param builder the {@link StandardServiceRegistryBuilder} for the creation of the factory
84+
*/
85+
public void registerService(StandardServiceRegistryBuilder builder) {
86+
Initiator initiator = new Initiator( this );
87+
builder.addInitiator( initiator );
88+
}
89+
90+
private static class Initiator implements StandardServiceInitiator<SqlStatementLogger> {
91+
private final SqlStatementTracker sqlStatementTracker;
92+
93+
public Initiator(SqlStatementTracker sqlStatementTracker) {
94+
this.sqlStatementTracker = sqlStatementTracker;
95+
}
96+
97+
@Override
98+
public SqlStatementLogger initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
99+
return sqlStatementTracker;
100+
}
101+
102+
@Override
103+
public Class<SqlStatementLogger> getServiceInitiated() {
104+
return SqlStatementLogger.class;
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)