Browse files

HHH-4459 Query with Composite Primary Key parameter crashes when query

cache is on
  • Loading branch information...
1 parent 199ee78 commit 58fa4c2eac2a4d556077d11250fa804d23bb9ddf brmeyer committed Oct 9, 2012
View
2 hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java
@@ -100,7 +100,7 @@ public Class getMappedClass() {
if ( component == BackrefPropertyAccessor.UNKNOWN ) {
return new Object[propertySpan];
}
- if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
+ else if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
return optimizer.getAccessOptimizer().getPropertyValues( component );
}
else {
View
10 hibernate-core/src/main/java/org/hibernate/type/ComponentType.java
@@ -425,7 +425,15 @@ public Object getPropertyValue(Object component, int i, EntityMode entityMode)
public Object[] getPropertyValues(Object component, EntityMode entityMode)
throws HibernateException {
- return componentTuplizer.getPropertyValues( component );
+ if ( component instanceof Object[] ) {
+ // A few calls to hashCode pass the property values already in an
+ // Object[] (ex: QueryKey hash codes for cached queries).
+ // It's easiest to just check for the condition here prior to
+ // trying reflection.
+ return ( Object[] ) component;
+ } else {
+ return componentTuplizer.getPropertyValues( component );
+ }
}
public void setPropertyValues(Object component, Object[] values, EntityMode entityMode)
View
49 hibernate-core/src/test/java/org/hibernate/test/querycache/CompositeKey.java
@@ -0,0 +1,49 @@
+package org.hibernate.test.querycache;
+
+import java.io.Serializable;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class CompositeKey implements Serializable {
+
+ private static final long serialVersionUID = 7950910288405475131L;
+
+ public int a;
+
+ public int b;
+
+ public CompositeKey() {
+ }
+
+ public CompositeKey(int a, int b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + a;
+ result = prime * result + b;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CompositeKey other = (CompositeKey) obj;
+ if (a != other.a)
+ return false;
+ if (b != other.b)
+ return false;
+ return true;
+ }
+
+}
View
19 hibernate-core/src/test/java/org/hibernate/test/querycache/EntityWithCompositeKey.java
@@ -0,0 +1,19 @@
+package org.hibernate.test.querycache;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+
+@Entity
+public class EntityWithCompositeKey {
+
+ @EmbeddedId
+ public CompositeKey pk;
+
+ public EntityWithCompositeKey() {
+ }
+
+ public EntityWithCompositeKey(CompositeKey pk) {
+ this.pk = pk;
+ }
+
+}
View
23 hibernate-core/src/test/java/org/hibernate/test/querycache/EntityWithStringCompositeKey.java
@@ -0,0 +1,23 @@
+package org.hibernate.test.querycache;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+@Entity
+@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
+public class EntityWithStringCompositeKey {
+
+ private StringCompositeKey pk;
+
+ @EmbeddedId
+ public StringCompositeKey getPk() {
+ return pk;
+ }
+
+ public void setPk(StringCompositeKey pk) {
+ this.pk = pk;
+ }
+}
View
72 hibernate-core/src/test/java/org/hibernate/test/querycache/QueryCacheTest.java
@@ -23,38 +23,54 @@
*/
package org.hibernate.test.querycache;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import org.junit.Test;
-
+import org.hibernate.Criteria;
import org.hibernate.Hibernate;
+import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
+import org.hibernate.criterion.Restrictions;
import org.hibernate.stat.EntityStatistics;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.transform.Transformers;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
/**
* @author Gavin King
+ * @author Brett Meyer
*/
public class QueryCacheTest extends BaseCoreFunctionalTestCase {
+
+ private static final CompositeKey PK = new CompositeKey(1, 2);
+
@Override
public String[] getMappings() {
return new String[] { "querycache/Item.hbm.xml" };
}
@Override
+ protected Class[] getAnnotatedClasses() {
+ return new Class[] {
+ CompositeKey.class,
+ EntityWithCompositeKey.class,
+ StringCompositeKey.class,
+ EntityWithStringCompositeKey.class
+ };
+ }
+
+ @Override
public void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( Environment.USE_QUERY_CACHE, "true" );
@@ -431,6 +447,52 @@ public void testProjectionCache() throws Exception {
assertEquals( qs.getExecutionCount(), 3 );
assertEquals( es.getFetchCount(), 0 ); //check that it was being cached
}
+
+ @Test
+ @TestForIssue( jiraKey = "HHH-4459" )
+ public void testGetByCompositeId() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.persist( new EntityWithCompositeKey( PK ) );
+ Query query = s.createQuery( "FROM EntityWithCompositeKey e WHERE e.pk = :pk" );
+ query.setCacheable( true );
+ query.setParameter( "pk", PK );
+ assertEquals(1, query.list().size( ));
+ s.getTransaction().rollback();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ EntityWithStringCompositeKey entity = new EntityWithStringCompositeKey();
+ StringCompositeKey key = new StringCompositeKey();
+ key.setAnalog( "foo1" );
+ key.setDevice( "foo2" );
+ key.setDeviceType( "foo3" );
+ key.setSubstation( "foo4" );
+ entity.setPk( key );
+ s.persist( entity );
+ Criteria c = s.createCriteria(
+ EntityWithStringCompositeKey.class ).add( Restrictions.eq(
+ "pk", key ) );
+ c.setCacheable( true );
+ assertEquals( 1, c.list().size() );
+ s.getTransaction().rollback();
+ s.close();
+ }
+
+// @Test
+// public void testGetByCompositeIdNoCache() {
+// Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e.pk = :pk");
+// query.setParameter("pk", PK);
+// assertEquals(1, query.getResultList().size());
+// }
+//
+// @Test
+// public void testGetByEntityIself() {
+// Query query = em.createQuery("FROM EntityWithCompositeKey e WHERE e = :ent");
+// query.setParameter("ent", new EntityWithCompositeKey(PK));
+// assertEquals(1, query.getResultList().size());
+// }
}
View
51 hibernate-core/src/test/java/org/hibernate/test/querycache/StringCompositeKey.java
@@ -0,0 +1,51 @@
+package org.hibernate.test.querycache;
+
+import java.io.Serializable;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class StringCompositeKey implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private String substation;
+
+ private String deviceType;
+
+ private String device;
+
+ public String getSubstation() {
+ return substation;
+ }
+
+ public void setSubstation(String substation) {
+ this.substation = substation;
+ }
+
+ public String getDeviceType() {
+ return deviceType;
+ }
+
+ public void setDeviceType(String deviceType) {
+ this.deviceType = deviceType;
+ }
+
+ public String getDevice() {
+ return device;
+ }
+
+ public void setDevice(String device) {
+ this.device = device;
+ }
+
+ public String getAnalog() {
+ return analog;
+ }
+
+ public void setAnalog(String analog) {
+ this.analog = analog;
+ }
+
+ private String analog;
+}

0 comments on commit 58fa4c2

Please sign in to comment.