re-enable tests

re-organize some tests
o.h.test.hql.EntityJoinTest
fixed RIGHT JOIN handling
This commit is contained in:
Steve Ebersole 2021-04-19 14:34:48 -05:00
parent 107aab03eb
commit cebb9d7649
4 changed files with 412 additions and 668 deletions

View File

@ -242,20 +242,32 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
private final Stack<ParameterDeclarationContext> parameterDeclarationContextStack = new StandardStack<>();
private final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>();
private final BasicDomainType<Integer> integerDomainType;
private final JavaTypeDescriptor<List<?>> listJavaTypeDescriptor;
private final JavaTypeDescriptor<Map<?,?>> mapJavaTypeDescriptor;
private ParameterCollector parameterCollector;
private BasicDomainType<Integer> integerDomainType;
private JavaTypeDescriptor<List<?>> listJavaTypeDescriptor;
private JavaTypeDescriptor<Map<?,?>> mapJavaTypeDescriptor;
@SuppressWarnings("WeakerAccess")
public SemanticQueryBuilder(SqmCreationOptions creationOptions, SqmCreationContext creationContext) {
this.creationOptions = creationOptions;
this.creationContext = creationContext;
this.dotIdentifierConsumerStack = new StandardStack<>( new BasicDotIdentifierConsumer( this ) );
this.integerDomainType = creationContext
.getNodeBuilder()
.getTypeConfiguration()
.standardBasicTypeForJavaType( Integer.class );
this.listJavaTypeDescriptor = creationContext
.getNodeBuilder()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( List.class );
this.mapJavaTypeDescriptor = creationContext
.getNodeBuilder()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.resolveDescriptor( Map.class );
}
@Override
@ -855,24 +867,12 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
final SqmDynamicInstantiation<?> dynamicInstantiation;
if ( ctx.dynamicInstantiationTarget().MAP() != null ) {
if ( mapJavaTypeDescriptor == null ) {
mapJavaTypeDescriptor = creationContext.getJpaMetamodel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.getDescriptor( Map.class );
}
dynamicInstantiation = SqmDynamicInstantiation.forMapInstantiation(
mapJavaTypeDescriptor,
creationContext.getNodeBuilder()
);
}
else if ( ctx.dynamicInstantiationTarget().LIST() != null ) {
if ( listJavaTypeDescriptor == null ) {
listJavaTypeDescriptor = creationContext.getJpaMetamodel()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.getDescriptor( List.class );
}
dynamicInstantiation = SqmDynamicInstantiation.forListInstantiation(
listJavaTypeDescriptor,
creationContext.getNodeBuilder()
@ -1452,7 +1452,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
throw new SemanticException( "FULL OUTER joins are not yet supported : " + parserJoin.getText() );
}
else if ( joinTypeQualifier.RIGHT() != null ) {
throw new SemanticException( "RIGHT OUTER joins are not yet supported : " + parserJoin.getText() );
joinType = SqmJoinType.RIGHT;
}
else if ( joinTypeQualifier.OUTER() != null || joinTypeQualifier.LEFT() != null ) {
joinType = SqmJoinType.LEFT;
@ -1475,6 +1475,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
);
try {
//noinspection rawtypes
final SqmQualifiedJoin join = (SqmQualifiedJoin) parserJoin.qualifiedJoinRhs().path().accept( this );
// we need to set the alias here because the path could be treated - the treat operator is
@ -1486,8 +1487,13 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
sqmRoot.addSqmJoin( join );
}
else {
if ( joinType == SqmJoinType.RIGHT ) {
throw new SemanticException( "RIGHT OUTER attribute-joins are not supported : " + parserJoin.getText() );
}
if ( getCreationOptions().useStrictJpaCompliance() ) {
if ( join.getExplicitAlias() != null ){
//noinspection rawtypes
if ( ( (SqmAttributeJoin) join ).isFetched() ) {
throw new StrictJpaComplianceViolation(
"Encountered aliased fetch join, but strict JPQL compliance was requested",

View File

@ -0,0 +1,390 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.orm.test.query.hql;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.NaturalId;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.hql.HqlTranslator;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.sql.SqmTranslation;
import org.hibernate.query.sqm.sql.SqmTranslator;
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
/**
* @author Steve Ebersole, Jan Martiska
* @author Christian Beikov
*/
@DomainModel( annotatedClasses = { EntityJoinTest.FinancialRecord.class, EntityJoinTest.User.class, EntityJoinTest.Customer.class } )
@SessionFactory
public class EntityJoinTest {
@Test
public void testInnerEntityJoins(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// this should get financial records which have a lastUpdateBy user set
List<Object[]> result = session.createQuery(
"select r.id, c.name, u.id, u.username " +
"from FinancialRecord r " +
" inner join r.customer c " +
" inner join User u on r.lastUpdateBy = u.username",
Object[].class
).list();
assertThat( result.size(), is( 1 ) );
Object[] steveAndAcme = result.get( 0 );
assertThat( steveAndAcme[0], is( 1 ) );
assertThat( steveAndAcme[1], is( "Acme" ) );
assertThat( steveAndAcme[3], is( "steve" ) );
// NOTE that this leads to not really valid SQL, although some databases might support it /
// result = session.createQuery(
// "select r.id, r.customer.name, u.id, u.username " +
// "from FinancialRecord r " +
// " inner join User u on r.lastUpdateBy = u.username"
// ).list();
// assertThat( result.size(), is( 1 ) );
}
);
}
@Test
public void testLeftOuterEntityJoins(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// this should get all financial records even if their lastUpdateBy user is null
List<Object[]> result = session.createQuery(
"select r.id, u.id, u.username " +
"from FinancialRecord r " +
" left join User u on r.lastUpdateBy = u.username" +
" order by r.id",
Object[].class
).list();
assertThat( result.size(), is( 2 ) );
Object[] stevesRecord = result.get( 0 );
assertThat( stevesRecord[0], is( 1 ) );
assertThat( stevesRecord[2], is( "steve" ) );
Object[] noOnesRecord = result.get( 1 );
assertThat( noOnesRecord[0], is( 2 ) );
assertNull( noOnesRecord[2] );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-11337")
@SkipForDialect( dialectClass = SybaseDialect.class )
public void testLeftOuterEntityJoinsWithImplicitInnerJoinInSelectClause(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// this should get all financial records even if their lastUpdateBy user is null
List<Object[]> result = session.createQuery(
"select r.id, u.id, u.username, r.customer.name " +
"from FinancialRecord r " +
" left join User u on r.lastUpdateBy = u.username" +
" order by r.id",
Object[].class
).list();
assertThat( result.size(), is( 2 ) );
Object[] stevesRecord = result.get( 0 );
assertThat( stevesRecord[0], is( 1 ) );
assertThat( stevesRecord[2], is( "steve" ) );
Object[] noOnesRecord = result.get( 1 );
assertThat( noOnesRecord[0], is( 2 ) );
assertNull( noOnesRecord[2] );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-11340")
public void testJoinOnEntityJoinNode(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// this should get all financial records even if their lastUpdateBy user is null
List<Object[]> result = session.createQuery(
"select u.username, c.name " +
"from FinancialRecord r " +
" left join User u on r.lastUpdateBy = u.username " +
" left join u.customer c " +
" order by r.id",
Object[].class
).list();
assertThat( result.size(), is( 2 ) );
Object[] stevesRecord = result.get( 0 );
assertThat( stevesRecord[0], is( "steve" ) );
assertThat( stevesRecord[1], is( "Acme" ) );
Object[] noOnesRecord = result.get( 1 );
assertNull( noOnesRecord[0] );
assertNull( noOnesRecord[1] );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-11538")
public void testNoImpliedJoinGeneratedForEqualityComparison(SessionFactoryScope scope) {
final String qry = "select r.id, cust.name " +
"from FinancialRecord r " +
" join Customer cust on r.customer = cust" +
" order by r.id";
scope.inTransaction(
(session) -> {
final SessionFactoryImplementor factory = scope.getSessionFactory();
final EntityMappingType customerEntityDescriptor = factory.getRuntimeMetamodels()
.getMappingMetamodel()
.findEntityDescriptor( Customer.class );
final QueryEngine queryEngine = factory.getQueryEngine();
final HqlTranslator hqlTranslator = queryEngine.getHqlTranslator();
final SqmTranslatorFactory sqmTranslatorFactory = queryEngine.getSqmTranslatorFactory();
final SqmStatement<Object> sqm = hqlTranslator.translate( qry );
final SqmTranslator<SelectStatement> selectTranslator = sqmTranslatorFactory.createSelectTranslator(
(SqmSelectStatement<?>) sqm,
QueryOptions.NONE,
DomainParameterXref.empty(),
QueryParameterBindings.NO_PARAM_BINDINGS,
LoadQueryInfluencers.NONE,
factory
);
final SqmTranslation<SelectStatement> sqmTranslation = selectTranslator.translate();
final SelectStatement sqlAst = sqmTranslation.getSqlAst();
final List<TableGroup> roots = sqlAst.getQuerySpec().getFromClause().getRoots();
assertThat( roots.size(), is( 1 ) );
final TableGroup rootTableGroup = roots.get( 0 );
assertThat( rootTableGroup.getTableGroupJoins().size(), is( 1 ) );
final TableGroupJoin tableGroupJoin = rootTableGroup.getTableGroupJoins().get( 0 );
assertThat( tableGroupJoin.getJoinedGroup().getModelPart(), is( customerEntityDescriptor ) );
}
);
}
@Test
public void testRightOuterEntityJoins(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// this should get all users even if they have no financial records
List<Object[]> result = session.createQuery(
"select r.id, u.id, u.username " +
"from FinancialRecord r " +
" right join User u on r.lastUpdateBy = u.username" +
" order by u.id",
Object[].class
).list();
assertThat( result.size(), is( 2 ) );
Object[] steveAndAcme = result.get( 0 );
assertThat( steveAndAcme[ 0 ], is( 1 ) );
assertThat( steveAndAcme[ 2 ], is( "steve" ) );
Object[] janeAndNull = result.get( 1 );
assertNull( janeAndNull[ 0 ] );
assertThat( janeAndNull[ 2 ], is( "jane" ) );
}
);
}
@BeforeEach
public void createTestData(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme" );
session.save( customer );
session.save( new User( 1, "steve", customer ) );
session.save( new User( 2, "jane" ) );
session.save( new FinancialRecord( 1, customer, "steve" ) );
session.save( new FinancialRecord( 2, customer, null ) );
}
);
}
@AfterEach
public void dropTestData(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
session.createQuery( "delete FinancialRecord" ).executeUpdate();
session.createQuery( "delete User" ).executeUpdate();
session.createQuery( "delete Customer" ).executeUpdate();
}
);
}
@Entity(name = "Customer")
@Table(name = "`a:customer`")
public static class Customer {
private Integer id;
private String name;
public Customer() {
}
public Customer(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "FinancialRecord")
@Table(name = "`a:financial_record`")
public static class FinancialRecord {
private Integer id;
private Customer customer;
private String lastUpdateBy;
public FinancialRecord() {
}
public FinancialRecord(Integer id, Customer customer, String lastUpdateBy) {
this.id = id;
this.customer = customer;
this.lastUpdateBy = lastUpdateBy;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne
@JoinColumn
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String getLastUpdateBy() {
return lastUpdateBy;
}
public void setLastUpdateBy(String lastUpdateBy) {
this.lastUpdateBy = lastUpdateBy;
}
}
@Entity(name = "User")
@Table(name = "`a:user`")
public static class User {
private Integer id;
private String username;
private Customer customer;
public User() {
}
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
public User(Integer id, String username, Customer customer) {
this.id = id;
this.username = username;
this.customer = customer;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@NaturalId
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@ManyToOne(fetch = FetchType.LAZY)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
}

View File

@ -1,350 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.hql;
import java.util.Collections;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.annotations.NaturalId;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.core.Is.is;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
/**
* @author Steve Ebersole, Jan Martiska
* @author Christian Beikov
*/
public class EntityJoinTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {FinancialRecord.class, User.class, Customer.class};
}
@Before
public void prepare() {
createTestData();
}
@After
public void cleanup() {
deleteTestData();
}
@Test()
public void testInnerEntityJoins() {
doInHibernate( this::sessionFactory, session -> {
// this should get financial records which have a lastUpdateBy user set
List<Object[]> result = session.createQuery(
"select r.id, c.name, u.id, u.username " +
"from FinancialRecord r " +
" inner join r.customer c " +
" inner join User u on r.lastUpdateBy = u.username"
).list();
assertThat( result.size(), is( 1 ) );
Object[] steveAndAcme = result.get( 0 );
assertThat( steveAndAcme[0], is( 1 ) );
assertThat( steveAndAcme[1], is( "Acme" ) );
assertThat( steveAndAcme[3], is( "steve" ) );
// NOTE that this leads to not really valid SQL, although some databases might support it /
// result = session.createQuery(
// "select r.id, r.customer.name, u.id, u.username " +
// "from FinancialRecord r " +
// " inner join User u on r.lastUpdateBy = u.username"
// ).list();
// assertThat( result.size(), is( 1 ) );
} );
}
@Test
public void testLeftOuterEntityJoins() {
doInHibernate( this::sessionFactory, session -> {
// this should get all financial records even if their lastUpdateBy user is null
List<Object[]> result = session.createQuery(
"select r.id, u.id, u.username " +
"from FinancialRecord r " +
" left join User u on r.lastUpdateBy = u.username" +
" order by r.id"
).list();
assertThat( result.size(), is( 2 ) );
Object[] stevesRecord = result.get( 0 );
assertThat( stevesRecord[0], is( 1 ) );
assertThat( stevesRecord[2], is( "steve" ) );
Object[] noOnesRecord = result.get( 1 );
assertThat( noOnesRecord[0], is( 2 ) );
assertNull( noOnesRecord[2] );
} );
}
@Test
@TestForIssue(jiraKey = "HHH-11337")
@SkipForDialect(SybaseDialect.class)
public void testLeftOuterEntityJoinsWithImplicitInnerJoinInSelectClause() {
doInHibernate( this::sessionFactory, session -> {
// this should get all financial records even if their lastUpdateBy user is null
List<Object[]> result = session.createQuery(
"select r.id, u.id, u.username, r.customer.name " +
"from FinancialRecord r " +
" left join User u on r.lastUpdateBy = u.username" +
" order by r.id"
).list();
assertThat( result.size(), is( 2 ) );
Object[] stevesRecord = result.get( 0 );
assertThat( stevesRecord[0], is( 1 ) );
assertThat( stevesRecord[2], is( "steve" ) );
Object[] noOnesRecord = result.get( 1 );
assertThat( noOnesRecord[0], is( 2 ) );
assertNull( noOnesRecord[2] );
} );
}
@Test
@TestForIssue(jiraKey = "HHH-11340")
public void testJoinOnEntityJoinNode() {
doInHibernate( this::sessionFactory, session -> {
// this should get all financial records even if their lastUpdateBy user is null
List<Object[]> result = session.createQuery(
"select u.username, c.name " +
"from FinancialRecord r " +
" left join User u on r.lastUpdateBy = u.username " +
" left join u.customer c " +
" order by r.id"
).list();
assertThat( result.size(), is( 2 ) );
Object[] stevesRecord = result.get( 0 );
assertThat( stevesRecord[0], is( "steve" ) );
assertThat( stevesRecord[1], is( "Acme" ) );
Object[] noOnesRecord = result.get( 1 );
assertNull( noOnesRecord[0] );
assertNull( noOnesRecord[1] );
} );
}
@Test
@TestForIssue(jiraKey = "HHH-11538")
public void testNoImpliedJoinGeneratedForEqualityComparison() {
// doInHibernate( this::sessionFactory, session -> {
// final HQLQueryPlan plan = sessionFactory().getQueryInterpretationCache().getHQLQueryPlan(
// "select r.id, cust.name " +
// "from FinancialRecord r " +
// " join Customer cust on r.customer = cust" +
// " order by r.id",
// false,
// Collections.EMPTY_MAP
// );
// assertEquals( 1, plan.getTranslators().length );
// final QueryTranslator translator = plan.getTranslators()[0];
// final String generatedSql = translator.getSQLString();
//
// int tableReferenceIndex = generatedSql.indexOf( " customer " );
// assertNotEquals("Generated SQL doesn't contain a table reference for customer", -1, tableReferenceIndex );
// int nextTableReferenceIndex = generatedSql.indexOf( " customer ", tableReferenceIndex + 1 );
// assertEquals("Generated SQL wrongly joined customer twice", -1, nextTableReferenceIndex );
// } );
throw new NotYetImplementedFor6Exception( getClass() );
}
@Test
public void testRightOuterEntityJoins() {
doInHibernate( this::sessionFactory, session -> {
// this should get all users even if they have no financial records
List<Object[]> result = session.createQuery(
"select r.id, u.id, u.username " +
"from FinancialRecord r " +
" right join User u on r.lastUpdateBy = u.username" +
" order by u.id"
).list();
assertThat( result.size(), is( 2 ) );
Object[] steveAndAcme = result.get( 0 );
assertThat( steveAndAcme[0], is( 1 ) );
assertThat( steveAndAcme[2], is( "steve" ) );
Object[] janeAndNull = result.get( 1 );
assertNull( janeAndNull[0] );
assertThat( janeAndNull[2], is( "jane" ) );
} );
}
private void createTestData() {
doInHibernate( this::sessionFactory, session -> {
final Customer customer = new Customer( 1, "Acme" );
session.save( customer );
session.save( new User( 1, "steve", customer ) );
session.save( new User( 2, "jane" ) );
session.save( new FinancialRecord( 1, customer, "steve" ) );
session.save( new FinancialRecord( 2, customer, null ) );
} );
}
private void deleteTestData() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete FinancialRecord" ).executeUpdate();
session.createQuery( "delete User" ).executeUpdate();
session.createQuery( "delete Customer" ).executeUpdate();
} );
}
@Entity(name = "Customer")
@Table(name = "customer")
public static class Customer {
private Integer id;
private String name;
public Customer() {
}
public Customer(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "FinancialRecord")
@Table(name = "financial_record")
public static class FinancialRecord {
private Integer id;
private Customer customer;
private String lastUpdateBy;
public FinancialRecord() {
}
public FinancialRecord(Integer id, Customer customer, String lastUpdateBy) {
this.id = id;
this.customer = customer;
this.lastUpdateBy = lastUpdateBy;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne
@JoinColumn
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String getLastUpdateBy() {
return lastUpdateBy;
}
public void setLastUpdateBy(String lastUpdateBy) {
this.lastUpdateBy = lastUpdateBy;
}
}
@Entity(name = "User")
@Table(name = "`user`")
public static class User {
private Integer id;
private String username;
private Customer customer;
public User() {
}
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
public User(Integer id, String username, Customer customer) {
this.id = id;
this.username = username;
this.customer = customer;
}
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@NaturalId
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@ManyToOne(fetch = FetchType.LAZY)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
}

View File

@ -1,302 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.hql;
import static org.hamcrest.core.Is.is;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertThat;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.NaturalId;
import org.hibernate.testing.Skip;
import org.hibernate.testing.TestForIssue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* @author Jonathan Bregler
*/
public class EntityWithUnusualTableNameJoinTest extends EntityJoinTest {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[]{ FinancialRecord.class, User.class, Customer.class, Account.class };
}
@Override
@Before
public void prepare() {
createTestData();
}
@Override
@After
public void cleanup() {
deleteTestData();
}
@Test
@TestForIssue(jiraKey = "HHH-11816")
public void testInnerEntityJoinsWithVariable() {
doInHibernate( this::sessionFactory, session -> {
// this should get financial records which have a lastUpdateBy user set
List<Object[]> result = session.createQuery(
"select r.id, c.name, u.id, u.username " +
"from FinancialRecord r " +
" inner join r.customer c " +
" inner join User u on r.lastUpdateBy = u.username and u.username=:username" )
.setParameter( "username", "steve" ).list();
assertThat( Integer.valueOf( result.size() ), is( Integer.valueOf( 1 ) ) );
Object[] steveAndAcme = result.get( 0 );
assertThat( steveAndAcme[0], is( Integer.valueOf( 1 ) ) );
assertThat( steveAndAcme[1], is( "Acme" ) );
assertThat( steveAndAcme[3], is( "steve" ) );
} );
}
@Test
@TestForIssue(jiraKey = "HHH-11816")
public void testInnerEntityJoinsWithVariableSingleQuoted() {
doInHibernate( this::sessionFactory, session -> {
// this should get financial records which have a lastUpdateBy user set
List<Object[]> result = session.createQuery(
"select r.id, c.name, a.id, a.accountname, r.lastUpdateBy " +
"from FinancialRecord r " +
" inner join r.customer c " +
" inner join Account a on a.customer = c and a.accountname!='test:account' and a.accountname=:accountname and r.lastUpdateBy != null" )
.setParameter( "accountname", "DEBIT" ).list();
assertThat( Integer.valueOf( result.size() ), is( Integer.valueOf( 1 ) ) );
Object[] steveAndAcmeAndDebit = result.get( 0 );
assertThat( steveAndAcmeAndDebit[0], is( Integer.valueOf( 1 ) ) );
assertThat( steveAndAcmeAndDebit[1], is( "Acme" ) );
assertThat( steveAndAcmeAndDebit[3], is( "DEBIT" ) );
assertThat( steveAndAcmeAndDebit[4], is( "steve" ) );
} );
}
@Override
@Skip(message = "The superclass test checks for the table name which is different in this test case and causes the test to fail", condition = Skip.AlwaysSkip.class)
public void testNoImpliedJoinGeneratedForEqualityComparison() {
}
private void createTestData() {
doInHibernate( this::sessionFactory, session -> {
final Customer customer = new Customer( Integer.valueOf( 1 ), "Acme" );
session.save( customer );
session.save( new User( Integer.valueOf( 1 ), "steve", customer ) );
session.save( new User( Integer.valueOf( 2 ), "jane" ) );
session.save( new FinancialRecord( Integer.valueOf( 1 ), customer, "steve" ) );
session.save( new FinancialRecord( Integer.valueOf( 2 ), customer, null ) );
session.save( new Account( Integer.valueOf( 1 ), "DEBIT", customer ) );
session.save( new Account( Integer.valueOf( 2 ), "CREDIT" ) );
} );
}
private void deleteTestData() {
doInHibernate( this::sessionFactory, session -> {
session.createQuery( "delete FinancialRecord" ).executeUpdate();
session.createQuery( "delete User" ).executeUpdate();
session.createQuery( "delete Account" ).executeUpdate();
session.createQuery( "delete Customer" ).executeUpdate();
} );
}
@Entity(name = "Customer")
@Table(name = "`my::customer`")
public static class Customer {
private Integer id;
private String name;
public Customer() {
}
public Customer(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "FinancialRecord")
@Table(name = "`financial?record`")
public static class FinancialRecord {
private Integer id;
private Customer customer;
private String lastUpdateBy;
public FinancialRecord() {
}
public FinancialRecord(Integer id, Customer customer, String lastUpdateBy) {
this.id = id;
this.customer = customer;
this.lastUpdateBy = lastUpdateBy;
}
@Id
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@ManyToOne
@JoinColumn
public Customer getCustomer() {
return this.customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String getLastUpdateBy() {
return this.lastUpdateBy;
}
public void setLastUpdateBy(String lastUpdateBy) {
this.lastUpdateBy = lastUpdateBy;
}
}
@Entity(name = "User")
@Table(name = "`my::user`")
public static class User {
private Integer id;
private String username;
private Customer customer;
public User() {
}
public User(Integer id, String username) {
this.id = id;
this.username = username;
}
public User(Integer id, String username, Customer customer) {
this.id = id;
this.username = username;
this.customer = customer;
}
@Id
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@NaturalId
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
@ManyToOne(fetch = FetchType.LAZY)
public Customer getCustomer() {
return this.customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
@Entity(name = "Account")
@Table(name = "`account`")
public static class Account {
private Integer id;
private String accountname;
private Customer customer;
public Account() {
}
public Account(Integer id, String accountname) {
this.id = id;
this.accountname = accountname;
}
public Account(Integer id, String accountname, Customer customer) {
this.id = id;
this.accountname = accountname;
this.customer = customer;
}
@Id
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@NaturalId
public String getAccountname() {
return this.accountname;
}
public void setAccountname(String accountname) {
this.accountname = accountname;
}
@ManyToOne(fetch = FetchType.LAZY)
public Customer getCustomer() {
return this.customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
}