diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IntoClause.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IntoClause.java index 6219d124c7..8c62b9acd8 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IntoClause.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/IntoClause.java @@ -26,11 +26,16 @@ package org.hibernate.hql.internal.ast.tree; import java.sql.Types; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; + import org.hibernate.QueryException; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.persister.entity.Queryable; +import org.hibernate.type.ComponentType; import org.hibernate.type.Type; + import antlr.collections.AST; /** @@ -49,6 +54,8 @@ public class IntoClause extends HqlSqlWalkerNode implements DisplayableNode { private boolean explicitIdInsertion; private boolean explicitVersionInsertion; + private Set componentIds; + private List explicitComponentIds; public void initialize(Queryable persister) { if ( persister.isAbstract() ) { @@ -165,10 +172,27 @@ public class IntoClause extends HqlSqlWalkerNode implements DisplayableNode { throw new QueryException( "INSERT statements cannot refer to superclass/joined properties [" + name + "]" ); } - if ( name.equals( persister.getIdentifierPropertyName() ) ) { - explicitIdInsertion = true; + if ( !explicitIdInsertion ) { + if ( persister.getIdentifierType() instanceof ComponentType ) { + if ( componentIds == null ) { + String[] propertyNames = ( (ComponentType) persister.getIdentifierType() ).getPropertyNames(); + componentIds = new HashSet(); + for ( int i = 0; i < propertyNames.length; i++ ) { + componentIds.add( propertyNames[i] ); + } + } + if ( componentIds.contains(name) ) { + if ( explicitComponentIds == null ) { + explicitComponentIds = new ArrayList( componentIds.size() ); + } + explicitComponentIds.add( name ); + explicitIdInsertion = explicitComponentIds.size() == componentIds.size(); + } + } else if ( name.equals( persister.getIdentifierPropertyName() ) ) { + explicitIdInsertion = true; + } } - + if ( persister.isVersioned() ) { if ( name.equals( persister.getPropertyNames()[ persister.getVersionProperty() ] ) ) { explicitVersionInsertion = true; diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/hql/BulkManipulationTest.java b/hibernate-core/src/matrix/java/org/hibernate/test/hql/BulkManipulationTest.java index 40ff05216c..79eb12b574 100644 --- a/hibernate-core/src/matrix/java/org/hibernate/test/hql/BulkManipulationTest.java +++ b/hibernate-core/src/matrix/java/org/hibernate/test/hql/BulkManipulationTest.java @@ -65,7 +65,8 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { "legacy/Multi.hbm.xml", "hql/EntityWithCrazyCompositeKey.hbm.xml", "hql/SimpleEntityWithAssociation.hbm.xml", - "hql/BooleanLiteralEntity.hbm.xml" + "hql/BooleanLiteralEntity.hbm.xml", + "hql/CompositeIdEntity.hbm.xml" }; } @@ -496,6 +497,18 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase { s.close(); } + @Test + public void testInsertWithAssignedCompositeId() { + // this just checks that the query parser detects that we are explicitly inserting a composite id + Session s = openSession(); + s.beginTransaction(); + // intentionally reversing the order of the composite id properties to make sure that is supported too + s.createQuery( "insert into CompositeIdEntity (key2, someProperty, key1) select a.key2, 'COPY', a.key1 from CompositeIdEntity a" ).executeUpdate(); + s.createQuery( "delete from CompositeIdEntity" ).executeUpdate(); + s.getTransaction().commit(); + s.close(); + } + @Test public void testInsertWithSelectListUsingJoins() { // this is just checking parsing and syntax... diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/hql/CompositeIdEntity.hbm.xml b/hibernate-core/src/matrix/java/org/hibernate/test/hql/CompositeIdEntity.hbm.xml new file mode 100644 index 0000000000..0684164c14 --- /dev/null +++ b/hibernate-core/src/matrix/java/org/hibernate/test/hql/CompositeIdEntity.hbm.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/hql/CompositeIdEntity.java b/hibernate-core/src/matrix/java/org/hibernate/test/hql/CompositeIdEntity.java new file mode 100644 index 0000000000..4f526e61c8 --- /dev/null +++ b/hibernate-core/src/matrix/java/org/hibernate/test/hql/CompositeIdEntity.java @@ -0,0 +1,60 @@ +package org.hibernate.test.hql; + +import java.io.Serializable; + +public class CompositeIdEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long key1; + private String key2; + private String someProperty; + + public Long getKey1() { + return key1; + } + + public void setKey1( Long key1 ) { + this.key1 = key1; + } + + public String getKey2() { + return key2; + } + + public void setKey2( String key2 ) { + this.key2 = key2; + } + + public String getSomeProperty() { + return someProperty; + } + + public void setSomeProperty( String someProperty ) { + this.someProperty = someProperty; + } + + @Override + public int hashCode() { + // not really needed, thus the dumb implementation. + return 42; + } + + @Override + public boolean equals( Object obj ) { + if (this == obj) { + return true; + } + if ( !( obj instanceof CompositeIdEntity ) ) { + return false; + } + CompositeIdEntity other = ( CompositeIdEntity ) obj; + if ( key1 == null ? other.key1 != null : !key1.equals( other.key1 ) ) { + return false; + } + if ( key2 == null ? other.key2 != null : !key2.equals( other.key2 ) ) { + return false; + } + return true; + } +}