HHH-16717 Type pollution fix for ExecutableList having to implement Comparable
This commit is contained in:
parent
c2c874ad65
commit
f6c10f0334
|
@ -10,11 +10,11 @@ import java.io.Serializable;
|
|||
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.Executable;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.ComparableExecutable;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.internal.FastSessionServices;
|
||||
|
@ -27,7 +27,7 @@ import org.hibernate.pretty.MessageHelper;
|
|||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public abstract class CollectionAction implements Executable, Serializable, Comparable<CollectionAction> {
|
||||
public abstract class CollectionAction implements ComparableExecutable {
|
||||
|
||||
private transient CollectionPersister persister;
|
||||
private transient EventSource session;
|
||||
|
@ -122,6 +122,16 @@ public abstract class CollectionAction implements Executable, Serializable, Comp
|
|||
return finalKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimarySortClassifier() {
|
||||
return collectionRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSecondarySortIndex() {
|
||||
return key;
|
||||
}
|
||||
|
||||
protected final EventSource getSession() {
|
||||
return session;
|
||||
}
|
||||
|
@ -145,15 +155,15 @@ public abstract class CollectionAction implements Executable, Serializable, Comp
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(CollectionAction action) {
|
||||
public int compareTo(ComparableExecutable o) {
|
||||
// sort first by role name
|
||||
final int roleComparison = collectionRole.compareTo( action.collectionRole );
|
||||
final int roleComparison = collectionRole.compareTo( o.getPrimarySortClassifier() );
|
||||
if ( roleComparison != 0 ) {
|
||||
return roleComparison;
|
||||
}
|
||||
else {
|
||||
//then by fk
|
||||
return persister.getAttributeMapping().getKeyDescriptor().compare( key, action.key );
|
||||
return persister.getAttributeMapping().getKeyDescriptor().compare( key, o.getSecondarySortIndex() );
|
||||
// //noinspection unchecked
|
||||
// final JavaType<Object> javaType = (JavaType<Object>) persister.getAttributeMapping().getKeyDescriptor().getJavaType();
|
||||
// return javaType.getComparator().compare( key, action.key );
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.io.Serializable;
|
|||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.Executable;
|
||||
import org.hibernate.engine.spi.ComparableExecutable;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.internal.FastSessionServices;
|
||||
|
@ -26,7 +26,7 @@ import org.hibernate.pretty.MessageHelper;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public abstract class EntityAction
|
||||
implements Comparable<EntityAction>, Executable, Serializable, AfterTransactionCompletionProcess {
|
||||
implements ComparableExecutable, AfterTransactionCompletionProcess {
|
||||
|
||||
private final String entityName;
|
||||
private final Object id;
|
||||
|
@ -151,13 +151,23 @@ public abstract class EntityAction
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(EntityAction action) {
|
||||
public int compareTo(ComparableExecutable o) {
|
||||
//sort first by entity name
|
||||
final int roleComparison = entityName.compareTo( action.getEntityName() );
|
||||
final int roleComparison = entityName.compareTo( o.getPrimarySortClassifier() );
|
||||
return roleComparison != 0
|
||||
? roleComparison
|
||||
//then by id
|
||||
: persister.getIdentifierType().compare( id, action.getId(), session.getSessionFactory() );
|
||||
: persister.getIdentifierType().compare( id, o.getSecondarySortIndex(), session.getSessionFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimarySortClassifier() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSecondarySortIndex() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -592,7 +592,7 @@ public class ActionQueue {
|
|||
* @param list The list of Executable elements to be performed
|
||||
*
|
||||
*/
|
||||
private <E extends Executable & Comparable<? super E> & Serializable> void executeActions(ExecutableList<E> list)
|
||||
private <E extends ComparableExecutable> void executeActions(ExecutableList<E> list)
|
||||
throws HibernateException {
|
||||
if ( list == null || list.isEmpty() ) {
|
||||
return;
|
||||
|
@ -601,7 +601,7 @@ public class ActionQueue {
|
|||
// 1) we explicitly iterate list here to perform Executable#execute()
|
||||
// 2) ExecutableList#getQuerySpaces also iterates the Executables to collect query spaces.
|
||||
try {
|
||||
for ( E e : list ) {
|
||||
for ( ComparableExecutable e : list ) {
|
||||
try {
|
||||
e.execute();
|
||||
}
|
||||
|
@ -1354,7 +1354,7 @@ public class ActionQueue {
|
|||
|
||||
}
|
||||
|
||||
private abstract static class ListProvider<T extends Executable & Comparable<? super T> & Serializable> {
|
||||
private abstract static class ListProvider<T extends ComparableExecutable> {
|
||||
abstract ExecutableList<T> get(ActionQueue instance);
|
||||
abstract ExecutableList<T> init(ActionQueue instance);
|
||||
ExecutableList<T> getOrInit( ActionQueue instance ) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.engine.spi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.action.spi.Executable;
|
||||
|
||||
/**
|
||||
* We frequently need the union type of Executable, Comparable of ComparableExecutable, Serializable;
|
||||
* this interface represents such union; this helps to simplify several generic signatures.
|
||||
* Secondarily, it helps to avoid triggering type pollution by not needing to typecheck
|
||||
* for a very specific Comparable type; we represent the common needs to resolve sorting
|
||||
* by exposing primary and secondary sorting attributes.
|
||||
*/
|
||||
public interface ComparableExecutable extends Executable, Comparable<ComparableExecutable>, Serializable {
|
||||
|
||||
/**
|
||||
* This affect sorting order of the executables, when sorting is enabled.
|
||||
* @return the primary sorting attribute; typically the entity name or collection role.
|
||||
*/
|
||||
String getPrimarySortClassifier();
|
||||
|
||||
/**
|
||||
* This affect sorting order of the executables, when sorting is enabled.
|
||||
* @return the secondary sorting attribute, applied when getPrimarySortClassifier
|
||||
* matches during a comparison; typically the entity key or collection key.
|
||||
*/
|
||||
Object getSecondarySortIndex();
|
||||
|
||||
}
|
|
@ -29,24 +29,20 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Anton Marsden
|
||||
*
|
||||
* @param <E> Intersection type describing {@link Executable} implementations
|
||||
*/
|
||||
public class ExecutableList<E extends Executable & Comparable<? super E> & Serializable>
|
||||
public class ExecutableList<E extends ComparableExecutable>
|
||||
implements Serializable, Iterable<E>, Externalizable {
|
||||
|
||||
public static final int INIT_QUEUE_LIST_SIZE = 5;
|
||||
|
||||
/**
|
||||
* Provides a sorting interface for {@link ExecutableList}.
|
||||
*
|
||||
* @param <E>
|
||||
*/
|
||||
public interface Sorter<E extends Executable> {
|
||||
public interface Sorter<ComparableExecutable> {
|
||||
/**
|
||||
* Sorts the list.
|
||||
*/
|
||||
void sort(List<E> l);
|
||||
void sort(List<ComparableExecutable> l);
|
||||
}
|
||||
|
||||
private final ArrayList<E> executables;
|
||||
|
@ -123,7 +119,7 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
*/
|
||||
public Set<Serializable> getQuerySpaces() {
|
||||
if ( querySpaces == null ) {
|
||||
for ( E e : executables ) {
|
||||
for ( ComparableExecutable e : executables ) {
|
||||
Serializable[] propertySpaces = e.getPropertySpaces();
|
||||
if ( propertySpaces != null && propertySpaces.length > 0 ) {
|
||||
if( querySpaces == null ) {
|
||||
|
@ -132,7 +128,7 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
Collections.addAll( querySpaces, propertySpaces );
|
||||
}
|
||||
}
|
||||
if( querySpaces == null ) {
|
||||
if ( querySpaces == null ) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
@ -153,10 +149,10 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
*
|
||||
* @return the entry that was removed
|
||||
*/
|
||||
public E remove(int index) {
|
||||
public ComparableExecutable remove(int index) {
|
||||
// removals are generally safe with regard to sorting...
|
||||
|
||||
final E e = executables.remove( index );
|
||||
final ComparableExecutable e = executables.remove( index );
|
||||
|
||||
// If the executable being removed defined query spaces we need to recalculate the overall query spaces for
|
||||
// this list. The problem is that we don't know how many other executable instances in the list also
|
||||
|
@ -187,7 +183,7 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
public void removeLastN(int n) {
|
||||
if ( n > 0 ) {
|
||||
int size = executables.size();
|
||||
for ( Executable e : executables.subList( size - n, size ) ) {
|
||||
for ( ComparableExecutable e : executables.subList( size - n, size ) ) {
|
||||
if ( e.getPropertySpaces() != null && e.getPropertySpaces().length > 0 ) {
|
||||
// querySpaces could now be incorrect
|
||||
querySpaces = null;
|
||||
|
@ -206,7 +202,7 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
* @return true if the object was added to the list
|
||||
*/
|
||||
public boolean add(E executable) {
|
||||
final E previousLast = sorter != null || executables.isEmpty() ? null : executables.get( executables.size() - 1 );
|
||||
final ComparableExecutable previousLast = sorter != null || executables.isEmpty() ? null : executables.get( executables.size() - 1 );
|
||||
boolean added = executables.add( executable );
|
||||
|
||||
if ( !added ) {
|
||||
|
@ -291,7 +287,7 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
oos.writeBoolean( sorted );
|
||||
|
||||
oos.writeInt( executables.size() );
|
||||
for ( E e : executables ) {
|
||||
for ( ComparableExecutable e : executables ) {
|
||||
oos.writeObject( e );
|
||||
}
|
||||
|
||||
|
@ -347,7 +343,7 @@ public class ExecutableList<E extends Executable & Comparable<? super E> & Seria
|
|||
* @param session The session with which to associate the {@code Executable}s
|
||||
*/
|
||||
public void afterDeserialize(EventSource session) {
|
||||
for ( E e : executables ) {
|
||||
for ( ComparableExecutable e : executables ) {
|
||||
e.afterDeserialize( session );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,8 @@ import java.util.Set;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.Executable;
|
||||
import org.hibernate.engine.spi.ComparableExecutable;
|
||||
import org.hibernate.engine.spi.ExecutableList;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
|
||||
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
||||
|
@ -38,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
public class NonSortedExecutableListTest {
|
||||
|
||||
// For testing, we need an Executable that is also Comparable and Serializable
|
||||
private static class AnExecutable implements Executable, Comparable<AnExecutable>, Serializable {
|
||||
private static class AnExecutable implements ComparableExecutable {
|
||||
|
||||
private final int n;
|
||||
private final Serializable[] spaces;
|
||||
|
@ -55,8 +54,9 @@ public class NonSortedExecutableListTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AnExecutable o) {
|
||||
return Integer.compare( n, o.n );
|
||||
public int compareTo(ComparableExecutable o) {
|
||||
Integer index = (Integer) o.getSecondarySortIndex();
|
||||
return Integer.compare( n, index.intValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,6 +106,15 @@ public class NonSortedExecutableListTest {
|
|||
return String.valueOf(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimarySortClassifier() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSecondarySortIndex() {
|
||||
return Integer.valueOf( n );
|
||||
}
|
||||
}
|
||||
|
||||
private ExecutableList<AnExecutable> actionList;
|
||||
|
@ -303,4 +312,3 @@ public class NonSortedExecutableListTest {
|
|||
assertThat( actionList ).element( 3 ).extracting( AnExecutable::wasAfterDeserializeCalled ).isEqualTo( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,8 @@ import java.util.Set;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.action.spi.AfterTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
|
||||
import org.hibernate.action.spi.Executable;
|
||||
import org.hibernate.engine.spi.ComparableExecutable;
|
||||
import org.hibernate.engine.spi.ExecutableList;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
|
||||
import org.hibernate.testing.orm.junit.BaseUnitTest;
|
||||
|
@ -37,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
public class SortedExecutableListTest {
|
||||
|
||||
// For testing, we need an Executable that is also Comparable and Serializable
|
||||
private static class AnExecutable implements Executable, Comparable<AnExecutable>, Serializable {
|
||||
private static class AnExecutable implements ComparableExecutable {
|
||||
|
||||
private final int n;
|
||||
private Serializable[] spaces;
|
||||
|
@ -53,8 +52,9 @@ public class SortedExecutableListTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AnExecutable o) {
|
||||
return Integer.compare( n, o.n );
|
||||
public int compareTo(ComparableExecutable o) {
|
||||
Integer index = (Integer) o.getSecondarySortIndex();
|
||||
return Integer.compare( n, index.intValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,9 +101,18 @@ public class SortedExecutableListTest {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
return String.valueOf(n);
|
||||
return String.valueOf( n );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrimarySortClassifier() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSecondarySortIndex() {
|
||||
return Integer.valueOf( n );
|
||||
}
|
||||
}
|
||||
|
||||
private ExecutableList<AnExecutable> actionList;
|
||||
|
@ -288,4 +297,3 @@ public class SortedExecutableListTest {
|
|||
assertThat( actionList ).element( 3 ).isEqualTo( action4 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue