HHH-3409 : ResultTransformer uniqueing
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@14995 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
280f722a32
commit
1851bffce7
|
@ -29,29 +29,64 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps the tuples in a constructor call.
|
||||||
|
*
|
||||||
|
* todo : why Alias* in the name???
|
||||||
|
*/
|
||||||
public class AliasToBeanConstructorResultTransformer implements ResultTransformer {
|
public class AliasToBeanConstructorResultTransformer implements ResultTransformer {
|
||||||
|
|
||||||
private Constructor constructor;
|
private final Constructor constructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a AliasToBeanConstructorResultTransformer.
|
||||||
|
*
|
||||||
|
* @param constructor The contructor in which to wrap the tuples.
|
||||||
|
*/
|
||||||
public AliasToBeanConstructorResultTransformer(Constructor constructor) {
|
public AliasToBeanConstructorResultTransformer(Constructor constructor) {
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the incoming tuples in a call to our configured constructor.
|
||||||
|
*/
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
try {
|
try {
|
||||||
return constructor.newInstance( tuple );
|
return constructor.newInstance( tuple );
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch ( Exception e ) {
|
||||||
throw new QueryException(
|
throw new QueryException(
|
||||||
"could not instantiate: " +
|
"could not instantiate class [" + constructor.getDeclaringClass().getName() + "] from tuple",
|
||||||
constructor.getDeclaringClass().getName(),
|
e
|
||||||
e );
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public List transformList(List collection) {
|
public List transformList(List collection) {
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define our hashCode by our defined constructor's hasCode.
|
||||||
|
*
|
||||||
|
* @return Our defined ctor hashCode
|
||||||
|
*/
|
||||||
|
public int hashCode() {
|
||||||
|
return constructor.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2 AliasToBeanConstructorResultTransformer are considered equal if they have the same
|
||||||
|
* defined constructor.
|
||||||
|
*
|
||||||
|
* @param other The other instance to check for equality.
|
||||||
|
* @return True if both have the same defined constuctor; false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return other instanceof AliasToBeanConstructorResultTransformer
|
||||||
|
&& constructor.equals( ( ( AliasToBeanConstructorResultTransformer ) other ).constructor );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,64 +33,76 @@ import org.hibernate.property.PropertyAccessorFactory;
|
||||||
import org.hibernate.property.Setter;
|
import org.hibernate.property.Setter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result transformer that allows to transform a result to
|
* Result transformer that allows to transform a result to
|
||||||
* a user specified class which will be populated via setter
|
* a user specified class which will be populated via setter
|
||||||
* methods or fields matching the alias names.
|
* methods or fields matching the alias names.
|
||||||
*
|
* <p/>
|
||||||
* <pre>
|
* <pre>
|
||||||
* List resultWithAliasedBean = s.createCriteria(Enrolment.class)
|
* List resultWithAliasedBean = s.createCriteria(Enrolment.class)
|
||||||
* .createAlias("student", "st")
|
* .createAlias("student", "st")
|
||||||
* .createAlias("course", "co")
|
* .createAlias("course", "co")
|
||||||
* .setProjection( Projections.projectionList()
|
* .setProjection( Projections.projectionList()
|
||||||
* .add( Projections.property("co.description"), "courseDescription" )
|
* .add( Projections.property("co.description"), "courseDescription" )
|
||||||
* )
|
* )
|
||||||
* .setResultTransformer( new AliasToBeanResultTransformer(StudentDTO.class) )
|
* .setResultTransformer( new AliasToBeanResultTransformer(StudentDTO.class) )
|
||||||
* .list();
|
* .list();
|
||||||
*
|
* <p/>
|
||||||
* StudentDTO dto = (StudentDTO)resultWithAliasedBean.get(0);
|
* StudentDTO dto = (StudentDTO)resultWithAliasedBean.get(0);
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author max
|
* @author max
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class AliasToBeanResultTransformer implements ResultTransformer {
|
public class AliasToBeanResultTransformer implements ResultTransformer {
|
||||||
|
|
||||||
|
// IMPL NOTE : due to the delayed population of setters (setters cached
|
||||||
|
// for performance), we really cannot pro0perly define equality for
|
||||||
|
// this transformer
|
||||||
|
|
||||||
private final Class resultClass;
|
private final Class resultClass;
|
||||||
|
private final PropertyAccessor propertyAccessor;
|
||||||
private Setter[] setters;
|
private Setter[] setters;
|
||||||
private PropertyAccessor propertyAccessor;
|
|
||||||
|
|
||||||
public AliasToBeanResultTransformer(Class resultClass) {
|
public AliasToBeanResultTransformer(Class resultClass) {
|
||||||
if(resultClass==null) throw new IllegalArgumentException("resultClass cannot be null");
|
if ( resultClass == null ) {
|
||||||
|
throw new IllegalArgumentException( "resultClass cannot be null" );
|
||||||
|
}
|
||||||
this.resultClass = resultClass;
|
this.resultClass = resultClass;
|
||||||
propertyAccessor = new ChainedPropertyAccessor(new PropertyAccessor[] { PropertyAccessorFactory.getPropertyAccessor(resultClass,null), PropertyAccessorFactory.getPropertyAccessor("field")});
|
propertyAccessor = new ChainedPropertyAccessor(
|
||||||
|
new PropertyAccessor[] {
|
||||||
|
PropertyAccessorFactory.getPropertyAccessor( resultClass, null ),
|
||||||
|
PropertyAccessorFactory.getPropertyAccessor( "field" )
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
Object result;
|
Object result;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(setters==null) {
|
if ( setters == null ) {
|
||||||
setters = new Setter[aliases.length];
|
setters = new Setter[aliases.length];
|
||||||
for (int i = 0; i < aliases.length; i++) {
|
for ( int i = 0; i < aliases.length; i++ ) {
|
||||||
String alias = aliases[i];
|
String alias = aliases[i];
|
||||||
if(alias != null) {
|
if ( alias != null ) {
|
||||||
setters[i] = propertyAccessor.getSetter(resultClass, alias);
|
setters[i] = propertyAccessor.getSetter( resultClass, alias );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = resultClass.newInstance();
|
result = resultClass.newInstance();
|
||||||
|
|
||||||
for (int i = 0; i < aliases.length; i++) {
|
for ( int i = 0; i < aliases.length; i++ ) {
|
||||||
if(setters[i]!=null) {
|
if ( setters[i] != null ) {
|
||||||
setters[i].set(result, tuple[i], null);
|
setters[i].set( result, tuple[i], null );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InstantiationException e) {
|
|
||||||
throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName());
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new HibernateException("Could not instantiate resultclass: " + resultClass.getName());
|
|
||||||
}
|
}
|
||||||
|
catch ( InstantiationException e ) {
|
||||||
|
throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() );
|
||||||
|
}
|
||||||
|
catch ( IllegalAccessException e ) {
|
||||||
|
throw new HibernateException( "Could not instantiate resultclass: " + resultClass.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,4 +110,10 @@ public class AliasToBeanResultTransformer implements ResultTransformer {
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
result = resultClass.hashCode();
|
||||||
|
result = 31 * result + propertyAccessor.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,31 @@
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link ResultTransformer} implementation which builds a map for each "row",
|
||||||
|
* made up of each aliased value where the alias is the map key.
|
||||||
|
* <p/>
|
||||||
|
* Since this transformer is stateless, all instances would be considered equal.
|
||||||
|
* So for optimization purposes we limit it to a single, singleton {@link #INSTANCE instance}.
|
||||||
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class AliasToEntityMapResultTransformer implements ResultTransformer {
|
public class AliasToEntityMapResultTransformer extends BasicTransformerAdapter implements Serializable {
|
||||||
|
|
||||||
|
public static final AliasToEntityMapResultTransformer INSTANCE = new AliasToEntityMapResultTransformer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate AliasToEntityMapResultTransformer.
|
||||||
|
*
|
||||||
|
* @deprecated Use the {@link #INSTANCE} reference instead of explicitly creating a new one.
|
||||||
|
*/
|
||||||
|
public AliasToEntityMapResultTransformer() {
|
||||||
|
// todo : make private
|
||||||
|
}
|
||||||
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
Map result = new HashMap(tuple.length);
|
Map result = new HashMap(tuple.length);
|
||||||
|
@ -44,8 +62,38 @@ public class AliasToEntityMapResultTransformer implements ResultTransformer {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List transformList(List collection) {
|
/**
|
||||||
return collection;
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
|
*
|
||||||
|
* @return The singleton instance : {@link #INSTANCE}
|
||||||
|
*/
|
||||||
|
private Object readResolve() {
|
||||||
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// all AliasToEntityMapResultTransformer are considered equal ~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All AliasToEntityMapResultTransformer are considered equal
|
||||||
|
*
|
||||||
|
* @param other The other instance to check for equality
|
||||||
|
* @return True if (non-null) other is a instance of
|
||||||
|
* AliasToEntityMapResultTransformer.
|
||||||
|
*/
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
// todo : we can remove this once the deprecated ctor can be made private...
|
||||||
|
return other != null && AliasToEntityMapResultTransformer.class.isInstance( other );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All AliasToEntityMapResultTransformer are considered equal
|
||||||
|
*
|
||||||
|
* @return We simply return the hashCode of the
|
||||||
|
* AliasToEntityMapResultTransformer class name string.
|
||||||
|
*/
|
||||||
|
public int hashCode() {
|
||||||
|
// todo : we can remove this once the deprecated ctor can be made private...
|
||||||
|
return getClass().getName().hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.transform;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the basic "noop" impls of the {@link ResultTransformer} contract.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class BasicTransformerAdapter implements ResultTransformer {
|
||||||
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
|
return tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List transformList(List list) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Middleware LLC.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.hibernate.transform;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distinctions the result tuples in the final result based on the defined
|
||||||
|
* equality of the tuples.
|
||||||
|
* <p/>
|
||||||
|
* Since this transformer is stateless, all instances would be considered equal.
|
||||||
|
* So for optimization purposes we limit it to a single, singleton {@link #INSTANCE instance}.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class DistinctResultTransformer extends BasicTransformerAdapter implements Serializable {
|
||||||
|
|
||||||
|
public static final DistinctResultTransformer INSTANCE = new DistinctResultTransformer();
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger( DistinctResultTransformer.class );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to handle distincting
|
||||||
|
*/
|
||||||
|
private static final class Identity {
|
||||||
|
final Object entity;
|
||||||
|
|
||||||
|
private Identity(Object entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return Identity.class.isInstance( other )
|
||||||
|
&& this.entity == ( ( Identity ) other ).entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public int hashCode() {
|
||||||
|
return System.identityHashCode( entity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disallow instantiation of DistinctResultTransformer.
|
||||||
|
*/
|
||||||
|
private DistinctResultTransformer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uniquely distinct each tuple row here.
|
||||||
|
*/
|
||||||
|
public List transformList(List list) {
|
||||||
|
List result = new ArrayList( list.size() );
|
||||||
|
Set distinct = new HashSet();
|
||||||
|
for ( int i = 0; i < list.size(); i++ ) {
|
||||||
|
Object entity = list.get( i );
|
||||||
|
if ( distinct.add( new Identity( entity ) ) ) {
|
||||||
|
result.add( entity );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debug(
|
||||||
|
"transformed: " +
|
||||||
|
list.size() + " rows to: " +
|
||||||
|
result.size() + " distinct results"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
|
*
|
||||||
|
* @return The singleton instance : {@link #INSTANCE}
|
||||||
|
*/
|
||||||
|
private Object readResolve() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,54 +24,63 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Much like {@link RootEntityResultTransformer}, but we also distinct
|
||||||
|
* the entity in the final result.
|
||||||
|
* <p/>
|
||||||
|
* Since this transformer is stateless, all instances would be considered equal.
|
||||||
|
* So for optimization purposes we limit it to a single, singleton {@link #INSTANCE instance}.
|
||||||
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class DistinctRootEntityResultTransformer implements ResultTransformer {
|
public class DistinctRootEntityResultTransformer implements ResultTransformer, Serializable {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(DistinctRootEntityResultTransformer.class);
|
public static final DistinctRootEntityResultTransformer INSTANCE = new DistinctRootEntityResultTransformer();
|
||||||
|
|
||||||
static final class Identity {
|
/**
|
||||||
final Object entity;
|
* Instantiate a DistinctRootEntityResultTransformer.
|
||||||
Identity(Object entity) {
|
*
|
||||||
this.entity = entity;
|
* @deprecated Use the {@link #INSTANCE} reference instead of explicitly creating a new one.
|
||||||
}
|
*/
|
||||||
public boolean equals(Object other) {
|
public DistinctRootEntityResultTransformer() {
|
||||||
Identity that = (Identity) other;
|
|
||||||
return entity==that.entity;
|
|
||||||
}
|
|
||||||
public int hashCode() {
|
|
||||||
return System.identityHashCode(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simply delegates to {@link RootEntityResultTransformer#transformTuple}.
|
||||||
|
*
|
||||||
|
* @param tuple The tuple to transform
|
||||||
|
* @param aliases The tuple aliases
|
||||||
|
* @return The transformed tuple row.
|
||||||
|
*/
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return tuple[ tuple.length-1 ];
|
return RootEntityResultTransformer.INSTANCE.transformTuple( tuple, aliases );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simply delegates to {@link DistinctResultTransformer#transformList}.
|
||||||
|
*
|
||||||
|
* @param list The list to transform.
|
||||||
|
* @return The transformed List.
|
||||||
|
*/
|
||||||
public List transformList(List list) {
|
public List transformList(List list) {
|
||||||
List result = new ArrayList( list.size() );
|
return DistinctResultTransformer.INSTANCE.transformList( list );
|
||||||
Set distinct = new HashSet();
|
|
||||||
for ( int i=0; i<list.size(); i++ ) {
|
|
||||||
Object entity = list.get(i);
|
|
||||||
if ( distinct.add( new Identity(entity) ) ) {
|
|
||||||
result.add(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( log.isDebugEnabled() ) log.debug(
|
|
||||||
"transformed: " +
|
|
||||||
list.size() + " rows to: " +
|
|
||||||
result.size() + " distinct results"
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
|
*
|
||||||
|
* @return The singleton instance : {@link #INSTANCE}
|
||||||
|
*/
|
||||||
|
private Object readResolve() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
// todo : we can remove this once the deprecated ctor can be made private...
|
||||||
|
return DistinctRootEntityResultTransformer.class.isInstance( obj );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,19 +24,41 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.util.List;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* ???
|
||||||
|
*
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public class PassThroughResultTransformer implements ResultTransformer {
|
public class PassThroughResultTransformer extends BasicTransformerAdapter implements Serializable {
|
||||||
|
|
||||||
|
public static final PassThroughResultTransformer INSTANCE = new PassThroughResultTransformer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instamtiate a PassThroughResultTransformer.
|
||||||
|
*
|
||||||
|
* @deprecated Use the {@link #INSTANCE} reference instead of explicitly creating a new one.
|
||||||
|
*/
|
||||||
|
public PassThroughResultTransformer() {
|
||||||
|
}
|
||||||
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return tuple.length==1 ? tuple[0] : tuple;
|
return tuple.length==1 ? tuple[0] : tuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List transformList(List collection) {
|
/**
|
||||||
return collection;
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
|
*
|
||||||
|
* @return The singleton instance : {@link #INSTANCE}
|
||||||
|
*/
|
||||||
|
private Object readResolve() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
// todo : we can remove this once the deprecated ctor can be made private...
|
||||||
|
return PassThroughResultTransformer.class.isInstance( obj );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,48 @@
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@link ResultTransformer} implementation which limits the result tuple
|
||||||
|
* to only the "root entity".
|
||||||
|
* <p/>
|
||||||
|
* Since this transformer is stateless, all instances would be considered equal.
|
||||||
|
* So for optimization purposes we limit it to a single, singleton {@link #INSTANCE instance}.
|
||||||
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class RootEntityResultTransformer implements ResultTransformer {
|
public final class RootEntityResultTransformer extends BasicTransformerAdapter implements Serializable {
|
||||||
|
|
||||||
|
public static final RootEntityResultTransformer INSTANCE = new RootEntityResultTransformer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate RootEntityResultTransformer.
|
||||||
|
*
|
||||||
|
* @deprecated Use the {@link #INSTANCE} reference instead of explicitly creating a new one.
|
||||||
|
*/
|
||||||
|
public RootEntityResultTransformer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return just the root entity from the row tuple.
|
||||||
|
*/
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return tuple[ tuple.length-1 ];
|
return tuple[ tuple.length-1 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
public List transformList(List collection) {
|
/**
|
||||||
return collection;
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
|
*
|
||||||
|
* @return The singleton instance : {@link #INSTANCE}
|
||||||
|
*/
|
||||||
|
private Object readResolve() {
|
||||||
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
// todo : we can remove this once the deprecated ctor can be made private...
|
||||||
|
return RootEntityResultTransformer.class.isInstance( obj );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,19 +26,35 @@ package org.hibernate.transform;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class ToListResultTransformer implements ResultTransformer {
|
/**
|
||||||
|
* Tranforms each result row from a tuple into a {@link List}, such that what
|
||||||
|
* you end up with is a {@link List} of {@link List Lists}.
|
||||||
|
*/
|
||||||
|
public class ToListResultTransformer extends BasicTransformerAdapter implements Serializable {
|
||||||
|
|
||||||
public static final ResultTransformer INSTANCE = new ToListResultTransformer();
|
public static final ToListResultTransformer INSTANCE = new ToListResultTransformer();
|
||||||
|
|
||||||
private ToListResultTransformer() {}
|
/**
|
||||||
|
* Disallow instantiation of ToListResultTransformer.
|
||||||
|
*/
|
||||||
|
private ToListResultTransformer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return Arrays.asList(tuple);
|
return Arrays.asList( tuple );
|
||||||
}
|
}
|
||||||
|
|
||||||
public List transformList(List collection) {
|
/**
|
||||||
return collection;
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
|
*
|
||||||
|
* @return The singleton instance : {@link #INSTANCE}
|
||||||
|
*/
|
||||||
|
private Object readResolve() {
|
||||||
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ final public class Transformers {
|
||||||
/**
|
/**
|
||||||
* Each row of results is a <tt>Map</tt> from alias to values/entities
|
* Each row of results is a <tt>Map</tt> from alias to values/entities
|
||||||
*/
|
*/
|
||||||
public static final ResultTransformer ALIAS_TO_ENTITY_MAP = new AliasToEntityMapResultTransformer();
|
public static final AliasToEntityMapResultTransformer ALIAS_TO_ENTITY_MAP =
|
||||||
|
AliasToEntityMapResultTransformer.INSTANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each row of results is a <tt>List</tt>
|
* Each row of results is a <tt>List</tt>
|
||||||
|
|
Loading…
Reference in New Issue