diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java index e01ff88ea40e..85d45057013b 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/exec/DeleteExecutor.java @@ -11,8 +11,7 @@ import java.util.List; import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.dialect.Dialect; +import org.hibernate.QueryException; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -120,7 +119,7 @@ public DeleteExecutor(HqlSqlWalker walker) { } columnNames = columns.toArray( new String[0] ); } - catch (MappingException e) { + catch (QueryException e) { // Property not found, due to IdClasses are not properly handled in metamodel HHH-12996 columnNames = persister.getIdentifierColumnNames(); } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractNullnessCheckNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractNullnessCheckNode.java index 7f9d81cd05ea..99f2fad72d90 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractNullnessCheckNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractNullnessCheckNode.java @@ -6,10 +6,8 @@ */ package org.hibernate.hql.internal.ast.tree; -import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; -import org.hibernate.internal.util.StringHelper; import org.hibernate.type.Type; import antlr.collections.AST; @@ -102,40 +100,4 @@ private static Type extractDataType(Node operand) { return null; } - private static String[] extractMutationTexts(Node operand, int count) { - if ( operand instanceof ParameterNode ) { - String[] rtn = new String[count]; - for ( int i = 0; i < count; i++ ) { - rtn[i] = "?"; - } - return rtn; - } - else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) { - final String[] rtn = new String[ operand.getNumberOfChildren() ]; - AST node = operand.getFirstChild(); - int x = 0; - while ( node != null ) { - rtn[ x++ ] = node.getText(); - node = node.getNextSibling(); - } - return rtn; - } - else if ( operand instanceof SqlNode ) { - String nodeText = operand.getText(); - if ( nodeText.startsWith( "(" ) ) { - nodeText = nodeText.substring( 1 ); - } - if ( nodeText.endsWith( ")" ) ) { - nodeText = nodeText.substring( 0, nodeText.length() - 1 ); - } - String[] splits = StringHelper.split( ", ", nodeText ); - if ( count != splits.length ) { - throw new HibernateException( "SqlNode's text did not reference expected number of columns" ); - } - return splits; - } - else { - throw new HibernateException( "don't know how to extract row value elements from node : " + operand ); - } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractSelectExpression.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractSelectExpression.java index ec7f54a66a4b..27965ddc3745 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractSelectExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/AbstractSelectExpression.java @@ -6,9 +6,15 @@ */ package org.hibernate.hql.internal.ast.tree; +import java.util.Arrays; + +import org.hibernate.HibernateException; +import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; +import org.hibernate.internal.util.StringHelper; import org.hibernate.type.Type; import antlr.SemanticException; +import antlr.collections.AST; /** * Partial implementation of SelectExpression for all the nodes that aren't constructors. @@ -55,4 +61,40 @@ public void setScalarColumn(int i) throws SemanticException { public int getScalarColumnIndex() { return scalarColumnIndex; } + + protected static String[] extractMutationTexts(Node operand, int count) { + if ( operand instanceof ParameterNode ) { + String[] rtn = new String[count]; + Arrays.fill( rtn, "?" ); + return rtn; + } + else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) { + String[] rtn = new String[operand.getNumberOfChildren()]; + int x = 0; + AST node = operand.getFirstChild(); + while ( node != null ) { + rtn[x++] = node.getText(); + node = node.getNextSibling(); + } + return rtn; + } + else if ( operand instanceof SqlNode ) { + String nodeText = operand.getText(); + if ( nodeText.startsWith( "(" ) ) { + nodeText = nodeText.substring( 1 ); + } + if ( nodeText.endsWith( ")" ) ) { + nodeText = nodeText.substring( 0, nodeText.length() - 1 ); + } + String[] splits = StringHelper.split( ",", nodeText ); + if ( count != splits.length ) { + throw new HibernateException( "SqlNode's text did not reference expected number of columns" ); + } + return splits; + } + else { + throw new HibernateException( "dont know how to extract row value elements from node : " + operand ); + } + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java index bbe94719c344..e273bb20e43f 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/BinaryLogicOperatorNode.java @@ -6,16 +6,12 @@ */ package org.hibernate.hql.internal.ast.tree; -import java.util.Arrays; - -import org.hibernate.HibernateException; import org.hibernate.TypeMismatchException; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; import org.hibernate.hql.internal.ast.QuerySyntaxException; import org.hibernate.hql.internal.ast.util.ColumnHelper; -import org.hibernate.internal.util.StringHelper; import org.hibernate.param.ParameterSpecification; import org.hibernate.type.OneToOneType; import org.hibernate.type.StandardBasicTypes; @@ -239,41 +235,6 @@ private static void copyReferencedTables(Node from, SqlFragment to) { } } - protected static String[] extractMutationTexts(Node operand, int count) { - if ( operand instanceof ParameterNode ) { - String[] rtn = new String[count]; - Arrays.fill( rtn, "?" ); - return rtn; - } - else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) { - String[] rtn = new String[operand.getNumberOfChildren()]; - int x = 0; - AST node = operand.getFirstChild(); - while ( node != null ) { - rtn[x++] = node.getText(); - node = node.getNextSibling(); - } - return rtn; - } - else if ( operand instanceof SqlNode ) { - String nodeText = operand.getText(); - if ( nodeText.startsWith( "(" ) ) { - nodeText = nodeText.substring( 1 ); - } - if ( nodeText.endsWith( ")" ) ) { - nodeText = nodeText.substring( 0, nodeText.length() - 1 ); - } - String[] splits = StringHelper.split( ", ", nodeText ); - if ( count != splits.length ) { - throw new HibernateException( "SqlNode's text did not reference expected number of columns" ); - } - return splits; - } - else { - throw new HibernateException( "dont know how to extract row value elements from node : " + operand ); - } - } - protected Type extractDataType(Node operand) { Type type = null; if ( operand instanceof SqlNode ) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 9c5ba874c7cd..96ed75e1221b 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -637,7 +637,7 @@ public SqlValueReference[] map(String reference) { formulaTemplates = elementFormulaTemplates; } else { - columnNames = elementPropertyMapping.toColumns( reference ); + columnNames = columnNames( reference ); formulaTemplates = formulaTemplates( reference, columnNames.length ); } @@ -670,6 +670,20 @@ public String getColumnName() { } } + private String[] columnNames(String reference) { + if ( elementPersister == null ) { + return elementPropertyMapping.toColumns( reference ); + } + + final Integer propertyIndex = elementPersister.getEntityMetamodel().getPropertyIndexOrNull( reference ); + if ( propertyIndex != null ) { + return ( (Queryable) elementPersister ).getSubclassPropertyColumnNameClosure()[propertyIndex]; + } + else { + return elementPropertyMapping.toColumns( reference ); + } + } + private String[] formulaTemplates(String reference, int expectedSize) { try { final int propertyIndex = elementPersister.getEntityMetamodel().getPropertyIndex( reference ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index e447b10ed292..f63749040d60 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -2032,7 +2032,7 @@ public String[] toColumns(String alias, String propertyName) throws QueryExcepti */ @Override public String[] toColumns(String propertyName) throws QueryException { - return propertyMapping.getColumnNames( propertyName ); + return propertyMapping.toColumns( propertyName ); } /** @@ -2224,7 +2224,8 @@ protected Type[] getSubclassPropertyTypeClosure() { return subclassPropertyTypeClosure; } - protected String[][] getSubclassPropertyColumnNameClosure() { + @Override + public String[][] getSubclassPropertyColumnNameClosure() { return subclassPropertyColumnNameClosure; } @@ -2820,17 +2821,36 @@ else if ( isAllOrDirtyOptLocking() && oldFields != null ) { String[] propertyColumnNames = getPropertyColumnNames( i ); String[] propertyColumnWriters = getPropertyColumnWriters( i ); boolean[] propertyNullness = types[i].toColumnNullness( oldFields[i], getFactory() ); + String[] propertyColumnFormulaTemplates = this.propertyColumnFormulaTemplates[i]; for ( int k = 0; k < propertyNullness.length; k++ ) { - if ( propertyNullness[k] ) { - update.addWhereColumn( propertyColumnNames[k], "=" + propertyColumnWriters[k] ); + final String propertyColumnFormulaTemplate = propertyColumnFormulaTemplates[k]; + final String propertyColumnName = propertyColumnNames[k]; + if ( propertyColumnName == null && propertyColumnFormulaTemplate != null ) { + final String formula = StringHelper.replace( + propertyColumnFormulaTemplate, + Template.TEMPLATE + ".", + "" + ); + if ( propertyNullness[k] ) { + final String propertyColumnWriter = propertyColumnWriters[k]; + update.addWhereColumn( + formula, + "=" + ( propertyColumnWriter == null ? "?" : propertyColumnWriter ) + ); + } + else { + update.addWhereColumn( formula, " is null" ); + } + } + else if ( propertyNullness[k] ) { + update.addWhereColumn( propertyColumnName, "=" + propertyColumnWriters[k] ); } else { - update.addWhereColumn( propertyColumnNames[k], " is null" ); + update.addWhereColumn( propertyColumnName, " is null" ); } } } } - } if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java index fd37e9955bdb..a4f4df63bae6 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractPropertyMapping.java @@ -115,7 +115,7 @@ public String[] toColumns(String propertyName) throws QueryException { String[] result = new String[columns.length]; for ( int i = 0; i < columns.length; i++ ) { if ( columnReaders[i] == null ) { - result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, "" ); + result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE + ".", "" ); } else { result[i] = columnReaders[i]; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java index bcd7e7f9feb7..02910cc32b46 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/Queryable.java @@ -138,6 +138,8 @@ public interface Queryable extends Loadable, PropertyMapping, Joinable { String[][] getSubclassPropertyFormulaTemplateClosure(); + String[][] getSubclassPropertyColumnNameClosure(); + public static class Declarer { public static final Declarer CLASS = new Declarer( "class" ); public static final Declarer SUBCLASS = new Declarer( "subclass" ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/AssociationFormulaTest.java b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/AssociationFormulaTest.java new file mode 100644 index 000000000000..71652bcfea6d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/AssociationFormulaTest.java @@ -0,0 +1,249 @@ +/* + * 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 . + */ +package org.hibernate.test.formulajoin; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@TestForIssue(jiraKey = "HHH-9952") +public class AssociationFormulaTest extends BaseCoreFunctionalTestCase { + + public AssociationFormulaTest() { + super(); + } + + @Override + protected boolean rebuildSessionFactoryOnError() { + return true; + } + + @Override + public String[] getMappings() { + return new String[] { "formulajoin/Mapping.hbm.xml" }; + } + + @Before + public void fillDb() { + + Entity entity = new Entity(); + entity.setId( new Id( "test", 1 ) ); + entity.setOther( new OtherEntity() ); + entity.getOther().setId( new Id( "test", 2 ) ); + + Entity otherNull = new Entity(); + otherNull.setId( new Id( "null", 3 ) ); + + inTransaction( + session -> { + session.merge( entity ); + session.merge( otherNull ); + } + ); + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createQuery( "delete from Entity" ).executeUpdate(); + session.createQuery( "delete from OtherEntity" ).executeUpdate(); + } + ); + } + + @Test + public void testJoin() { + + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "select e from Entity e inner join e.other o" ) + .uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 1, loaded.getId().getId() ); + assertEquals( 2, loaded.getOther().getId().getId() ); + assertFalse( Hibernate.isInitialized( loaded.getOther() ) ); + Hibernate.initialize( loaded.getOther() ); + } + ); + } + + @Test + public void testJoinFetch() { + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "select e from Entity e inner join fetch e.other o" ) + .uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 1, loaded.getId().getId() ); + assertTrue( Hibernate.isInitialized( loaded.getOther() ) ); + assertEquals( 2, loaded.getOther().getId().getId() ); + } + ); + } + + @Test + public void testSelectFullNull() { + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "from Entity e where e.other is null" ) + .uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 3, loaded.getId().getId() ); + assertNull( loaded.getOther() ); + + } + ); + } + + @Test + public void testSelectPartialNull() { + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "from Entity e where e.other.id.id is null" ) + .uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 3, loaded.getId().getId() ); + assertNull( loaded.getOther() ); + } + ); + } + + @Test + public void testSelectFull() { + inTransaction( + session -> { + OtherEntity other = new OtherEntity(); + other.setId( new Id( "test", 2 ) ); + Entity loaded = (Entity) session.createQuery( "from Entity e where e.other = :other" ) + .setParameter( "other", other ) + .uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 1, loaded.getId().getId() ); + assertNotNull( loaded.getOther() ); + assertEquals( 2, loaded.getOther().getId().getId() ); + } + ); + } + + @Test + public void testUpdateFromExisting() { + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 1" ).uniqueResult(); + assertNotNull( "loaded", loaded ); + assertNotNull( loaded.getOther() ); + loaded.setOther( new OtherEntity() ); + loaded.getOther().setId( new Id( "test", 3 ) ); + } + ); + } + + @Test + public void testUpdateFromNull() { + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 3" ).uniqueResult(); + assertNotNull( "loaded", loaded ); + assertNull( loaded.getOther() ); + loaded.setOther( new OtherEntity() ); + loaded.getOther().setId( new Id( "test", 3 ) ); + } + ); + } + + @Test + @Ignore("multi-column updates don't work!") + public void testUpdateHql() { + inTransaction( + session -> { + OtherEntity other = new OtherEntity(); + other.setId( new Id( "null", 4 ) ); + assertEquals( + "execute", + 1, + session.createQuery( "update Entity e set e.other = :other where e.id.id = 3" ) + .setParameter( "other", other ) + .executeUpdate() + ); + Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 3" ).uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 4, loaded.getOther().getId().getId() ); + } + ); + } + + @Test + @Ignore("multi-column updates don't work!") + public void testUpdateHqlNull() { + inTransaction( + session -> { + assertEquals( + "execute", + 1, + session.createQuery( "update Entity e set e.other = null where e.id.id = 1" ) + .executeUpdate() + ); + Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 1" ).uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 4, loaded.getOther().getId().getId() ); + } + ); + } + + @Test + public void testDeleteHql() { + inTransaction( + session -> { + OtherEntity other = new OtherEntity(); + other.setId( new Id( "test", 2 ) ); + assertEquals( + "execute", + 1, + session.createQuery( "delete Entity e where e.other = :other" ) + .setParameter( "other", other ) + .executeUpdate() + ); + Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 1" ).uniqueResult(); + assertNull( "loaded", loaded ); + } + ); + } + + @Test + public void testPersist() { + inTransaction( + session -> { + Entity entity = new Entity(); + entity.setId( new Id( "new", 5 ) ); + entity.setOther( new OtherEntity() ); + entity.getOther().setId( new Id( "new", 6 ) ); + session.persist( entity ); + } + ); + + inTransaction( + session -> { + Entity loaded = (Entity) session.createQuery( "from Entity e where e.id.id = 5" ).uniqueResult(); + assertNotNull( "loaded", loaded ); + assertEquals( 6, loaded.getOther().getId().getId() ); + } + ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Entity.java b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Entity.java new file mode 100644 index 000000000000..e80f16a569f5 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Entity.java @@ -0,0 +1,39 @@ +/* + * 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 . + */ +package org.hibernate.test.formulajoin; + +public class Entity { + private Id id; + + private String name; + + private OtherEntity other; + + public Id getId() { + return id; + } + + public void setId(Id id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public OtherEntity getOther() { + return other; + } + + public void setOther(OtherEntity partial) { + this.other = partial; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Id.java b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Id.java new file mode 100644 index 000000000000..33a150f7c286 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Id.java @@ -0,0 +1,76 @@ +/* + * 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 . + */ +package org.hibernate.test.formulajoin; + +import java.io.Serializable; + +public class Id implements Serializable { + private String mandant; + + private int id; + + public Id() { + super(); + } + + public Id(String mandant, int id) { + super(); + this.mandant = mandant; + this.id = id; + } + + public String getMandant() { + return mandant; + } + + public void setMandant(String mandant) { + this.mandant = mandant; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ( ( mandant == null ) ? 0 : mandant.hashCode() ); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + Id other = (Id) obj; + if ( id != other.id ) { + return false; + } + if ( mandant == null ) { + if ( other.mandant != null ) { + return false; + } + } + else if ( !mandant.equals( other.mandant ) ) { + return false; + } + return true; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Mapping.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Mapping.hbm.xml new file mode 100644 index 000000000000..a0da44e88b3b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/Mapping.hbm.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + case when other is null then null else mandant end + + + + + + + + + + + + \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/formulajoin/OtherEntity.java b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/OtherEntity.java new file mode 100644 index 000000000000..ef38b7845792 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/formulajoin/OtherEntity.java @@ -0,0 +1,30 @@ +/* + * 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 . + */ +package org.hibernate.test.formulajoin; + +public class OtherEntity { + + private Id id; + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Id getId() { + return id; + } + + public void setId(Id id) { + this.id = id; + } +}