[hibernate-commits] Hibernate SVN: r18444 - in core/trunk/entitymanager/src: main/java/org/hibernate/ejb/criteria and 2 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Thu Jan 7 15:41:55 EST 2010
Author: steve.ebersole at jboss.com
Date: 2010-01-07 15:41:54 -0500 (Thu, 07 Jan 2010)
New Revision: 18444
Removed:
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/Customer.java
Modified:
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/TupleCriteriaTest.java
core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/Customer.java
Log:
HHH-4724 - query.multiselect() on a CriteriaQuery<Tuple> returns List<Object[]> instead of List<Tuple>
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-01-07 20:34:59 UTC (rev 18443)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java 2010-01-07 20:41:54 UTC (rev 18444)
@@ -41,12 +41,15 @@
import javax.persistence.PessimisticLockException;
import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;
+import javax.persistence.Tuple;
+import javax.persistence.TupleElement;
import javax.persistence.TypedQuery;
import javax.persistence.PessimisticLockScope;
import javax.persistence.LockTimeoutException;
import javax.persistence.QueryTimeoutException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.Selection;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.transaction.Status;
@@ -60,6 +63,7 @@
import org.hibernate.*;
import org.hibernate.cfg.Environment;
import org.hibernate.ejb.criteria.ValueHandlerFactory;
+import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl;
import org.hibernate.ejb.transaction.JoinableCMTTransaction;
import org.hibernate.ejb.util.ConfigurationHelper;
import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
@@ -68,6 +72,7 @@
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.transaction.TransactionFactory;
import org.hibernate.transform.BasicTransformerAdapter;
+import org.hibernate.transform.ResultTransformer;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.JTAHelper;
@@ -145,15 +150,24 @@
public <T> TypedQuery<T> createQuery(
String jpaqlString,
Class<T> resultClass,
+ Selection selection,
Options options) {
try {
org.hibernate.Query hqlQuery = getSession().createQuery( jpaqlString );
- if ( options.getValueHandlers() != null ) {
- hqlQuery.setResultTransformer( new ValueConversionResultTransformer( options.getValueHandlers() ) );
- }
- else {
+
+ if ( options.getValueHandlers() == null ) {
options.getResultMetadataValidator().validate( hqlQuery.getReturnTypes() );
}
+
+ // determine if we need a result transformer
+ List tupleElements = Tuple.class.equals( resultClass )
+ ? ( (CompoundSelectionImpl<Tuple>) selection ).getCompoundSelectionItems()
+ : null;
+ if ( options.getValueHandlers() != null || tupleElements != null ) {
+ hqlQuery.setResultTransformer(
+ new CriteriaQueryTransformer( options.getValueHandlers(), tupleElements )
+ );
+ }
return new QueryImpl<T>( hqlQuery, this, options.getNamedParameterExplicitTypes() );
}
catch ( HibernateException he ) {
@@ -161,24 +175,109 @@
}
}
- private static class ValueConversionResultTransformer extends BasicTransformerAdapter {
- private List<ValueHandlerFactory.ValueHandler> valueHandlers;
+ private static class CriteriaQueryTransformer extends BasicTransformerAdapter {
+ private final List<ValueHandlerFactory.ValueHandler> valueHandlers;
+ private final List tupleElements;
- private ValueConversionResultTransformer(List<ValueHandlerFactory.ValueHandler> valueHandlers) {
+ private CriteriaQueryTransformer(List<ValueHandlerFactory.ValueHandler> valueHandlers, List tupleElements) {
+ // todo : should these 2 sizes match *always*?
this.valueHandlers = valueHandlers;
+ this.tupleElements = tupleElements;
}
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
- Object[] result = new Object[ tuple.length ];
- for ( int i = 0; i < tuple.length; i++ ) {
- ValueHandlerFactory.ValueHandler valueHandler = valueHandlers.get( i );
- result[i] = valueHandler == null
- ? tuple[i]
- : valueHandler.convert( tuple[i] );
+ final Object[] valueHandlerResult;
+ if ( valueHandlers == null ) {
+ valueHandlerResult = tuple;
}
- return result.length == 1 ? result[0] : result;
+ else {
+ valueHandlerResult = new Object[ tuple.length ];
+ for ( int i = 0; i < tuple.length; i++ ) {
+ ValueHandlerFactory.ValueHandler valueHandler = valueHandlers.get( i );
+ valueHandlerResult[i] = valueHandler == null
+ ? tuple[i]
+ : valueHandler.convert( tuple[i] );
+ }
+ }
+
+ return tupleElements == null
+ ? valueHandlerResult.length == 1 ? valueHandlerResult[0] : valueHandlerResult
+ : new TupleImpl( tuple );
+
}
+
+ private class TupleImpl implements Tuple {
+ private final Object[] tuples;
+
+ private TupleImpl(Object[] tuples) {
+ if ( tuples.length != tupleElements.size() ) {
+ throw new IllegalArgumentException(
+ "Size mismatch between tuple result [" + tuples.length
+ + "] and expected tuple elements [" + tupleElements.size() + "]"
+ );
+ }
+ this.tuples = tuples;
+ }
+
+ public <X> X get(TupleElement<X> tupleElement) {
+ int index = tupleElements.indexOf( tupleElement );
+ if ( index < 0 ) {
+ throw new IllegalArgumentException( "Requested tuple element did not correspond to element in the result tuple" );
+ }
+ // index should be "in range" by nature of size check in ctor
+ return (X) tuples[index];
+ }
+
+ public Object get(String alias) {
+ int index = -1;
+ if ( alias != null ) {
+ alias = alias.trim();
+ if ( alias.length() > 0 ) {
+ int i = 0;
+ for ( TupleElement selection : (List<TupleElement>) tupleElements ) {
+ if ( alias.equals( selection.getAlias() ) ) {
+ index = i;
+ break;
+ }
+ i++;
+ }
+ }
+ }
+ if ( index < 0 ) {
+ throw new IllegalArgumentException(
+ "Given alias [" + alias + "] did not correspond to an element in the result tuple"
+ );
+ }
+ // index should be "in range" by nature of size check in ctor
+ return tuples[index];
+ }
+
+ public <X> X get(String alias, Class<X> type) {
+ return (X) get( alias );
+ }
+
+ public Object get(int i) {
+ if ( i >= tuples.length ) {
+ throw new IllegalArgumentException(
+ "Given index [" + i + "] was outside the range of result tuple size [" + tuples.length + "] "
+ );
+ }
+ return tuples[i];
+ }
+
+ public <X> X get(int i, Class<X> type) {
+ return (X) get( i );
+ }
+
+ public Object[] toArray() {
+ return tuples;
+ }
+
+ public List<TupleElement<?>> getElements() {
+ return (List<TupleElement<?>>) tupleElements;
+ }
+ }
}
private CriteriaQueryCompiler criteriaQueryCompiler;
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2010-01-07 20:34:59 UTC (rev 18443)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/HibernateEntityManagerImplementor.java 2010-01-07 20:41:54 UTC (rev 18444)
@@ -26,6 +26,7 @@
import javax.persistence.PersistenceException;
import javax.persistence.LockModeType;
import javax.persistence.TypedQuery;
+import javax.persistence.criteria.Selection;
import org.hibernate.HibernateException;
import org.hibernate.StaleStateException;
@@ -141,9 +142,10 @@
*
* @param jpaqlString The criteria query rendered as a JPA QL string
* @param resultClass The result type (the type expected in the result list)
+ * @param selection The selection(s)
* @param options The options to use to build the query.
* @param <T> The query type
* @return The typed query
*/
- public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass, Options options);
+ public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass, Selection selection, Options options);
}
Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java 2010-01-07 20:34:59 UTC (rev 18443)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaQueryCompiler.java 2010-01-07 20:41:54 UTC (rev 18444)
@@ -154,6 +154,7 @@
TypedQuery<T> jpaqlQuery = entityManager.createQuery(
renderedCriteriaQuery.getQueryString(),
criteriaQuery.getResultType(),
+ criteriaQuery.getSelection(),
new HibernateEntityManagerImplementor.Options() {
public List<ValueHandlerFactory.ValueHandler> getValueHandlers() {
return renderedCriteriaQuery.getValueHandlers();
Deleted: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/Customer.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/Customer.java 2010-01-07 20:34:59 UTC (rev 18443)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/Customer.java 2010-01-07 20:41:54 UTC (rev 18444)
@@ -1,43 +0,0 @@
-package org.hibernate.ejb.criteria.tuple;
-
-import javax.persistence.Table;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.GeneratedValue;
-
-/**
- * @author Emmanuel Bernard
- */
- at Entity
- at Table(name="tup_cust")
-public class Customer {
- private Long id;
- private String name;
- private Integer age;
-
- @Id
- @GeneratedValue
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-}
Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/TupleCriteriaTest.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/TupleCriteriaTest.java 2010-01-07 20:34:59 UTC (rev 18443)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/tuple/TupleCriteriaTest.java 2010-01-07 20:41:54 UTC (rev 18444)
@@ -3,72 +3,92 @@
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Tuple;
-import javax.persistence.TupleElement;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
-import org.hibernate.ejb.test.TestCase;
+import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest;
+import org.hibernate.ejb.metamodel.Customer;
+import org.hibernate.ejb.metamodel.Customer_;
/**
* @author Emmanuel Bernard
*/
-public class TupleCriteriaTest extends TestCase {
+public class TupleCriteriaTest extends AbstractMetamodelSpecificTest {
public void testArray() {
EntityManager em = factory.createEntityManager();
+ em.getTransaction().begin();
Customer c1 = new Customer();
+ c1.setId( "c1" );
c1.setAge( 18 );
c1.setName( "Bob" );
- em.getTransaction().begin();
em.persist( c1 );
- em.flush();
+ em.getTransaction().commit();
+ em.close();
+ em = factory.createEntityManager();
+ em.getTransaction().begin();
final CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> q = cb.createQuery(Object[].class);
Root<Customer> c = q.from(Customer.class);
q.select( cb.array( c.get(Customer_.name), c.get(Customer_.age) ) );
List<Object[]> result = em.createQuery(q).getResultList();
-
assertEquals( 1, result.size() );
assertEquals( c1.getName(), result.get( 0 )[0] );
assertEquals( c1.getAge(), result.get( 0 )[1] );
+ em.getTransaction().commit();
+ em.close();
- em.getTransaction().rollback();
+ em = factory.createEntityManager();
+ em.getTransaction().begin();
+ em.createQuery( "delete Customer" ).executeUpdate();
+ em.getTransaction().commit();
em.close();
}
public void testTuple() {
EntityManager em = factory.createEntityManager();
+
+ em.getTransaction().begin();
Customer c1 = new Customer();
+ c1.setId( "c1" );
c1.setAge( 18 );
c1.setName( "Bob" );
- em.getTransaction().begin();
em.persist( c1 );
- em.flush();
+ em.getTransaction().commit();
+ em.close();
- final CriteriaBuilder cb = em.getCriteriaBuilder();
+ em = factory.createEntityManager();
+ em.getTransaction().begin();
+ final CriteriaBuilder builder = em.getCriteriaBuilder();
+ CriteriaQuery<Tuple> criteria = builder.createTupleQuery();
+ Root<Customer> customerRoot = criteria.from( Customer.class );
+ Path<String> namePath = customerRoot.get( Customer_.name );
+ Path<Integer> agePath = customerRoot.get( Customer_.age );
+ agePath.alias( "age" );
+ criteria.multiselect( namePath, agePath );
+ List<Tuple> results = em.createQuery( criteria ).getResultList();
+ assertEquals( 1, results.size() );
+ Object resultElement = results.get( 0 );
+ assertTrue( "Check result 'row' as Tuple", Tuple.class.isInstance( resultElement ) );
+ Tuple resultElementTuple = (Tuple) resultElement;
+ Object[] tupleArray = resultElementTuple.toArray();
+ assertEquals( 2, tupleArray.length );
+ assertEquals( tupleArray[0], resultElementTuple.get( 0 ) );
+ assertEquals( resultElementTuple.get( namePath ), resultElementTuple.get( 0 ) );
+ assertEquals( tupleArray[1], resultElementTuple.get( 1 ) );
+ assertEquals( resultElementTuple.get( agePath ), resultElementTuple.get( 1 ) );
+ assertEquals( resultElementTuple.get( agePath ), resultElementTuple.get( "age" ) );
+ em.getTransaction().commit();
+ em.close();
- CriteriaQuery<Tuple> q = cb.createTupleQuery();
- Root<Customer> c = q.from(Customer.class);
- Path<String> tname = c.get(Customer_.name);
- q.multiselect( tname, c.get(Customer_.age).alias("age") );
- List<Tuple> result = em.createQuery(q).getResultList();
-
- assertEquals( 1, result.size() );
- //FIXME uncomment when HHH-4724 is fixed
-// assertEquals( c1.getName(), result.get(0).get(tname) );
-// assertEquals( c1.getAge(), result.get(0).get("age") );
-
-
- em.getTransaction().rollback();
+ em = factory.createEntityManager();
+ em.getTransaction().begin();
+ em.createQuery( "delete Customer" ).executeUpdate();
+ em.getTransaction().commit();
em.close();
}
- public Class[] getAnnotatedClasses() {
- return new Class[] {
- Customer.class
- };
- }
}
Modified: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/Customer.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/Customer.java 2010-01-07 20:34:59 UTC (rev 18443)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/Customer.java 2010-01-07 20:41:54 UTC (rev 18444)
@@ -45,6 +45,7 @@
public class Customer implements java.io.Serializable {
private String id;
private String name;
+ private Integer age;
private Address home;
private Address work;
private Country country;
@@ -96,6 +97,15 @@
this.name = v;
}
+ @Column(name = "AGE")
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
@Embedded
public Country getCountry() {
return country;
More information about the hibernate-commits
mailing list