Get rid of unnecessary sql tokens for joins and improve join counting for tests

This commit is contained in:
Christian Beikov 2021-09-10 19:08:43 +02:00
parent 582e7f84aa
commit 905227d2ed
14 changed files with 244 additions and 345 deletions

View File

@ -13,27 +13,27 @@ public enum SqlAstJoinType {
/**
* Represents an inner join.
*/
INNER( "inner" ),
INNER( "" ),
/**
* Represents a left outer join.
*/
LEFT( "left outer" ),
LEFT( "left " ),
/**
* Represents a right outer join.
*/
RIGHT( "right outer" ),
RIGHT( "right " ),
/**
* Represents a cross join (aka a cartesian product).
*/
CROSS( "cross" ),
CROSS( "cross " ),
/**
* Represents a full join.
*/
FULL( "full" );
FULL( "full " );
private final String text;

View File

@ -3494,7 +3494,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
protected void renderJoinType(SqlAstJoinType joinType) {
appendSql( joinType.getText() );
appendSql( " join " );
appendSql( "join " );
}
@Override

View File

@ -12,6 +12,7 @@ import javax.persistence.ManyToOne;
import org.hibernate.orm.test.annotations.manytoone.NotOptionalManyToOneTest.Child;
import org.hibernate.orm.test.annotations.manytoone.NotOptionalManyToOneTest.Parent;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
@ -63,7 +64,7 @@ public class NotOptionalManyToOneTest {
scope.inTransaction(
session -> {
session.get( Parent.class, 2 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "inner", 1 );
statementInspector.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
}
);
}

View File

@ -146,7 +146,7 @@ public class ColumnTransformerTest {
final String sqlString =
// represents how each is mapped in the mappings - see their @ColumnTransformer#read
"select i.integer_val"
+ " from t_staff s inner join integers i on s.id = i.Staff_id"
+ " from t_staff s join integers i on s.id = i.Staff_id"
+ " where s.id = 12";
final List<?> results = session

View File

@ -65,7 +65,7 @@ public class EntityGraphWithFetchAnnotationTest {
.getResultList();
statementInspector.assertExecutedCount( 1 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "left outer join", 0 );
statementInspector.assertNumberOfOccurrenceInQuery( 0, "left join", 0 );
}
);
}
@ -96,7 +96,7 @@ public class EntityGraphWithFetchAnnotationTest {
statementInspector.assertExecutedCount( 1 );
String sql = statementInspector.getSqlQueries().get( 0 );
assertThat( sql, containsString( "left outer join" ) );
assertThat( sql, containsString( "left join" ) );
}
);
}

View File

@ -23,16 +23,13 @@ import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryProducer;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
@ -50,22 +47,13 @@ import static org.hamcrest.MatcherAssert.assertThat;
EagerToOneWithJoinFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
public class EagerToOneWithJoinFetchModeTests {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
@ -92,6 +80,7 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
@Test
public void testFind(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -106,22 +95,16 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
String executedStatement = sqls.get( 0 );
assertThat( executedStatement, containsString( " root_entity " ) );
assertThat( executedStatement, containsString( " left outer join simple_entity " ) );
assertThat(
executedStatement.replaceFirst( "left outer join", "" ),
containsString( " left outer join " )
);
assertThat(
executedStatement.replaceFirst( " left outer join", "" )
.replaceFirst( "left outer join", "" ),
not( containsString( " join " ) )
);
assertThat( executedStatement, containsString( " left join simple_entity " ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.LEFT, 2 );
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -137,20 +120,21 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
assertThat( sqls.get( 0 ), containsString( " root_entity " ) );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -166,24 +150,23 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( true ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -200,24 +183,23 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -234,13 +216,11 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
}
@ -249,6 +229,7 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -265,13 +246,11 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
}
@ -280,6 +259,7 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -296,25 +276,16 @@ public class EagerToOneWithJoinFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( "inner join", "" )
.replaceFirst( "inner join", "" )
,
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);

View File

@ -20,8 +20,9 @@ import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
@ -46,22 +47,13 @@ import static org.hamcrest.MatcherAssert.assertThat;
EagerToOneWithSelectFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
public class EagerToOneWithSelectFetchModeTests {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
@ -80,6 +72,7 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
@Test
public void testFind(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -99,6 +92,7 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
@Test
public void testHql(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -114,22 +108,23 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
assertThat( firstStatement, containsString( " root_entity " ) );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -145,26 +140,25 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -180,26 +174,25 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -215,23 +208,22 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -247,31 +239,23 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( "inner join", "" )
.replaceFirst( "inner join", "" )
,
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -287,23 +271,22 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
}
);
}
@Test
public void testHqlJoinFetchManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -319,19 +302,10 @@ public class EagerToOneWithSelectFetchModeTests implements SessionFactoryProduce
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( " inner join ", "" )
.replaceFirst( " inner join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
}
);
}

View File

@ -17,16 +17,13 @@ import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryProducer;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
@ -47,22 +44,13 @@ import static org.hamcrest.MatcherAssert.assertThat;
LazyToOneWithJoinFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
public class LazyToOneWithJoinFetchModeTests {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
@ -81,6 +69,7 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
@Test
public void testFind(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -94,22 +83,16 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
String executedStatement = sqls.get( 0 );
assertThat( executedStatement, containsString( " root_entity " ) );
assertThat( executedStatement, containsString( " left outer join simple_entity " ) );
assertThat(
executedStatement.replaceFirst( "left outer join", "" ),
containsString( " left outer join " )
);
assertThat(
executedStatement.replaceFirst( " left outer join", "" )
.replaceFirst( "left outer join", "" ),
not( containsString( " join " ) )
);
assertThat( executedStatement, containsString( " left join simple_entity " ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.LEFT, 2 );
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -125,22 +108,23 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, not( containsString( " join " ) ) );
assertThat( firstStatement, containsString( " root_entity " ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -156,26 +140,25 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -191,26 +174,25 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
String thirthStatement = sqls.get( 2 );
assertThat( thirthStatement, containsString( " simple_entity " ) );
assertThat( thirthStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -226,23 +208,23 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -258,31 +240,23 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( "inner join", "" )
.replaceFirst( "inner join", "" )
,
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
assertThat( sqls.get( 1 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 1 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
assertThat( sqls.get( 2 ), containsString( " simple_entity " ) );
assertThat( sqls.get( 2 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 2, 0 );
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -298,29 +272,28 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
String secondStatement = sqls.get( 1 );
assertThat( secondStatement, containsString( " simple_entity " ) );
assertThat( secondStatement, not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
}
);
}
@Test
public void testHqlJoinFetchManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
RootEntity rootEntity = session.createQuery(
"from RootEntity r join fetch r.manyToOneSimpleEntity join fetch r.oneToOneSimpleEntity where r.id = :id",
"from RootEntity r join fetch r.manyToOneSimpleEntity join fetch r.oneToOneSimpleEntity where r.id = :id",
RootEntity.class
).setParameter( "id", 1 ).getSingleResult();
@ -330,19 +303,10 @@ public class LazyToOneWithJoinFetchModeTests implements SessionFactoryProducer {
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( " inner join ", "" )
.replaceFirst( " inner join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
}
);
}

View File

@ -21,7 +21,9 @@ import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
@ -48,22 +50,13 @@ import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize;
LazyToOneWithSelectFetchModeTests.SimpleEntity.class
}
)
@SessionFactory
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
@Override
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
public class LazyToOneWithSelectFetchModeTests {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
@ -82,6 +75,7 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
@Test
public void testFind(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -92,13 +86,14 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls, hasSize( 1 ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
}
);
}
@Test
public void testHql(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -110,7 +105,7 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
List<String> sqls = sqlStatementInterceptor.getSqlQueries();
assertThat( sqls.size(), is( 1 ) );
assertThat( sqls.get( 0 ), not( containsString( " join " ) ) );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
@ -120,6 +115,7 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
@Test
public void testHqlJoinManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -133,12 +129,10 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
assertThat( sqls.size(), is( 1 ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
@ -148,6 +142,7 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
@Test
public void testHqlJoinOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -161,12 +156,10 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
assertThat( sqls.size(), is( 1 ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
assertThat( Hibernate.isInitialized( rootEntity.manyToOneSimpleEntity ), is( false ) );
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
@ -177,6 +170,7 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
@Test
public void testHqlJoinFetchManyToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -192,20 +186,18 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
}
);
}
@Test
public void testHqlJoinManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -221,24 +213,18 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( false ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
containsString( " join " )
);
assertThat(
firstStatement.replaceFirst( " join ", "" ).replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
}
);
}
@Test
public void testHqlJoinFetchOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -254,20 +240,18 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat( firstStatement, containsString( " join simple_entity " ) );
assertThat(
firstStatement.replaceFirst( " join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
}
);
}
@Test
public void testHqlJoinFetchManyToOneAndOneToOne(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
sqlStatementInterceptor.clear();
@ -283,19 +267,10 @@ public class LazyToOneWithSelectFetchModeTests implements SessionFactoryProducer
assertThat( Hibernate.isInitialized( rootEntity.oneToOneSimpleEntity ), is( true ) );
String firstStatement = sqls.get( 0 );
assertThat( firstStatement, containsString( " inner join " ) );
assertThat( firstStatement, containsString( " join " ) );
assertThat( firstStatement, containsString( " root_entity " ) );
assertThat(
firstStatement.replaceFirst( "inner join", "" ),
containsString( " inner join " )
);
assertThat(
firstStatement
.replaceFirst( " inner join ", "" )
.replaceFirst( " inner join ", "" ),
not( containsString( " join " ) )
);
sqlStatementInterceptor.assertNumberOfJoins( 0, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
}
);
}

View File

@ -188,7 +188,7 @@ public class CriteriaLiteralsTest extends BaseEntityManagerFunctionalTestCase {
1,
sqlStatementInterceptor.getSqlQueries().size()
);
sqlStatementInterceptor.assertExecuted( "select a1_0.name from Book b1_0 inner join Author a1_0 on a1_0.book_id=b1_0.id where b1_0.name=? and a1_0.index_id=?" );
sqlStatementInterceptor.assertExecuted( "select a1_0.name from Book b1_0 join Author a1_0 on a1_0.book_id=b1_0.id where b1_0.name=? and a1_0.index_id=?" );
} );
}

View File

@ -106,7 +106,7 @@ public class BatchedManyToManyTest {
// outer join fragment. But at least this wil fail on the majority
// of dialects...
assertFalse(
sql.toLowerCase( Locale.ROOT ).contains( "left outer join" ),
sql.toLowerCase( Locale.ROOT ).contains( "left join" ),
"batch load of many-to-many should use inner join"
);
return super.onPrepareStatement( sql );

View File

@ -15,18 +15,15 @@ import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.stat.Statistics;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryProducer;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.Assert;
@ -50,22 +47,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
OneToManyBidirectionalTest.Item.class
}
)
@SessionFactory
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true"),
@Setting(name = AvailableSettings.HBM2DDL_DATABASE_ACTION, value = "create-drop")
}
)
public class OneToManyBidirectionalTest implements SessionFactoryProducer {
private SQLStatementInterceptor sqlStatementInterceptor;
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
sqlStatementInterceptor = new SQLStatementInterceptor( sessionFactoryBuilder );
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
}
public class OneToManyBidirectionalTest {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
@ -94,6 +83,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
@Test
public void testFetchingSameAssociationTwice(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Statistics statistics = session.getSessionFactory().getStatistics();
@ -111,7 +101,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
inner join "Order" as o1_0 on i1_0."order_id" = o1_0.id
*/
assertJoinFrequencyInSQL( true, 2, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
sqlStatementInterceptor.clear();
assertThat( items.size(), is( 2 ) );
@ -129,7 +119,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
Order itemOrder = item.getOrder();
@ -144,6 +134,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
@Test
public void testRetrievingItem(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Statistics statistics = session.getSessionFactory().getStatistics();
@ -159,7 +150,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where i1_0.id = ?
*/
assertJoinFrequencyInSQL( false, 1, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.LEFT, 1 );
sqlStatementInterceptor.clear();
Order order = item.getOrder();
@ -174,7 +165,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertThat( statistics.getPrepareStatementCount(), is( 2L ) );
@ -199,8 +190,8 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where o1_0.id = ?
*/
assertNoJoinInSQL( 0 );
assertNoJoinInSQL( 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 ).getOrder();
@ -217,7 +208,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertThat( statistics.getPrepareStatementCount(), is( 3L ) );
@ -243,8 +234,8 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where o1_0.id = ?
*/
assertJoinFrequencyInSQL( true, 1, 0 );
assertNoJoinInSQL( 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 ).getOrder();
@ -260,7 +251,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertThat( statistics.getPrepareStatementCount(), is( 3L ) );
@ -284,7 +275,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
inner join "Order" as o1_0 on i1_0."order_id" = o1_0.id
*/
assertJoinFrequencyInSQL( true, 1, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 ).getOrder();
@ -301,7 +292,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertThat( statistics.getPrepareStatementCount(), is( 2L ) );
@ -334,8 +325,8 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where o1_0.id = ?
*/
assertJoinFrequencyInSQL( true, 2, 0 );
assertNoJoinInSQL( 1 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
sqlStatementInterceptor.assertNumberOfJoins( 1, 0 );
sqlStatementInterceptor.clear();
Item item = results.get( 0 );
@ -352,7 +343,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
for ( Item itm : order.getLineItems() ) {
@ -364,6 +355,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
@Test
public void testRetrievingOrder(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction( session -> {
Statistics statistics = session.getSessionFactory().getStatistics();
statistics.clear();
@ -377,7 +369,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where o1_0.id = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
List<Item> lineItems = order.getLineItems();
@ -392,7 +384,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertTrue( Hibernate.isInitialized( lineItems ) );
@ -416,7 +408,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
from "Order" as o1_0
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 );
@ -433,7 +425,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertTrue( Hibernate.isInitialized( lineItems ) );
@ -457,7 +449,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
inner join Item as l1_0 on l1_0."order_id" = o1_0.id
*/
assertJoinFrequencyInSQL( true, 1, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 );
@ -474,7 +466,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertTrue( Hibernate.isInitialized( lineItems ) );
@ -499,7 +491,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
inner join Item as l1_0 on l1_0."order_id" = o1_0.id
*/
assertJoinFrequencyInSQL( true, 1, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 1 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 );
@ -526,12 +518,15 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
).list();
/*
select o1_0.id, o1_0.name
select o1_0.id, l1_0."order_id", l1_0.id, o1_0.name, o2_0.id, o2_0.name
from "Order" as o1_0
inner join Item as l1_0 on l1_0."order_id" = o1_0.id
inner join "Order" as o2_0 on l1_0."order_id" = o2_0.id
*/
assertJoinFrequencyInSQL( true, 1, 0 );
// todo (6.0): this was originally intended to produce only a single SQL join,
// but joins are created before fetches, thus we don't know about bi-directional fetching/joining
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 );
@ -547,7 +542,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
where l1_0."order_id" = ?
*/
assertNoJoinInSQL( 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, 0 );
sqlStatementInterceptor.clear();
assertTrue( Hibernate.isInitialized( lineItems ) );
@ -568,12 +563,15 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
).list();
/*
select o1_0.id, l1_0."order_id", l1_0.id, o1_0.name
select o1_0.id, l1_0."order_id", l1_0.id, o1_0.name, o2_0.id, o2_0.name
from "Order" as o1_0
inner join Item as l1_0 on l1_0."order_id" = o1_0.id
inner join "Order" as o2_0 on l1_0."order_id" = o2_0.id
*/
assertJoinFrequencyInSQL( true, 1, 0 );
// todo (6.0): this was originally intended to produce only a single SQL join,
// but joins are created before fetches, thus we don't know about bi-directional fetching/joining
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 );
@ -593,6 +591,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
@Test
@FailureExpected(jiraKey = "no jira", reason = "order.getLineItems().size() is 4 and not 2 as it should be")
public void testItemFetchJoin(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction( session -> {
Statistics statistics = session.getSessionFactory().getStatistics();
statistics.clear();
@ -610,7 +609,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
inner join Item as l1_0 on l1_0."order_id" = o1_0.id
*/
assertJoinFrequencyInSQL( true, 2, 0 );
sqlStatementInterceptor.assertNumberOfJoins( 0, SqlAstJoinType.INNER, 2 );
sqlStatementInterceptor.clear();
Order order = results.get( 0 ).getOrder();
@ -626,6 +625,7 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
@Test
@FailureExpected(reason = "It should throw an exception because query specified join fetching, but the owner of the fetched association was not present in the select list")
public void testItemJoinWithFetchJoin(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
Assertions.assertThrows( IllegalArgumentException.class, () ->
scope.inTransaction( session -> {
Statistics statistics = session.getSessionFactory().getStatistics();
@ -714,21 +714,4 @@ public class OneToManyBidirectionalTest implements SessionFactoryProducer {
}
}
private void assertJoinFrequencyInSQL(boolean innerJoin, int expectedCount, int sqlIndex) {
String joinPhrase = innerJoin ? "inner join" : "left outer join";
String sql = sqlStatementInterceptor.getSqlQueries().get( sqlIndex );
String re = String.format( "^.+(\\s+%s\\s+.+){%d}.*$", joinPhrase, expectedCount );
assertThat(
String.format( "%s should show up %d time(s) in SQL: %s", joinPhrase, expectedCount, sql ),
sql.matches( re ),
is( true )
);
}
private void assertNoJoinInSQL(int sqlIndex) {
String sql = sqlStatementInterceptor.getSqlQueries().get( sqlIndex );
String re = "^.+\\s+join\\s+.+$";
assertThat( String.format( " 'join' should not appear in SQL: %s", sql ), sql.matches( re ), is( false ) );
}
}

View File

@ -96,7 +96,7 @@ public class SqlAsserts {
private static List<Table> findOtherTables(String otherTablesPart) {
Pattern pattern = Pattern.compile(
"(?<jointype>join|inner join|left join|cross join|left outer join)\\s+(?<table>\\S+)\\s+(?<alias>\\S+)" );
"(?<jointype>join|inner join|left join|right join|full join|cross join)\\s+(?<table>\\S+)\\s+(?<alias>\\S+)" );
Matcher matcher = pattern.matcher( otherTablesPart );
List<Table> joins = new ArrayList<>();
while ( matcher.find() ) {

View File

@ -12,6 +12,7 @@ import java.util.Locale;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.sql.ast.SqlAstJoinType;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
@ -59,6 +60,36 @@ public class SQLStatementInspector implements StatementInspector {
assertEquals( "Number of executed statements ",expected, sqlQueries.size() );
}
public void assertNumberOfJoins(int queryNumber, SqlAstJoinType joinType, int expectedNumberOfOccurrences) {
String query = sqlQueries.get( queryNumber );
String[] parts = query.split( " join " );
int actual = getCount( parts, joinType );
assertThat( "number of " + joinType.getText() + "join", actual, is( expectedNumberOfOccurrences ) );
}
private int getCount(String[] parts, SqlAstJoinType joinType) {
final int end = parts.length - 1;
int count = 0;
for ( int i = 0; i < end; i++ ) {
if ( parts[i].endsWith( " left" ) ) {
count += joinType == SqlAstJoinType.LEFT ? 1 : 0;
}
else if ( parts[i].endsWith( " right" ) ) {
count += joinType == SqlAstJoinType.RIGHT ? 1 : 0;
}
else if ( parts[i].endsWith( " full" ) ) {
count += joinType == SqlAstJoinType.FULL ? 1 : 0;
}
else if ( parts[i].endsWith( " cross" ) ) {
count += joinType == SqlAstJoinType.CROSS ? 1 : 0;
}
else {
count += joinType == SqlAstJoinType.INNER ? 1 : 0;
}
}
return count;
}
public void assertNumberOfOccurrenceInQuery(int queryNumber, String toCheck, int expectedNumberOfOccurrences) {
String query = sqlQueries.get( queryNumber );
int actual = query.split( " " + toCheck + " ", -1 ).length - 1;