massive cleanout of the transformers stuff
- add meaningful generic types to stuff - remove things which weren't used/tested, and seem obsolete (and which could not be propertly generified)
This commit is contained in:
parent
22457cc74d
commit
c43b6ff606
|
@ -14,17 +14,17 @@ import jakarta.persistence.Tuple;
|
||||||
import jakarta.persistence.TupleElement;
|
import jakarta.persistence.TupleElement;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.transform.BasicTransformerAdapter;
|
import org.hibernate.transform.ResultTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResultTransformer adapter for handling Tuple results from Native queries
|
* ResultTransformer adapter for handling Tuple results from Native queries
|
||||||
*
|
*
|
||||||
* @author Arnold Galovics
|
* @author Arnold Galovics
|
||||||
*/
|
*/
|
||||||
public class NativeQueryTupleTransformer extends BasicTransformerAdapter {
|
public class NativeQueryTupleTransformer implements ResultTransformer<Tuple> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Tuple transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return new NativeTupleImpl( tuple, aliases );
|
return new NativeTupleImpl( tuple, aliases );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +52,10 @@ public class NativeQueryTupleTransformer extends BasicTransformerAdapter {
|
||||||
|
|
||||||
private static class NativeTupleImpl implements Tuple {
|
private static class NativeTupleImpl implements Tuple {
|
||||||
|
|
||||||
private Object[] tuple;
|
private final Object[] tuple;
|
||||||
|
|
||||||
private Map<String, Object> aliasToValue = new LinkedHashMap<>();
|
private final Map<String, Object> aliasToValue = new LinkedHashMap<>();
|
||||||
private Map<String, String> aliasReferences = new LinkedHashMap<>();
|
private final Map<String, String> aliasReferences = new LinkedHashMap<>();
|
||||||
|
|
||||||
public NativeTupleImpl(Object[] tuple, String[] aliases) {
|
public NativeTupleImpl(Object[] tuple, String[] aliases) {
|
||||||
if ( tuple == null ) {
|
if ( tuple == null ) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.hibernate.CacheMode;
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the aspects of query definition that apply to all forms of
|
* Defines the aspects of query definition that apply to all forms of
|
||||||
|
|
|
@ -558,13 +558,13 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
|
||||||
NativeQuery<T> setLockMode(LockModeType lockMode);
|
NativeQuery<T> setLockMode(LockModeType lockMode);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQuery<T> setTupleTransformer(TupleTransformer<T> transformer);
|
<R> NativeQuery<R> setTupleTransformer(TupleTransformer<R> transformer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQuery<T> setResultListTransformer(ResultListTransformer transformer);
|
NativeQuery<T> setResultListTransformer(ResultListTransformer<T> transformer);
|
||||||
|
|
||||||
@Override @SuppressWarnings("deprecation")
|
@Override @Deprecated @SuppressWarnings("deprecation")
|
||||||
NativeQuery<T> setResultTransformer(ResultTransformer transformer);
|
<S> NativeQuery<S> setResultTransformer(ResultTransformer<S> transformer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQuery<T> setParameter(String name, Object value);
|
NativeQuery<T> setParameter(String name, Object value);
|
||||||
|
|
|
@ -303,12 +303,12 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
|
||||||
/**
|
/**
|
||||||
* Set a {@link TupleTransformer}
|
* Set a {@link TupleTransformer}
|
||||||
*/
|
*/
|
||||||
Query<R> setTupleTransformer(TupleTransformer<R> transformer);
|
<T> Query<T> setTupleTransformer(TupleTransformer<T> transformer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a {@link ResultListTransformer}
|
* Set a {@link ResultListTransformer}
|
||||||
*/
|
*/
|
||||||
Query<R> setResultListTransformer(ResultListTransformer transformer);
|
Query<R> setResultListTransformer(ResultListTransformer<R> transformer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the execution options for this Query. Many of the setter on the Query
|
* Get the execution options for this Query. Many of the setter on the Query
|
||||||
|
@ -807,14 +807,11 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
|
||||||
// deprecated methods
|
// deprecated methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 5.2) Use {@link #setTupleTransformer} or {@link #setResultListTransformer}
|
* @deprecated Use {@link #setTupleTransformer} or {@link #setResultListTransformer}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated(since = "5.2")
|
||||||
@SuppressWarnings("unchecked")
|
default <T> Query<T> setResultTransformer(ResultTransformer<T> transformer) {
|
||||||
default Query<R> setResultTransformer(ResultTransformer transformer) {
|
return setTupleTransformer( transformer ).setResultListTransformer( transformer );
|
||||||
setTupleTransformer( transformer );
|
|
||||||
setResultListTransformer( transformer );
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,15 +9,17 @@ package org.hibernate.query;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows defining transformation of the result List from a Query to some
|
* Defines some processing performed on the result {@link List} of a
|
||||||
* other form.
|
* {@link org.hibernate.Query} before the result list is returned to
|
||||||
|
* the caller of {@link org.hibernate.Query#getResultList()}.
|
||||||
*
|
*
|
||||||
* @see org.hibernate.transform.ResultTransformer
|
* @see org.hibernate.transform.ResultTransformer
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public interface ResultListTransformer {
|
@FunctionalInterface
|
||||||
|
public interface ResultListTransformer<T> {
|
||||||
/**
|
/**
|
||||||
* Here we have an opportunity to perform transformation on the
|
* Here we have an opportunity to perform transformation on the
|
||||||
* query result as a whole. This might be useful to convert from
|
* query result as a whole. This might be useful to convert from
|
||||||
|
@ -29,5 +31,5 @@ public interface ResultListTransformer {
|
||||||
*
|
*
|
||||||
* @return The transformed result.
|
* @return The transformed result.
|
||||||
*/
|
*/
|
||||||
List transformList(List resultList);
|
List<T> transformList(List<T> resultList);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,19 @@ package org.hibernate.query;
|
||||||
|
|
||||||
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
|
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User hook for applying transformations of the query result tuples (the result "row").
|
* Defines some transformation applied to each result of a {@link org.hibernate.Query}
|
||||||
*
|
* before the results are packaged as a {@link List} and returned to the caller of
|
||||||
* Ultimately, gets wrapped in a {@link RowTransformerTupleTransformerAdapter}
|
* {@link org.hibernate.Query#getResultList()}. Each query result is received as a
|
||||||
* to adapt the TupleTransformer to the {@link org.hibernate.sql.results.spi.RowTransformer}
|
* tuple, that is, as an array of type {@code Object[]}, and may be transformed to
|
||||||
* contract, which is the thing actually used to process the results internally.
|
* some other type.
|
||||||
|
* <p>
|
||||||
|
* Every {@code TupleTransformer} is automatically wrapped in an instance of
|
||||||
|
* {@link RowTransformerTupleTransformerAdapter}, adapting it to the
|
||||||
|
* {@link org.hibernate.sql.results.spi.RowTransformer} contract, which is always
|
||||||
|
* used to actually process the results internally.
|
||||||
*
|
*
|
||||||
* @see org.hibernate.transform.ResultTransformer
|
* @see org.hibernate.transform.ResultTransformer
|
||||||
* @see org.hibernate.sql.results.spi.RowTransformer
|
* @see org.hibernate.sql.results.spi.RowTransformer
|
||||||
|
@ -21,6 +28,7 @@ import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
public interface TupleTransformer<T> {
|
public interface TupleTransformer<T> {
|
||||||
/**
|
/**
|
||||||
* Tuples are the elements making up each "row" of the query result.
|
* Tuples are the elements making up each "row" of the query result.
|
||||||
|
@ -33,11 +41,4 @@ public interface TupleTransformer<T> {
|
||||||
* @return The transformed row.
|
* @return The transformed row.
|
||||||
*/
|
*/
|
||||||
T transformTuple(Object[] tuple, String[] aliases);
|
T transformTuple(Object[] tuple, String[] aliases);
|
||||||
|
|
||||||
/**
|
|
||||||
* How many result elements will this transformation produce?
|
|
||||||
*/
|
|
||||||
default int determineNumberOfResultElements(int rawElementCount) {
|
|
||||||
return rawElementCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,6 @@ import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
||||||
protected static final EntityManagerMessageLogger log = HEMLogging.messageLogger( AbstractQuery.class );
|
protected static final EntityManagerMessageLogger log = HEMLogging.messageLogger( AbstractQuery.class );
|
||||||
|
|
||||||
|
@ -201,15 +200,15 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @SuppressWarnings("unchecked")
|
||||||
@SuppressWarnings( "rawtypes" )
|
public <T> QueryImplementor<T> setTupleTransformer(TupleTransformer<T> transformer) {
|
||||||
public QueryImplementor<R> setTupleTransformer(TupleTransformer transformer) {
|
|
||||||
getQueryOptions().setTupleTransformer( transformer );
|
getQueryOptions().setTupleTransformer( transformer );
|
||||||
return this;
|
// this is bad, we should really return a new instance:
|
||||||
|
return (QueryImplementor<T>) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryImplementor<R> setResultListTransformer(ResultListTransformer transformer) {
|
public QueryImplementor<R> setResultListTransformer(ResultListTransformer<R> transformer) {
|
||||||
getQueryOptions().setResultListTransformer( transformer );
|
getQueryOptions().setResultListTransformer( transformer );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ import org.hibernate.query.QueryParameter;
|
||||||
|
|
||||||
import jakarta.persistence.Parameter;
|
import jakarta.persistence.Parameter;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
import org.hibernate.query.ResultListTransformer;
|
||||||
|
import org.hibernate.query.TupleTransformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -46,6 +48,12 @@ public interface QueryImplementor<R> extends Query<R> {
|
||||||
ScrollableResultsImplementor<R> scroll(ScrollMode scrollMode);
|
ScrollableResultsImplementor<R> scroll(ScrollMode scrollMode);
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
<T> QueryImplementor<T> setTupleTransformer(TupleTransformer<T> transformer);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
QueryImplementor<R> setResultListTransformer(ResultListTransformer<R> transformer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
QueryImplementor<R> setParameter(String name, Object value);
|
QueryImplementor<R> setParameter(String name, Object value);
|
||||||
|
|
||||||
|
@ -101,7 +109,7 @@ public interface QueryImplementor<R> extends Query<R> {
|
||||||
QueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType);
|
QueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
QueryImplementor<R> setParameterList(String name, Collection values);
|
QueryImplementor<R> setParameterList(String name, @SuppressWarnings("rawtypes") Collection values);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
<P> QueryImplementor<R> setParameterList(String name, Collection<? extends P> values, Class<P> javaType);
|
<P> QueryImplementor<R> setParameterList(String name, Collection<? extends P> values, Class<P> javaType);
|
||||||
|
@ -119,7 +127,7 @@ public interface QueryImplementor<R> extends Query<R> {
|
||||||
<P> QueryImplementor<R> setParameterList(String name, P[] values, BindableType<P> type);
|
<P> QueryImplementor<R> setParameterList(String name, P[] values, BindableType<P> type);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
QueryImplementor<R> setParameterList(int position, Collection values);
|
QueryImplementor<R> setParameterList(int position, @SuppressWarnings("rawtypes") Collection values);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
<P> QueryImplementor<R> setParameterList(int position, Collection<? extends P> values, Class<P> javaType);
|
<P> QueryImplementor<R> setParameterList(int position, Collection<? extends P> values, Class<P> javaType);
|
||||||
|
@ -158,5 +166,5 @@ public interface QueryImplementor<R> extends Query<R> {
|
||||||
QueryImplementor<R> setProperties(Object bean);
|
QueryImplementor<R> setProperties(Object bean);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
QueryImplementor<R> setProperties(Map bean);
|
QueryImplementor<R> setProperties(@SuppressWarnings("rawtypes") Map bean);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,6 @@ import static org.hibernate.jpa.QueryHints.HINT_NATIVE_LOCKMODE;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public class NativeQueryImpl<R>
|
public class NativeQueryImpl<R>
|
||||||
extends AbstractQuery<R>
|
extends AbstractQuery<R>
|
||||||
implements NativeQueryImplementor<R>, DomainQueryExecutionContext, ResultSetMappingResolutionContext {
|
implements NativeQueryImplementor<R>, DomainQueryExecutionContext, ResultSetMappingResolutionContext {
|
||||||
|
@ -503,12 +502,12 @@ public class NativeQueryImpl<R>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryImplementor<R> setTupleTransformer(@SuppressWarnings("rawtypes") TupleTransformer transformer) {
|
public <T> NativeQueryImplementor<T> setTupleTransformer(TupleTransformer<T> transformer) {
|
||||||
return (NativeQueryImplementor<R>) super.setTupleTransformer( transformer );
|
return (NativeQueryImplementor<T>) super.setTupleTransformer( transformer );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer transformer) {
|
public NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer<R> transformer) {
|
||||||
return (NativeQueryImplementor<R>) super.setResultListTransformer( transformer );
|
return (NativeQueryImplementor<R>) super.setResultListTransformer( transformer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,21 +1448,9 @@ public class NativeQueryImpl<R>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override @Deprecated @SuppressWarnings("deprecation")
|
||||||
|
public <S> NativeQueryImplementor<S> setResultTransformer(ResultTransformer<S> transformer) {
|
||||||
|
return setTupleTransformer( transformer ).setResultListTransformer( transformer );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override @SuppressWarnings("deprecation")
|
|
||||||
public NativeQueryImplementor<R> setResultTransformer(ResultTransformer transformer) {
|
|
||||||
super.setResultTransformer( transformer );
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -190,10 +190,10 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
|
||||||
NativeQueryImplementor<R> addQueryHint(String hint);
|
NativeQueryImplementor<R> addQueryHint(String hint);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQueryImplementor<R> setTupleTransformer(@SuppressWarnings("rawtypes") TupleTransformer transformer);
|
<T> NativeQueryImplementor<T> setTupleTransformer(TupleTransformer<T> transformer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer transformer);
|
NativeQueryImplementor<R> setResultListTransformer(ResultListTransformer<R> transformer);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQueryImplementor<R> setParameter(String name, Object val);
|
NativeQueryImplementor<R> setParameter(String name, Object val);
|
||||||
|
|
|
@ -32,6 +32,6 @@ public class RowTransformerTupleTransformerAdapter<T> implements RowTransformer<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int determineNumberOfResultElements(int rawElementCount) {
|
public int determineNumberOfResultElements(int rawElementCount) {
|
||||||
return tupleTransformer.determineNumberOfResultElements( rawElementCount );
|
return rawElementCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,26 +5,24 @@
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps the tuples in a constructor call.
|
* Wraps the tuples in a constructor call.
|
||||||
*
|
|
||||||
* todo : why Alias* in the name???
|
|
||||||
*/
|
*/
|
||||||
public class AliasToBeanConstructorResultTransformer implements ResultTransformer {
|
public class AliasToBeanConstructorResultTransformer<T> implements ResultTransformer<T> {
|
||||||
|
|
||||||
private final Constructor constructor;
|
private final Constructor<T> constructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a AliasToBeanConstructorResultTransformer.
|
* Instantiates a AliasToBeanConstructorResultTransformer.
|
||||||
*
|
*
|
||||||
* @param constructor The constructor in which to wrap the tuples.
|
* @param constructor The constructor in which to wrap the tuples.
|
||||||
*/
|
*/
|
||||||
public AliasToBeanConstructorResultTransformer(Constructor constructor) {
|
public AliasToBeanConstructorResultTransformer(Constructor<T> constructor) {
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +30,7 @@ public class AliasToBeanConstructorResultTransformer implements ResultTransforme
|
||||||
* Wrap the incoming tuples in a call to our configured constructor.
|
* Wrap the incoming tuples in a call to our configured constructor.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public T transformTuple(Object[] tuple, String[] aliases) {
|
||||||
try {
|
try {
|
||||||
return constructor.newInstance( tuple );
|
return constructor.newInstance( tuple );
|
||||||
}
|
}
|
||||||
|
@ -44,11 +42,6 @@ public class AliasToBeanConstructorResultTransformer implements ResultTransforme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List transformList(List collection) {
|
|
||||||
return collection;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define our hashCode by our defined constructor's hasCode.
|
* Define our hashCode by our defined constructor's hasCode.
|
||||||
*
|
*
|
||||||
|
@ -69,6 +62,6 @@ public class AliasToBeanConstructorResultTransformer implements ResultTransforme
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
return other instanceof AliasToBeanConstructorResultTransformer
|
return other instanceof AliasToBeanConstructorResultTransformer
|
||||||
&& constructor.equals( ( ( AliasToBeanConstructorResultTransformer ) other ).constructor );
|
&& constructor.equals( ( (AliasToBeanConstructorResultTransformer<?>) other ).constructor );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,34 +19,21 @@ import org.hibernate.property.access.spi.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>
|
|
||||||
* List resultWithAliasedBean = s.createCriteria(Enrolment.class)
|
|
||||||
* .createAlias("student", "st")
|
|
||||||
* .createAlias("course", "co")
|
|
||||||
* .setProjection( Projections.projectionList()
|
|
||||||
* .add( Projections.property("co.description"), "courseDescription" )
|
|
||||||
* )
|
|
||||||
* .setResultTransformer( new AliasToBeanResultTransformer(StudentDTO.class) )
|
|
||||||
* .list();
|
|
||||||
* <p/>
|
|
||||||
* StudentDTO dto = (StudentDTO)resultWithAliasedBean.get(0);
|
|
||||||
* </pre>
|
|
||||||
*
|
*
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransformer {
|
public class AliasToBeanResultTransformer<T> implements ResultTransformer<T> {
|
||||||
|
|
||||||
// IMPL NOTE : due to the delayed population of setters (setters cached
|
// IMPL NOTE : due to the delayed population of setters (setters cached
|
||||||
// for performance), we really cannot properly define equality for
|
// for performance), we really cannot properly define equality for
|
||||||
// this transformer
|
// this transformer
|
||||||
|
|
||||||
private final Class resultClass;
|
private final Class<T> resultClass;
|
||||||
private boolean isInitialized;
|
private boolean isInitialized;
|
||||||
private String[] aliases;
|
private String[] aliases;
|
||||||
private Setter[] setters;
|
private Setter[] setters;
|
||||||
|
|
||||||
public AliasToBeanResultTransformer(Class resultClass) {
|
public AliasToBeanResultTransformer(Class<T> resultClass) {
|
||||||
if ( resultClass == null ) {
|
if ( resultClass == null ) {
|
||||||
throw new IllegalArgumentException( "resultClass cannot be null" );
|
throw new IllegalArgumentException( "resultClass cannot be null" );
|
||||||
}
|
}
|
||||||
|
@ -55,13 +42,8 @@ public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransf
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
|
public T transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return false;
|
T result;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
|
||||||
Object result;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ( ! isInitialized ) {
|
if ( ! isInitialized ) {
|
||||||
|
@ -121,16 +103,10 @@ public class AliasToBeanResultTransformer extends AliasedTupleSubsetResultTransf
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AliasToBeanResultTransformer that = ( AliasToBeanResultTransformer ) o;
|
AliasToBeanResultTransformer<?> that = (AliasToBeanResultTransformer<?>) o;
|
||||||
|
|
||||||
if ( ! resultClass.equals( that.resultClass ) ) {
|
return resultClass.equals( that.resultClass )
|
||||||
return false;
|
&& Arrays.equals( aliases, that.aliases );
|
||||||
}
|
|
||||||
if ( ! Arrays.equals( aliases, that.aliases ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -12,14 +12,11 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
/**
|
/**
|
||||||
* {@link ResultTransformer} implementation which builds a map for each "row",
|
* {@link ResultTransformer} implementation which builds a map for each "row",
|
||||||
* made up of each aliased value where the alias is the map key.
|
* 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
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class AliasToEntityMapResultTransformer extends AliasedTupleSubsetResultTransformer {
|
public class AliasToEntityMapResultTransformer implements ResultTransformer<Map<String,Object>> {
|
||||||
|
|
||||||
public static final AliasToEntityMapResultTransformer INSTANCE = new AliasToEntityMapResultTransformer();
|
public static final AliasToEntityMapResultTransformer INSTANCE = new AliasToEntityMapResultTransformer();
|
||||||
|
|
||||||
|
@ -30,8 +27,8 @@ public class AliasToEntityMapResultTransformer extends AliasedTupleSubsetResultT
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Map<String,Object> transformTuple(Object[] tuple, String[] aliases) {
|
||||||
Map result = CollectionHelper.mapOfSize( tuple.length );
|
Map<String,Object> result = CollectionHelper.mapOfSize( tuple.length );
|
||||||
for ( int i = 0; i < tuple.length; i++ ) {
|
for ( int i = 0; i < tuple.length; i++ ) {
|
||||||
String alias = aliases[i];
|
String alias = aliases[i];
|
||||||
if ( alias != null ) {
|
if ( alias != null ) {
|
||||||
|
@ -41,11 +38,6 @@ public class AliasToEntityMapResultTransformer extends AliasedTupleSubsetResultT
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialization hook for ensuring singleton uniqueing.
|
* Serialization hook for ensuring singleton uniqueing.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of TupleSubsetResultTransformer that ignores a
|
|
||||||
* tuple element if its corresponding alias is null.
|
|
||||||
*
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public abstract class AliasedTupleSubsetResultTransformer
|
|
||||||
extends BasicTransformerAdapter
|
|
||||||
implements TupleSubsetResultTransformer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean[] includeInTransform(String[] aliases, int tupleLength) {
|
|
||||||
if ( aliases == null ) {
|
|
||||||
throw new IllegalArgumentException( "aliases cannot be null" );
|
|
||||||
}
|
|
||||||
if ( aliases.length != tupleLength ) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"aliases and tupleLength must have the same length; " +
|
|
||||||
"aliases.length=" + aliases.length + "; tupleLength=" + tupleLength
|
|
||||||
);
|
|
||||||
}
|
|
||||||
boolean[] includeInTransform = new boolean[tupleLength];
|
|
||||||
for ( int i = 0 ; i < aliases.length ; i++ ) {
|
|
||||||
if ( aliases[ i ] != null ) {
|
|
||||||
includeInTransform[ i ] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return includeInTransform;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,318 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ResultTransformer that is used to transform tuples to a value(s)
|
|
||||||
* that can be cached.
|
|
||||||
*
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class CacheableResultTransformer implements ResultTransformer {
|
|
||||||
|
|
||||||
// would be nice to be able to have this class extend
|
|
||||||
// PassThroughResultTransformer, but the default constructor
|
|
||||||
// is private (as it should be for a singleton)
|
|
||||||
private final static PassThroughResultTransformer ACTUAL_TRANSFORMER =
|
|
||||||
PassThroughResultTransformer.INSTANCE;
|
|
||||||
private final int tupleLength;
|
|
||||||
private final int tupleSubsetLength;
|
|
||||||
|
|
||||||
// array with the i-th element indicating whether the i-th
|
|
||||||
// expression returned by a query is included in the tuple;
|
|
||||||
// IMPLEMENTATION NOTE:
|
|
||||||
// "joined" and "fetched" associations may use the same SQL,
|
|
||||||
// but result in different tuple and cached values. This is
|
|
||||||
// because "fetched" associations are excluded from the tuple.
|
|
||||||
// includeInTuple provides a way to distinguish these 2 cases.
|
|
||||||
private final boolean[] includeInTuple;
|
|
||||||
|
|
||||||
// indexes for tuple that are included in the transformation;
|
|
||||||
// set to null if all elements in the tuple are included
|
|
||||||
private final int[] includeInTransformIndex;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a CacheableResultTransformer that is used to transform
|
|
||||||
* tuples to a value(s) that can be cached.
|
|
||||||
*
|
|
||||||
* @param transformer - result transformer that will ultimately be
|
|
||||||
* be used (after caching results)
|
|
||||||
* @param aliases - the aliases that correspond to the tuple;
|
|
||||||
* if it is non-null, its length must equal the number
|
|
||||||
* of true elements in includeInTuple[]
|
|
||||||
* @param includeInTuple - array with the i-th element indicating
|
|
||||||
* whether the i-th expression returned by a query is
|
|
||||||
* included in the tuple; the number of true values equals
|
|
||||||
* the length of the tuple that will be transformed;
|
|
||||||
* must be non-null
|
|
||||||
*
|
|
||||||
* @return a CacheableResultTransformer that is used to transform
|
|
||||||
* tuples to a value(s) that can be cached.
|
|
||||||
*/
|
|
||||||
public static CacheableResultTransformer create(
|
|
||||||
ResultTransformer transformer,
|
|
||||||
String[] aliases,
|
|
||||||
boolean[] includeInTuple) {
|
|
||||||
return transformer instanceof TupleSubsetResultTransformer
|
|
||||||
? create( ( TupleSubsetResultTransformer ) transformer, aliases, includeInTuple )
|
|
||||||
: create( includeInTuple );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a CacheableResultTransformer that is used to transform
|
|
||||||
* tuples to a value(s) that can be cached.
|
|
||||||
*
|
|
||||||
* @param transformer - a tuple subset result transformer;
|
|
||||||
* must be non-null;
|
|
||||||
* @param aliases - the aliases that correspond to the tuple;
|
|
||||||
* if it is non-null, its length must equal the number
|
|
||||||
* of true elements in includeInTuple[]
|
|
||||||
* @param includeInTuple - array with the i-th element indicating
|
|
||||||
* whether the i-th expression returned by a query is
|
|
||||||
* included in the tuple; the number of true values equals
|
|
||||||
* the length of the tuple that will be transformed;
|
|
||||||
* must be non-null
|
|
||||||
*
|
|
||||||
* @return a CacheableResultTransformer that is used to transform
|
|
||||||
* tuples to a value(s) that can be cached.
|
|
||||||
*/
|
|
||||||
private static CacheableResultTransformer create(
|
|
||||||
TupleSubsetResultTransformer transformer,
|
|
||||||
String[] aliases,
|
|
||||||
boolean[] includeInTuple) {
|
|
||||||
if ( transformer == null ) {
|
|
||||||
throw new IllegalArgumentException( "transformer cannot be null" );
|
|
||||||
}
|
|
||||||
int tupleLength = ArrayHelper.countTrue( includeInTuple );
|
|
||||||
if ( aliases != null && aliases.length != tupleLength ) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"if aliases are not null, then the length of aliases must equal the number of true elements in includeInTuple; " +
|
|
||||||
"aliases.length=" + aliases.length + "; tupleLength=" + tupleLength
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new CacheableResultTransformer(
|
|
||||||
includeInTuple,
|
|
||||||
transformer.includeInTransform( aliases, tupleLength )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a CacheableResultTransformer that is used to transform
|
|
||||||
* tuples to a value(s) that can be cached.
|
|
||||||
*
|
|
||||||
* @param includeInTuple - array with the i-th element indicating
|
|
||||||
* whether the i-th expression returned by a query is
|
|
||||||
* included in the tuple; the number of true values equals
|
|
||||||
* the length of the tuple that will be transformed;
|
|
||||||
* must be non-null
|
|
||||||
*
|
|
||||||
* @return a CacheableResultTransformer that is used to transform
|
|
||||||
* tuples to a value(s) that can be cached.
|
|
||||||
*/
|
|
||||||
private static CacheableResultTransformer create(boolean[] includeInTuple) {
|
|
||||||
return new CacheableResultTransformer( includeInTuple, null );
|
|
||||||
}
|
|
||||||
|
|
||||||
private CacheableResultTransformer(boolean[] includeInTuple, boolean[] includeInTransform) {
|
|
||||||
if ( includeInTuple == null ) {
|
|
||||||
throw new IllegalArgumentException( "includeInTuple cannot be null" );
|
|
||||||
}
|
|
||||||
this.includeInTuple = includeInTuple;
|
|
||||||
tupleLength = ArrayHelper.countTrue( includeInTuple );
|
|
||||||
tupleSubsetLength = (
|
|
||||||
includeInTransform == null ?
|
|
||||||
tupleLength :
|
|
||||||
ArrayHelper.countTrue( includeInTransform )
|
|
||||||
);
|
|
||||||
if ( tupleSubsetLength == tupleLength ) {
|
|
||||||
includeInTransformIndex = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
includeInTransformIndex = new int[tupleSubsetLength];
|
|
||||||
for ( int i = 0, j = 0 ; i < includeInTransform.length ; i++ ) {
|
|
||||||
if ( includeInTransform[ i ] ) {
|
|
||||||
includeInTransformIndex[ j ] = i;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
|
||||||
if ( aliases != null && aliases.length != tupleLength ) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"aliases expected length is " + tupleLength +
|
|
||||||
"; actual length is " + aliases.length );
|
|
||||||
}
|
|
||||||
// really more correct to pass index( aliases.getClass(), aliases )
|
|
||||||
// as the 2nd arg to the following statement;
|
|
||||||
// passing null instead because it ends up being ignored.
|
|
||||||
return ACTUAL_TRANSFORMER.transformTuple( index( tuple.getClass(), tuple ), null );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-transforms, if necessary, a List of values previously
|
|
||||||
* transformed by this (or an equivalent) CacheableResultTransformer.
|
|
||||||
* Each element of the list is re-transformed in place (i.e, List
|
|
||||||
* elements are replaced with re-transformed values) and the original
|
|
||||||
* List is returned.
|
|
||||||
* <p/>
|
|
||||||
* If re-transformation is unnecessary, the original List is returned
|
|
||||||
* unchanged.
|
|
||||||
*
|
|
||||||
* @param transformedResults - results that were previously transformed
|
|
||||||
* @param aliases - the aliases that correspond to the untransformed tuple;
|
|
||||||
* @param transformer - the transformer for the re-transformation
|
|
||||||
* @param includeInTuple indicates the indexes of
|
|
||||||
*
|
|
||||||
* @return transformedResults, with each element re-transformed (if necessary)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings( {"unchecked"})
|
|
||||||
public List retransformResults(
|
|
||||||
List transformedResults,
|
|
||||||
String[] aliases,
|
|
||||||
ResultTransformer transformer,
|
|
||||||
boolean[] includeInTuple) {
|
|
||||||
if ( transformer == null ) {
|
|
||||||
throw new IllegalArgumentException( "transformer cannot be null" );
|
|
||||||
}
|
|
||||||
if ( ! this.equals( create( transformer, aliases, includeInTuple ) ) ) {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"this CacheableResultTransformer is inconsistent with specified arguments; cannot re-transform"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
boolean requiresRetransform = true;
|
|
||||||
String[] aliasesToUse = aliases == null ? null : index( ( aliases.getClass() ), aliases );
|
|
||||||
if ( transformer == ACTUAL_TRANSFORMER ) {
|
|
||||||
requiresRetransform = false;
|
|
||||||
}
|
|
||||||
else if ( transformer instanceof TupleSubsetResultTransformer ) {
|
|
||||||
requiresRetransform = ! ( ( TupleSubsetResultTransformer ) transformer ).isTransformedValueATupleElement(
|
|
||||||
aliasesToUse,
|
|
||||||
tupleLength
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( requiresRetransform ) {
|
|
||||||
for ( int i = 0 ; i < transformedResults.size() ; i++ ) {
|
|
||||||
Object[] tuple = ACTUAL_TRANSFORMER.untransformToTuple(
|
|
||||||
transformedResults.get( i ),
|
|
||||||
tupleSubsetLength == 1
|
|
||||||
);
|
|
||||||
transformedResults.set( i, transformer.transformTuple( tuple, aliasesToUse ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return transformedResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Untransforms, if necessary, a List of values previously
|
|
||||||
* transformed by this (or an equivalent) CacheableResultTransformer.
|
|
||||||
* Each element of the list is untransformed in place (i.e, List
|
|
||||||
* elements are replaced with untransformed values) and the original
|
|
||||||
* List is returned.
|
|
||||||
* <p/>
|
|
||||||
* If not unnecessary, the original List is returned
|
|
||||||
* unchanged.
|
|
||||||
* <p/>
|
|
||||||
* NOTE: If transformed values are a subset of the original
|
|
||||||
* tuple, then, on return, elements corresponding to
|
|
||||||
* excluded tuple elements will be null.
|
|
||||||
* @param results - results that were previously transformed
|
|
||||||
* @return results, with each element untransformed (if necessary)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings( {"unchecked"})
|
|
||||||
public List untransformToTuples(List results) {
|
|
||||||
if ( includeInTransformIndex == null ) {
|
|
||||||
results = ACTUAL_TRANSFORMER.untransformToTuples(
|
|
||||||
results,
|
|
||||||
tupleSubsetLength == 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for ( int i = 0 ; i < results.size() ; i++ ) {
|
|
||||||
Object[] tuple = ACTUAL_TRANSFORMER.untransformToTuple(
|
|
||||||
results.get( i ),
|
|
||||||
tupleSubsetLength == 1
|
|
||||||
);
|
|
||||||
results.set( i, unindex( tuple.getClass(), tuple ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type[] getCachedResultTypes(Type[] tupleResultTypes) {
|
|
||||||
return tupleLength != tupleSubsetLength
|
|
||||||
? index( tupleResultTypes.getClass(), tupleResultTypes )
|
|
||||||
: tupleResultTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List transformList(List list) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T[] index(Class<? extends T[]> clazz, T[] objects) {
|
|
||||||
T[] objectsIndexed = objects;
|
|
||||||
if ( objects != null &&
|
|
||||||
includeInTransformIndex != null &&
|
|
||||||
objects.length != tupleSubsetLength ) {
|
|
||||||
objectsIndexed = clazz.cast( Array.newInstance( clazz.getComponentType(), tupleSubsetLength ) );
|
|
||||||
for ( int i = 0 ; i < tupleSubsetLength; i++ ) {
|
|
||||||
objectsIndexed[ i ] = objects[ includeInTransformIndex[ i ] ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return objectsIndexed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T[] unindex(Class<? extends T[]> clazz, T[] objects) {
|
|
||||||
T[] objectsUnindexed = objects;
|
|
||||||
if ( objects != null &&
|
|
||||||
includeInTransformIndex != null &&
|
|
||||||
objects.length != tupleLength ) {
|
|
||||||
objectsUnindexed = clazz.cast( Array.newInstance( clazz.getComponentType(), tupleLength ) );
|
|
||||||
for ( int i = 0 ; i < tupleSubsetLength; i++ ) {
|
|
||||||
objectsUnindexed[ includeInTransformIndex[ i ] ] = objects[ i ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return objectsUnindexed;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if ( this == o ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ( o == null || getClass() != o.getClass() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheableResultTransformer that = ( CacheableResultTransformer ) o;
|
|
||||||
|
|
||||||
return tupleLength == that.tupleLength
|
|
||||||
&& tupleSubsetLength == that.tupleSubsetLength
|
|
||||||
&& Arrays.equals( includeInTuple, that.includeInTuple )
|
|
||||||
&& Arrays.equals( includeInTransformIndex, that.includeInTransformIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = tupleLength;
|
|
||||||
result = 31 * result + tupleSubsetLength;
|
|
||||||
result = 31 * result + ( includeInTuple != null ? Arrays.hashCode( includeInTuple ) : 0 );
|
|
||||||
result = 31 * result + ( includeInTransformIndex != null ? Arrays.hashCode( includeInTransformIndex ) : 0 );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
|
|
||||||
import static org.hibernate.internal.CoreLogging.messageLogger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 {
|
|
||||||
public static final DistinctResultTransformer INSTANCE = new DistinctResultTransformer();
|
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = messageLogger( DistinctResultTransformer.class );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper class to handle distincting
|
|
||||||
*/
|
|
||||||
private static final class Identity {
|
|
||||||
final Object entity;
|
|
||||||
|
|
||||||
private Identity(Object entity) {
|
|
||||||
this.entity = entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
return Identity.class.isInstance( other )
|
|
||||||
&& this.entity == ( (Identity) other ).entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return System.identityHashCode( entity );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disallow instantiation of DistinctResultTransformer.
|
|
||||||
*/
|
|
||||||
private DistinctResultTransformer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uniquely distinct each tuple row here.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List transformList(List list) {
|
|
||||||
List<Object> result = new ArrayList<>( list.size() );
|
|
||||||
Set<Identity> distinct = new HashSet<>();
|
|
||||||
for ( Object entity : list ) {
|
|
||||||
if ( distinct.add( new Identity( entity ) ) ) {
|
|
||||||
result.add( entity );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG.debugf( "Transformed: %s rows to: %s distinct results", list.size(), result.size() );
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization hook for ensuring singleton uniqueing.
|
|
||||||
*
|
|
||||||
* @return The singleton instance : {@link #INSTANCE}
|
|
||||||
*/
|
|
||||||
private Object readResolve() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class DistinctRootEntityResultTransformer implements TupleSubsetResultTransformer {
|
|
||||||
|
|
||||||
public static final DistinctRootEntityResultTransformer INSTANCE = new DistinctRootEntityResultTransformer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disallow instantiation of DistinctRootEntityResultTransformer.
|
|
||||||
*/
|
|
||||||
private DistinctRootEntityResultTransformer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simply delegates to {@link RootEntityResultTransformer#transformTuple}.
|
|
||||||
*
|
|
||||||
* @param tuple The tuple to transform
|
|
||||||
* @param aliases The tuple aliases
|
|
||||||
* @return The transformed tuple row.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
|
||||||
return RootEntityResultTransformer.INSTANCE.transformTuple( tuple, aliases );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simply delegates to {@link DistinctResultTransformer#transformList}.
|
|
||||||
*
|
|
||||||
* @param list The list to transform.
|
|
||||||
* @return The transformed List.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List transformList(List list) {
|
|
||||||
return DistinctResultTransformer.INSTANCE.transformList( list );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean[] includeInTransform(String[] aliases, int tupleLength) {
|
|
||||||
return RootEntityResultTransformer.INSTANCE.includeInTransform( aliases, tupleLength );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
|
|
||||||
return RootEntityResultTransformer.INSTANCE.isTransformedValueATupleElement( null, tupleLength );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization hook for ensuring singleton uniqueing.
|
|
||||||
*
|
|
||||||
* @return The singleton instance : {@link #INSTANCE}
|
|
||||||
*/
|
|
||||||
private Object readResolve() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ???
|
|
||||||
*
|
|
||||||
* @author max
|
|
||||||
*/
|
|
||||||
public class PassThroughResultTransformer extends BasicTransformerAdapter implements TupleSubsetResultTransformer {
|
|
||||||
|
|
||||||
public static final PassThroughResultTransformer INSTANCE = new PassThroughResultTransformer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disallow instantiation of PassThroughResultTransformer.
|
|
||||||
*/
|
|
||||||
private PassThroughResultTransformer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
|
||||||
return tuple.length==1 ? tuple[0] : tuple;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
|
|
||||||
return tupleLength == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean[] includeInTransform(String[] aliases, int tupleLength) {
|
|
||||||
boolean[] includeInTransformedResult = new boolean[tupleLength];
|
|
||||||
Arrays.fill( includeInTransformedResult, true );
|
|
||||||
return includeInTransformedResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package-protected */
|
|
||||||
List untransformToTuples(List results, boolean isSingleResult) {
|
|
||||||
// un-transform only if necessary; if transformed, do it in place;
|
|
||||||
if ( isSingleResult ) {
|
|
||||||
for ( int i = 0 ; i < results.size() ; i++ ) {
|
|
||||||
Object[] tuple = untransformToTuple( results.get( i ), isSingleResult);
|
|
||||||
results.set( i, tuple );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package-protected */
|
|
||||||
Object[] untransformToTuple(Object transformed, boolean isSingleResult ) {
|
|
||||||
return isSingleResult ? new Object[] { transformed } : ( Object[] ) transformed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization hook for ensuring singleton uniqueing.
|
|
||||||
*
|
|
||||||
* @return The singleton instance : {@link #INSTANCE}
|
|
||||||
*/
|
|
||||||
private Object readResolve() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
import org.hibernate.query.ResultListTransformer;
|
import org.hibernate.query.ResultListTransformer;
|
||||||
|
@ -20,11 +21,13 @@ import org.hibernate.query.TupleTransformer;
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*
|
*
|
||||||
* @deprecated ResultTransformer is no longer supported. It has been split
|
* @deprecated Use {@link TupleTransformer} and/or {@link ResultListTransformer}
|
||||||
* into {@link TupleTransformer} and {@link ResultListTransformer} to define
|
|
||||||
* functional interfaces.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public interface ResultTransformer extends TupleTransformer, ResultListTransformer, Serializable {
|
public interface ResultTransformer<T> extends TupleTransformer<T>, ResultListTransformer<T>, Serializable {
|
||||||
|
@Override
|
||||||
|
default List<T> transformList(List<T> resultList) {
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
|
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@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 Steve Ebersole
|
|
||||||
*/
|
|
||||||
public final class RootEntityResultTransformer extends BasicTransformerAdapter implements TupleSubsetResultTransformer {
|
|
||||||
|
|
||||||
public static final RootEntityResultTransformer INSTANCE = new RootEntityResultTransformer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disallow instantiation of RootEntityResultTransformer.
|
|
||||||
*/
|
|
||||||
private RootEntityResultTransformer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return just the root entity from the row tuple.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
|
||||||
return tuple[ tuple.length-1 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean[] includeInTransform(String[] aliases, int tupleLength) {
|
|
||||||
boolean[] includeInTransform;
|
|
||||||
if ( tupleLength == 1 ) {
|
|
||||||
includeInTransform = ArrayHelper.TRUE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
includeInTransform = new boolean[tupleLength];
|
|
||||||
includeInTransform[ tupleLength - 1 ] = true;
|
|
||||||
}
|
|
||||||
return includeInTransform;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization hook for ensuring singleton uniqueing.
|
|
||||||
*
|
|
||||||
* @return The singleton instance : {@link #INSTANCE}
|
|
||||||
*/
|
|
||||||
private Object readResolve() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,11 +7,12 @@
|
||||||
package org.hibernate.transform;
|
package org.hibernate.transform;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms each result row from a tuple into a {@link java.util.List} whose elements are each tuple value
|
* Transforms each result row from a tuple into a {@link List} whose elements are each tuple value
|
||||||
*/
|
*/
|
||||||
public class ToListResultTransformer extends BasicTransformerAdapter {
|
public class ToListResultTransformer implements ResultTransformer<List<Object>> {
|
||||||
public static final ToListResultTransformer INSTANCE = new ToListResultTransformer();
|
public static final ToListResultTransformer INSTANCE = new ToListResultTransformer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +22,7 @@ public class ToListResultTransformer extends BasicTransformerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public List<Object> transformTuple(Object[] tuple, String[] aliases) {
|
||||||
return Arrays.asList( tuple );
|
return Arrays.asList( tuple );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ final public class Transformers {
|
||||||
* Creates a ResultTransformer that will inject aliased values into
|
* Creates a ResultTransformer that will inject aliased values into
|
||||||
* instances of Class via property methods or fields.
|
* instances of Class via property methods or fields.
|
||||||
*/
|
*/
|
||||||
public static ResultTransformer aliasToBean(Class target) {
|
public static <T> ResultTransformer<T> aliasToBean(Class<T> target) {
|
||||||
return new AliasToBeanResultTransformer(target);
|
return new AliasToBeanResultTransformer<>(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.transform;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ResultTransformer that operates on "well-defined" and consistent
|
|
||||||
* subset of a tuple's elements.
|
|
||||||
*
|
|
||||||
* "Well-defined" means that:
|
|
||||||
* <ol>
|
|
||||||
* <li>
|
|
||||||
* the indexes of tuple elements accessed by a
|
|
||||||
* TupleSubsetResultTransformer depends only on the aliases
|
|
||||||
* and the number of elements in the tuple; i.e, it does
|
|
||||||
* not depend on the value of the tuple being transformed;
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* any tuple elements included in the transformed value are
|
|
||||||
* unmodified by the transformation;
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* transforming equivalent tuples with the same aliases multiple
|
|
||||||
* times results in transformed values that are equivalent;
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* the result of transforming the tuple subset (only those
|
|
||||||
* elements accessed by the transformer) using only the
|
|
||||||
* corresponding aliases is equivalent to transforming the
|
|
||||||
* full tuple with the full array of aliases;
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* the result of transforming a tuple with non-accessed tuple
|
|
||||||
* elements and corresponding aliases set to null
|
|
||||||
* is equivalent to transforming the full tuple with the
|
|
||||||
* full array of aliases;
|
|
||||||
* </li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public interface TupleSubsetResultTransformer extends ResultTransformer {
|
|
||||||
/**
|
|
||||||
* When a tuple is transformed, is the result a single element of the tuple?
|
|
||||||
*
|
|
||||||
* @param aliases - the aliases that correspond to the tuple
|
|
||||||
* @param tupleLength - the number of elements in the tuple
|
|
||||||
* @return true, if the transformed value is a single element of the tuple;
|
|
||||||
* false, otherwise.
|
|
||||||
*/
|
|
||||||
boolean isTransformedValueATupleElement(String[] aliases, int tupleLength);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array with the i-th element indicating whether the i-th
|
|
||||||
* element of the tuple is included in the transformed value.
|
|
||||||
*
|
|
||||||
* @param aliases - the aliases that correspond to the tuple
|
|
||||||
* @param tupleLength - the number of elements in the tuple
|
|
||||||
* @return array with the i-th element indicating whether the i-th
|
|
||||||
* element of the tuple is included in the transformed value.
|
|
||||||
*/
|
|
||||||
boolean[] includeInTransform(String[] aliases, int tupleLength);
|
|
||||||
}
|
|
|
@ -27,12 +27,12 @@ import org.hibernate.cache.spi.entry.CollectionCacheEntry;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
import org.hibernate.testing.DialectChecks;
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.RequiresDialectFeature;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.transform.ResultTransformer;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -808,14 +808,18 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
criteria.where( criteriaBuilder.equal( root.get( "id" ), testData.prod1Id ) );
|
criteria.where( criteriaBuilder.equal( root.get( "id" ), testData.prod1Id ) );
|
||||||
|
|
||||||
Product prod = session.createQuery( criteria )
|
Product prod = session.createQuery( criteria )
|
||||||
.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
|
.setResultTransformer(new ResultTransformer<Product>() {
|
||||||
|
@Override
|
||||||
|
public Product transformTuple(Object[] tuple, String[] aliases) {
|
||||||
|
return (Product) tuple[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public List<Product> transformList(List<Product> resultList) {
|
||||||
|
return ResultTransformer.super.transformList(resultList);
|
||||||
|
}
|
||||||
|
})
|
||||||
.uniqueResult();
|
.uniqueResult();
|
||||||
|
|
||||||
// Product prod = ( Product ) session.createCriteria( Product.class )
|
|
||||||
// .setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
|
|
||||||
// .add( Restrictions.eq( "id", testData.prod1Id ) )
|
|
||||||
// .uniqueResult();
|
|
||||||
|
|
||||||
assertNotNull( prod );
|
assertNotNull( prod );
|
||||||
assertEquals( "Incorrect Product.categories count for filter", 1, prod.getCategories().size() );
|
assertEquals( "Incorrect Product.categories count for filter", 1, prod.getCategories().size() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ import org.hibernate.query.sqm.tree.expression.SqmFunction;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||||
import org.hibernate.stat.QueryStatistics;
|
import org.hibernate.stat.QueryStatistics;
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
import org.hibernate.transform.ResultTransformer;
|
||||||
import org.hibernate.transform.Transformers;
|
import org.hibernate.transform.Transformers;
|
||||||
|
|
||||||
import org.hibernate.testing.DialectChecks;
|
import org.hibernate.testing.DialectChecks;
|
||||||
|
@ -3572,7 +3572,12 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
|
||||||
t = session.beginTransaction();
|
t = session.beginTransaction();
|
||||||
|
|
||||||
results = session.createQuery( "select a from Animal a, Animal b order by a.id" )
|
results = session.createQuery( "select a from Animal a, Animal b order by a.id" )
|
||||||
.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
|
.setResultTransformer(new ResultTransformer() {
|
||||||
|
@Override
|
||||||
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
|
return tuple[0];
|
||||||
|
}
|
||||||
|
})
|
||||||
.list();
|
.list();
|
||||||
assertEquals( "Incorrect result size", 2, results.size());
|
assertEquals( "Incorrect result size", 2, results.size());
|
||||||
assertTrue( "Incorrect return type", results.get( 0 ) instanceof Animal );
|
assertTrue( "Incorrect return type", results.get( 0 ) instanceof Animal );
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.orm.test.hqlfetchscroll;
|
package org.hibernate.orm.test.hqlfetchscroll;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -14,12 +15,12 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.hibernate.transform.ResultTransformer;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -43,7 +44,16 @@ public class HQLScrollFetchTest {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
List list = session.createQuery( QUERY )
|
List list = session.createQuery( QUERY )
|
||||||
.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
|
.setResultTransformer(new ResultTransformer() {
|
||||||
|
@Override
|
||||||
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
|
return tuple[0];
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public List transformList(List resultList) {
|
||||||
|
return Arrays.asList( new HashSet(resultList).toArray() );
|
||||||
|
}
|
||||||
|
})
|
||||||
.list();
|
.list();
|
||||||
assertResultFromAllUsers( list );
|
assertResultFromAllUsers( list );
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.orm.test.jpa.compliance.tck2_2;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
|
@ -17,9 +17,9 @@ import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
import org.hibernate.boot.MetadataSources;
|
import org.hibernate.boot.MetadataSources;
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.transform.ResultTransformer;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -47,7 +47,12 @@ public class QueryExecutionTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
assertThat( distinctResult.size(), CoreMatchers.is( 1 ) );
|
assertThat( distinctResult.size(), CoreMatchers.is( 1 ) );
|
||||||
|
|
||||||
final List distinctViaTransformerResult = session.createQuery( "select c from Customer c join fetch c.orders" )
|
final List distinctViaTransformerResult = session.createQuery( "select c from Customer c join fetch c.orders" )
|
||||||
.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE ).list();
|
.setResultTransformer(new ResultTransformer() {
|
||||||
|
@Override
|
||||||
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
|
return tuple[0];
|
||||||
|
}
|
||||||
|
}).list();
|
||||||
assertThat( distinctResult.size(), CoreMatchers.is( 1 ) );
|
assertThat( distinctResult.size(), CoreMatchers.is( 1 ) );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -66,12 +66,6 @@ public class ResultTransformerTest extends BaseCoreFunctionalTestCase {
|
||||||
// return only the PartnerA object from the query
|
// return only the PartnerA object from the query
|
||||||
return arg0[1];
|
return arg0[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public List transformList(List arg0)
|
|
||||||
{
|
|
||||||
return arg0;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
ScrollableResults sr = q.scroll();
|
ScrollableResults sr = q.scroll();
|
||||||
// HANA supports only ResultSet.TYPE_FORWARD_ONLY and
|
// HANA supports only ResultSet.TYPE_FORWARD_ONLY and
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.sql.hand.query;
|
package org.hibernate.test.sql.hand.query;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -36,8 +35,7 @@ import org.hibernate.orm.test.sql.hand.Speech;
|
||||||
import org.hibernate.orm.test.sql.hand.TextHolder;
|
import org.hibernate.orm.test.sql.hand.TextHolder;
|
||||||
import org.hibernate.query.NativeQuery;
|
import org.hibernate.query.NativeQuery;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
import org.hibernate.transform.BasicTransformerAdapter;
|
import org.hibernate.transform.ResultTransformer;
|
||||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
|
||||||
import org.hibernate.transform.Transformers;
|
import org.hibernate.transform.Transformers;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
|
@ -215,7 +213,12 @@ public class NativeSQLQueriesTest {
|
||||||
" left outer join EMPLOYMENT emp on org.ORGID = emp.EMPLOYER, ORGANIZATION org2" )
|
" left outer join EMPLOYMENT emp on org.ORGID = emp.EMPLOYER, ORGANIZATION org2" )
|
||||||
.addEntity("org", Organization.class)
|
.addEntity("org", Organization.class)
|
||||||
.addJoin("emp", "org.employments")
|
.addJoin("emp", "org.employments")
|
||||||
.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
|
.setResultTransformer(new ResultTransformer() {
|
||||||
|
@Override
|
||||||
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
|
return tuple[0];
|
||||||
|
}
|
||||||
|
})
|
||||||
.list();
|
.list();
|
||||||
assertEquals( l.size(), 2 );
|
assertEquals( l.size(), 2 );
|
||||||
}
|
}
|
||||||
|
@ -893,10 +896,9 @@ public class NativeSQLQueriesTest {
|
||||||
return on ? ( byte ) 1 : ( byte ) 0;
|
return on ? ( byte ) 1 : ( byte ) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( {"unchecked"})
|
private static class UpperCasedAliasToEntityMapResultTransformer implements ResultTransformer<Object> {
|
||||||
private static class UpperCasedAliasToEntityMapResultTransformer extends BasicTransformerAdapter implements Serializable {
|
|
||||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||||
Map result = new HashMap( tuple.length );
|
Map<String,Object> result = new HashMap<>( tuple.length );
|
||||||
for ( int i = 0; i < tuple.length; i++ ) {
|
for ( int i = 0; i < tuple.length; i++ ) {
|
||||||
String alias = aliases[i];
|
String alias = aliases[i];
|
||||||
if ( alias != null ) {
|
if ( alias != null ) {
|
||||||
|
|
Loading…
Reference in New Issue