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

cache is on
This commit is contained in:
brmeyer 2012-10-08 21:51:56 -04:00
parent 95bc0194ec
commit b130e7e430
7 changed files with 219 additions and 7 deletions

View File

@ -100,7 +100,7 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
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 File

@ -424,7 +424,15 @@ public class ComponentType extends AbstractType implements CompositeType {
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 File

@ -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 File

@ -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 File

@ -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 File

@ -23,17 +23,21 @@
*/
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;
@ -41,19 +45,31 @@ 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 );
@ -431,6 +447,52 @@ public class QueryCacheTest extends BaseCoreFunctionalTestCase {
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 File

@ -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;
}