HHH-7736 join subclass support
This commit is contained in:
parent
ecf0114a63
commit
0671761c14
|
@ -56,7 +56,7 @@ public class SchemaModificationHelper {
|
|||
}
|
||||
|
||||
public static Column getSingleColumn(AttributeBinding attributeBinding) {
|
||||
if ( !( attributeBinding instanceof SingularAttributeBinding ) ) {
|
||||
if ( !( attributeBinding.getAttribute().isSingular() ) ) {
|
||||
// TODO verify that's correct (HF)
|
||||
return null;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class SchemaModificationHelper {
|
|||
RelationalValueBinding valueBinding = basicAttributeBinding.getRelationalValueBindings().get( 0 );
|
||||
Value value = valueBinding.getValue();
|
||||
|
||||
if ( !( value instanceof Column ) ) {
|
||||
if ( valueBinding.isDerived() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ public class LoadQueryInfluencers implements Serializable {
|
|||
return enabledFetchProfileNames != null && !enabledFetchProfileNames.isEmpty();
|
||||
}
|
||||
|
||||
public Set getEnabledFetchProfileNames() {
|
||||
public Set<String> getEnabledFetchProfileNames() {
|
||||
return enabledFetchProfileNames;
|
||||
}
|
||||
|
||||
|
|
|
@ -163,6 +163,21 @@ public final class ArrayHelper {
|
|||
return list;
|
||||
}
|
||||
|
||||
public static <T> T[] reverse(T[] objects) {
|
||||
return reverse( objects, objects.length );
|
||||
}
|
||||
|
||||
public static <T> T[] reverse(T[] objects, int n) {
|
||||
final int size = objects.length;
|
||||
final T[] temp = (T[]) Array.newInstance( objects.getClass().getComponentType(), size );
|
||||
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
temp[i] = objects[n - i - 1];
|
||||
}
|
||||
System.arraycopy( objects, n, temp, n, size - n );
|
||||
return temp;
|
||||
}
|
||||
|
||||
public static String[] join(String[] x, String[] y) {
|
||||
String[] result = new String[ x.length + y.length ];
|
||||
System.arraycopy( x, 0, result, 0, x.length );
|
||||
|
@ -181,7 +196,12 @@ public final class ArrayHelper {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean[] join(boolean[] x, boolean[] y) {
|
||||
boolean[] result = new boolean[ x.length + y.length ];
|
||||
System.arraycopy( x, 0, result, 0, x.length );
|
||||
System.arraycopy( y, 0, result, x.length, y.length );
|
||||
return result;
|
||||
}
|
||||
public static int[] join(int[] x, int[] y) {
|
||||
int[] result = new int[ x.length + y.length ];
|
||||
System.arraycopy( x, 0, result, 0, x.length );
|
||||
|
|
|
@ -457,7 +457,7 @@ public class AttributeBuilder {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
if ( attributeBinding.getAttribute().isSingular() ) {
|
||||
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
|
||||
final PersistentAttributeType jpaAttributeType;
|
||||
|
|
|
@ -531,7 +531,7 @@ public class Binder {
|
|||
// ensure version is non-nullable
|
||||
for ( RelationalValueBinding valueBinding : version.getVersioningAttributeBinding()
|
||||
.getRelationalValueBindings() ) {
|
||||
if ( valueBinding.getValue() instanceof Column ) {
|
||||
if ( !valueBinding.isDerived() ) {
|
||||
( (Column) valueBinding.getValue() ).setNullable( false );
|
||||
}
|
||||
}
|
||||
|
@ -2283,7 +2283,7 @@ public class Binder {
|
|||
primaryKey.addColumn( foreignKeyColumn );
|
||||
}
|
||||
for ( final RelationalValueBinding elementValueBinding : elementBinding.getRelationalValueBindings() ) {
|
||||
if ( elementValueBinding.getValue() instanceof Column && !elementValueBinding.isNullable() ) {
|
||||
if ( !elementValueBinding.isDerived() && !elementValueBinding.isNullable() ) {
|
||||
primaryKey.addColumn( (Column) elementValueBinding.getValue() );
|
||||
}
|
||||
}
|
||||
|
@ -3023,7 +3023,7 @@ public class Binder {
|
|||
primaryKey.addColumn( foreignKeyColumn );
|
||||
}
|
||||
for ( RelationalValueBinding relationalValueBinding : indexBinding.getRelationalValueBindings() ) {
|
||||
if ( relationalValueBinding.getValue() instanceof Column ) {
|
||||
if ( !relationalValueBinding.isDerived() ) {
|
||||
primaryKey.addColumn( (Column) relationalValueBinding.getValue() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -367,16 +367,16 @@ public class BindHelper {
|
|||
|
||||
private static AttributeBinding getRecursiveAttributeBinding(
|
||||
EntityBinding entityBinding, String propertyPath) {
|
||||
Iterable<AttributeBinding> attributeBindings
|
||||
= entityBinding.getAttributeBindingClosure();
|
||||
StringTokenizer st = new StringTokenizer( propertyPath, "." );
|
||||
// Iterable<AttributeBinding> attributeBindings
|
||||
// = entityBinding.getAttributeBindingClosure();
|
||||
// StringTokenizer st = new StringTokenizer( propertyPath, "." );
|
||||
AttributeBinding attributeBinding = null;
|
||||
while ( st.hasMoreElements() ) {
|
||||
String element = st.nextToken();
|
||||
for ( AttributeBinding binding : attributeBindings ) {
|
||||
|
||||
}
|
||||
}
|
||||
// while ( st.hasMoreElements() ) {
|
||||
// String element = st.nextToken();
|
||||
// for ( AttributeBinding binding : attributeBindings ) {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
return attributeBinding;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. 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 Inc.
|
||||
*
|
||||
* 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.metamodel.internal.source.hbm;
|
||||
|
||||
import org.hibernate.metamodel.spi.source.ColumnSource;
|
||||
import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class PrimaryKeyJoinColumnSourceImpl implements PrimaryKeyJoinColumnSource {
|
||||
private final ColumnSource columnSource;
|
||||
|
||||
public PrimaryKeyJoinColumnSourceImpl(ColumnSource relationalValueSource) {
|
||||
this.columnSource = relationalValueSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
return columnSource.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferencedColumnName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnDefinition() {
|
||||
return columnSource.getSqlType();
|
||||
}
|
||||
}
|
|
@ -23,14 +23,19 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.internal.source.hbm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.jaxb.spi.hbm.EntityElement;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbColumnElement;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbJoinedSubclassElement;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbKeyElement;
|
||||
import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement;
|
||||
import org.hibernate.jaxb.spi.hbm.TableInformationSource;
|
||||
import org.hibernate.metamodel.spi.source.ColumnSource;
|
||||
import org.hibernate.metamodel.spi.source.EntitySource;
|
||||
import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource;
|
||||
import org.hibernate.metamodel.spi.source.RelationalValueSource;
|
||||
import org.hibernate.metamodel.spi.source.SubclassEntitySource;
|
||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
||||
|
||||
|
@ -40,7 +45,9 @@ import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
|||
public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implements SubclassEntitySource {
|
||||
private final EntitySource container;
|
||||
private final TableSpecificationSource primaryTable;
|
||||
|
||||
private final boolean isJoinedSubclass;
|
||||
private final JaxbKeyElement key;
|
||||
private final List<PrimaryKeyJoinColumnSource> primaryKeyJoinColumnSources;
|
||||
protected SubclassEntitySourceImpl(
|
||||
MappingDocument sourceMappingDocument,
|
||||
EntityElement entityElement,
|
||||
|
@ -50,6 +57,45 @@ public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implement
|
|||
this.primaryTable = TableInformationSource.class.isInstance( entityElement )
|
||||
? Helper.createTableSource( sourceMappingDocument(), (TableInformationSource) entityElement, this )
|
||||
: null;
|
||||
this.isJoinedSubclass = JaxbJoinedSubclassElement.class.isInstance( entityElement );
|
||||
this.key = isJoinedSubclass? ( (JaxbJoinedSubclassElement) entityElement() ).getKey() : null;
|
||||
if ( isJoinedSubclass ) {
|
||||
List<RelationalValueSource> valueSources = Helper.buildValueSources(
|
||||
sourceMappingDocument(),
|
||||
new Helper.ValueSourcesAdapter() {
|
||||
@Override
|
||||
public boolean isIncludedInInsertByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInUpdateByDefault() {
|
||||
return Helper.getValue( key.isUpdate(), true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnAttribute() {
|
||||
return key.getColumnAttribute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JaxbColumnElement> getColumn() {
|
||||
return key.getColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForceNotNull() {
|
||||
return Helper.getValue( key.isNotNull(), false );
|
||||
}
|
||||
}
|
||||
);
|
||||
this.primaryKeyJoinColumnSources = new ArrayList<PrimaryKeyJoinColumnSource>( valueSources.size() );
|
||||
for(final RelationalValueSource valueSource : valueSources){
|
||||
primaryKeyJoinColumnSources.add( new PrimaryKeyJoinColumnSourceImpl( ColumnSource.class.cast( valueSource ) ) );
|
||||
}
|
||||
} else {
|
||||
this.primaryKeyJoinColumnSources = null;
|
||||
}
|
||||
|
||||
afterInstantiation();
|
||||
}
|
||||
|
@ -73,14 +119,14 @@ public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implement
|
|||
|
||||
@Override
|
||||
public String getJoinedForeignKeyName() {
|
||||
if ( JaxbJoinedSubclassElement.class.isInstance( entityElement() ) ) {
|
||||
return ( (JaxbJoinedSubclassElement) entityElement() ).getKey().getForeignKey();
|
||||
if ( isJoinedSubclass ) {
|
||||
return key.getForeignKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PrimaryKeyJoinColumnSource> getPrimaryKeyJoinColumnSources() {
|
||||
return null;
|
||||
return primaryKeyJoinColumnSources;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
|||
@Override
|
||||
public AttributeBinding locateAttributeBinding(List<Value> values) {
|
||||
for ( AttributeBinding attributeBinding : attributeBindingMapInternal().values() ) {
|
||||
if ( !SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
if ( !attributeBinding.getAttribute().isSingular() ) {
|
||||
continue;
|
||||
}
|
||||
SingularAttributeBinding basicAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||
|
|
|
@ -24,18 +24,16 @@
|
|||
package org.hibernate.metamodel.spi.binding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
|
@ -158,7 +156,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
}
|
||||
|
||||
public boolean isPolymorphic() {
|
||||
return superEntityBinding != null ||
|
||||
return !isRoot() ||
|
||||
hierarchyDetails.getEntityDiscriminator() != null ||
|
||||
!subEntityBindings.isEmpty();
|
||||
}
|
||||
|
@ -167,71 +165,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
return !subEntityBindings.isEmpty();
|
||||
}
|
||||
|
||||
public int getSubEntityBindingClosureSpan() {
|
||||
int n = subEntityBindings.size();
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
n += subEntityBinding.getSubEntityBindingClosureSpan();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* used for testing */
|
||||
public Iterable<EntityBinding> getDirectSubEntityBindings() {
|
||||
return subEntityBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sub-EntityBinding objects in a special 'order', most derived subclasses
|
||||
* first. Specifically, the sub-entity bindings follow a depth-first,
|
||||
* post-order traversal
|
||||
*
|
||||
* Note that the returned value excludes this entity binding.
|
||||
*
|
||||
* @return sub-entity bindings ordered by those entity bindings that are most derived.
|
||||
*/
|
||||
public Iterable<EntityBinding> getPostOrderSubEntityBindingClosure() {
|
||||
// TODO: why this order?
|
||||
List<Iterable<EntityBinding>> subclassIterables = new ArrayList<Iterable<EntityBinding>>( subEntityBindings.size() + 1 );
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
Iterable<EntityBinding> subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||
if ( subSubEntityBindings.iterator().hasNext() ) {
|
||||
subclassIterables.add( subSubEntityBindings );
|
||||
}
|
||||
}
|
||||
if ( !subEntityBindings.isEmpty() ) {
|
||||
subclassIterables.add( subEntityBindings );
|
||||
}
|
||||
return new JoinedIterable<EntityBinding>( subclassIterables );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sub-EntityBinding ordered as a depth-first,
|
||||
* pre-order traversal (a subclass precedes its own subclasses).
|
||||
*
|
||||
* Note that the returned value specifically excludes this entity binding.
|
||||
*
|
||||
* @return sub-entity bindings ordered as a depth-first,
|
||||
* pre-order traversal
|
||||
*/
|
||||
public Iterable<EntityBinding> getPreOrderSubEntityBindingClosure() {
|
||||
return getPreOrderSubEntityBindingClosure( false );
|
||||
}
|
||||
|
||||
private Iterable<EntityBinding> getPreOrderSubEntityBindingClosure(boolean includeThis) {
|
||||
List<Iterable<EntityBinding>> iterables = new ArrayList<Iterable<EntityBinding>>();
|
||||
if ( includeThis ) {
|
||||
iterables.add( java.util.Collections.singletonList( this ) );
|
||||
}
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
Iterable<EntityBinding> subSubEntityBindingClosure = subEntityBinding.getPreOrderSubEntityBindingClosure(
|
||||
true
|
||||
);
|
||||
if ( subSubEntityBindingClosure.iterator().hasNext() ) {
|
||||
iterables.add( subSubEntityBindingClosure );
|
||||
}
|
||||
}
|
||||
return new JoinedIterable<EntityBinding>( iterables );
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
|
@ -317,79 +251,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
public void addSecondaryTable(SecondaryTable secondaryTable) {
|
||||
secondaryTables.put( secondaryTable.getSecondaryTableReference().getLogicalName().getText(), secondaryTable );
|
||||
}
|
||||
|
||||
public int getSecondaryTableClosureSpan() {
|
||||
return superEntityBinding != null ?
|
||||
superEntityBinding.getSecondaryTableClosureSpan() + secondaryTables.size() :
|
||||
secondaryTables.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute bindings defined on this class, including the
|
||||
* identifier attribute binding and attribute bindings defined
|
||||
* as part of a join.
|
||||
*
|
||||
* @return The attribute bindings.
|
||||
*/
|
||||
public Iterable<SecondaryTable> getSecondaryTableClosure() {
|
||||
Iterable<SecondaryTable> iterable;
|
||||
if ( superEntityBinding != null ) {
|
||||
List<Iterable<SecondaryTable>> iterables = new ArrayList<Iterable<SecondaryTable>>( 2 );
|
||||
iterables.add( superEntityBinding.getSecondaryTableClosure() );
|
||||
iterables.add( secondaryTables.values() );
|
||||
iterable = new JoinedIterable<SecondaryTable>( iterables );
|
||||
}
|
||||
else {
|
||||
iterable = secondaryTables.values();
|
||||
}
|
||||
return iterable;
|
||||
}
|
||||
|
||||
private Iterable<SecondaryTable> getSubclassSecondaryTables() {
|
||||
List<Iterable<SecondaryTable>> iterables = new ArrayList<Iterable<SecondaryTable>>( subEntityBindings.size() );
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
iterables.add( subEntityBinding.secondaryTables.values() );
|
||||
if ( ! subEntityBinding.subEntityBindings.isEmpty() ) {
|
||||
iterables.add( subEntityBinding.getSubclassSecondaryTables() );
|
||||
}
|
||||
}
|
||||
return new JoinedIterable<SecondaryTable>( iterables );
|
||||
}
|
||||
|
||||
public Iterable<SecondaryTable> getSubclassSecondaryTableClosure() {
|
||||
Iterable<SecondaryTable> iterable;
|
||||
if ( ! subEntityBindings.isEmpty() ) {
|
||||
List<Iterable<SecondaryTable>> iterables = new ArrayList<Iterable<SecondaryTable>>( 2 );
|
||||
iterables.add( getSecondaryTableClosure() );
|
||||
iterables.add( getSubclassSecondaryTables() );
|
||||
iterable = new JoinedIterable<SecondaryTable>( iterables );
|
||||
}
|
||||
else {
|
||||
iterable = getSecondaryTableClosure();
|
||||
}
|
||||
return iterable;
|
||||
}
|
||||
|
||||
public boolean isClassOrSuperclassSecondaryTable(SecondaryTable secondaryTable) {
|
||||
String secondaryTableName = secondaryTable.getSecondaryTableReference().getLogicalName().getText();
|
||||
return secondaryTables.containsKey( secondaryTableName ) ||
|
||||
( superEntityBinding != null && superEntityBinding.isClassOrSuperclassSecondaryTable( secondaryTable ) );
|
||||
}
|
||||
|
||||
public int getSecondaryTableNumber(SingularAttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getRelationalValueBindings().isEmpty() ) {
|
||||
return 0;
|
||||
}
|
||||
int result=1;
|
||||
Value value = attributeBinding.getRelationalValueBindings().get( 0 ).getValue();
|
||||
TableSpecification table = value.getTable();
|
||||
for ( SecondaryTable secondaryTable : getSubclassSecondaryTableClosure() ) {
|
||||
if ( secondaryTable.getSecondaryTableReference() == table ) {
|
||||
return result;
|
||||
}
|
||||
result++;
|
||||
}
|
||||
return 0;
|
||||
public Map<String, SecondaryTable> getSecondaryTables() {
|
||||
return secondaryTables;
|
||||
}
|
||||
|
||||
|
||||
|
@ -669,28 +532,57 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
return binding;
|
||||
}
|
||||
|
||||
public AttributeBinding locateAttributeBindingByPath(String path) {
|
||||
if ( path == null ) {
|
||||
throw new IllegalArgumentException( "path must be non-null." );
|
||||
}
|
||||
final String pathDelimiter = "\\.";
|
||||
String[] tokens = path.split( pathDelimiter );
|
||||
AttributeBinding attributeBinding = locateAttributeBinding( tokens[ 0 ] );
|
||||
if ( attributeBinding == null ) {
|
||||
return superEntityBinding == null ? null : superEntityBinding.locateAttributeBindingByPath( path );
|
||||
}
|
||||
for ( int i = 1 ; i < tokens.length && attributeBinding != null ; i++ ) {
|
||||
if ( ! attributeBinding.getAttribute().isSingular() ||
|
||||
! ( (SingularAttribute) attributeBinding.getAttribute() ).getSingularAttributeType().isAggregate() ) {
|
||||
// TODO: improve this message!!!
|
||||
throw new MappingException( "improve this!!!" );
|
||||
}
|
||||
AttributeBindingContainer attributeBindingContainer = (AttributeBindingContainer) attributeBinding;
|
||||
attributeBinding = attributeBindingContainer.locateAttributeBinding( tokens[ i ] );
|
||||
}
|
||||
return attributeBinding;
|
||||
|
||||
public void setJpaCallbackClasses(List<JpaCallbackSource> jpaCallbackClasses) {
|
||||
this.jpaCallbackClasses = jpaCallbackClasses;
|
||||
}
|
||||
|
||||
public Iterable<JpaCallbackSource> getJpaCallbackClasses() {
|
||||
return jpaCallbackClasses;
|
||||
}
|
||||
//--------------------------
|
||||
//meta methods for persister , to improve performance, these methods below should really be replaced as ValueHolder
|
||||
//and only be called in persister -- after build MetadataImpl
|
||||
|
||||
|
||||
public TableSpecification[] getTableClosure() {
|
||||
if ( isRoot() ) {
|
||||
return new TableSpecification[] { getPrimaryTable() };
|
||||
}
|
||||
return ArrayHelper.join( superEntityBinding.getTableClosure(), getPrimaryTable() );
|
||||
}
|
||||
|
||||
public EntityBinding[] getEntityBindingClosure() {
|
||||
if ( isRoot() ) {
|
||||
return new EntityBinding[] { this };
|
||||
}
|
||||
return ArrayHelper.join( superEntityBinding.getEntityBindingClosure(), this );
|
||||
}
|
||||
|
||||
public int getSecondaryTableClosureSpan() {
|
||||
return isRoot() ? secondaryTables.size() : superEntityBinding.getSecondaryTableClosureSpan() + secondaryTables.size();
|
||||
}
|
||||
|
||||
public SecondaryTable[] getSecondaryTableClosure() {
|
||||
if ( isRoot() ) {
|
||||
return secondaryTables.values().toArray( new SecondaryTable[secondaryTables.size()] );
|
||||
}
|
||||
else {
|
||||
return ArrayHelper.join(
|
||||
superEntityBinding.getSecondaryTableClosure(),
|
||||
secondaryTables.values().toArray( new SecondaryTable[secondaryTables.size()] )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getSynchronizedTableNameClosure() {
|
||||
if ( isRoot() ) {
|
||||
return getSynchronizedTableNames();
|
||||
}
|
||||
return ArrayHelper.join( superEntityBinding.getSynchronizedTableNameClosure(), getSynchronizedTableNames() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the number of attribute bindings defined on this class, including the
|
||||
* identifier attribute binding and attribute bindings defined
|
||||
|
@ -700,9 +592,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
*/
|
||||
public int getAttributeBindingClosureSpan() {
|
||||
// TODO: update account for join attribute bindings
|
||||
return superEntityBinding != null ?
|
||||
superEntityBinding.getAttributeBindingClosureSpan() + attributeBindingMap.size() :
|
||||
attributeBindingMap.size();
|
||||
return isRoot() ? getNonIdAttributeBindingClosure().length :
|
||||
superEntityBinding.getAttributeBindingClosureSpan() + getNonIdAttributeBindingClosure().length;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -712,19 +603,127 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
*
|
||||
* @return The attribute bindings.
|
||||
*/
|
||||
public Iterable<AttributeBinding> getAttributeBindingClosure() {
|
||||
public AttributeBinding[] getAttributeBindingClosure() {
|
||||
// TODO: update size to account for joins
|
||||
Iterable<AttributeBinding> iterable;
|
||||
if ( superEntityBinding != null ) {
|
||||
List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>( 2 );
|
||||
iterables.add( superEntityBinding.getAttributeBindingClosure() );
|
||||
iterables.add( attributeBindings() );
|
||||
iterable = new JoinedIterable<AttributeBinding>( iterables );
|
||||
if ( isRoot() ) {
|
||||
return getNonIdAttributeBindingClosure();
|
||||
}
|
||||
else {
|
||||
iterable = attributeBindings();
|
||||
return ArrayHelper.join(
|
||||
superEntityBinding.getAttributeBindingClosure(),
|
||||
getNonIdAttributeBindingClosure()
|
||||
);
|
||||
}
|
||||
return iterable;
|
||||
}
|
||||
|
||||
private AttributeBinding[] getNonIdAttributeBindingClosure() {
|
||||
List<AttributeBinding> list = new ArrayList<AttributeBinding>();
|
||||
attributeBindings();
|
||||
for ( final AttributeBinding ab : attributeBindings() ) {
|
||||
if(ab instanceof CompositeAttributeBinding){
|
||||
|
||||
}
|
||||
boolean isId = getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( ab );
|
||||
if ( !isId ) {
|
||||
list.add( ab );
|
||||
}
|
||||
}
|
||||
return list.toArray( new AttributeBinding[list.size()] );
|
||||
|
||||
}
|
||||
|
||||
/* used for testing */
|
||||
public List<EntityBinding> getDirectSubEntityBindings() {
|
||||
return subEntityBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sub-EntityBinding objects in a special 'order', most derived subclasses
|
||||
* first. Specifically, the sub-entity bindings follow a depth-first,
|
||||
* post-order traversal
|
||||
*
|
||||
* Note that the returned value excludes this entity binding.
|
||||
*
|
||||
* @return sub-entity bindings ordered by those entity bindings that are most derived.
|
||||
*/
|
||||
public EntityBinding[] getPostOrderSubEntityBindingClosure() {
|
||||
EntityBinding[] results = new EntityBinding[0];
|
||||
if ( subEntityBindings.isEmpty() ) {
|
||||
return results;
|
||||
}
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
EntityBinding[] subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||
results = ArrayHelper.join( results, subSubEntityBindings );
|
||||
}
|
||||
if ( !subEntityBindings.isEmpty() ) {
|
||||
results = ArrayHelper.join( results, subEntityBindings.toArray( new EntityBinding[subEntityBindings.size()] ) );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sub-EntityBinding ordered as a depth-first,
|
||||
* pre-order traversal (a subclass precedes its own subclasses).
|
||||
*
|
||||
* Note that the returned value specifically excludes this entity binding.
|
||||
*
|
||||
* @return sub-entity bindings ordered as a depth-first,
|
||||
* pre-order traversal
|
||||
*/
|
||||
public EntityBinding[] getPreOrderSubEntityBindingClosure() {
|
||||
return getPreOrderSubEntityBindingClosure( false, new EntityBinding[0] );
|
||||
}
|
||||
|
||||
private EntityBinding[] getPreOrderSubEntityBindingClosure(boolean includeThis, EntityBinding[] results) {
|
||||
if ( includeThis ) {
|
||||
results = ArrayHelper.join( results, this );
|
||||
}
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
results = subEntityBinding.getPreOrderSubEntityBindingClosure(
|
||||
true, results
|
||||
);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public TableSpecification[] getPreOrderSubTableClosure(){
|
||||
EntityBinding[] subEntityBindings = getPreOrderSubEntityBindingClosure();
|
||||
TableSpecification [] tables = new TableSpecification[subEntityBindings.length];
|
||||
for(int i=0;i<subEntityBindings.length;i++){
|
||||
tables[i] = subEntityBindings[i].getPrimaryTable();
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
|
||||
public SecondaryTable[] getSubEntitySecondaryTables() {
|
||||
SecondaryTable[] results = new SecondaryTable[0];
|
||||
for ( EntityBinding eb : getPreOrderSubEntityBindingClosure() ) {
|
||||
Collection<SecondaryTable> sts = eb.getSecondaryTables().values();
|
||||
int size = sts.size();
|
||||
if ( size == 0 ) {
|
||||
continue;
|
||||
}
|
||||
results = ArrayHelper.join( results, sts.toArray( new SecondaryTable[size] ) );
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
public SecondaryTable[] getEntitiesSecondaryTableClosure() {
|
||||
if ( ! subEntityBindings.isEmpty() ) {
|
||||
return ArrayHelper.join( getSecondaryTableClosure(), getSubEntitySecondaryTables() );
|
||||
}
|
||||
else {
|
||||
return getSecondaryTableClosure();
|
||||
}
|
||||
}
|
||||
|
||||
public int getSubEntityBindingClosureSpan() {
|
||||
int n = subEntityBindings.size();
|
||||
for ( final EntityBinding seb : subEntityBindings ) {
|
||||
n += seb.getSubEntityBindingClosureSpan();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -732,37 +731,42 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
|||
* sub-EntityBinding, starting from the root of the hierarchy; includes
|
||||
* the identifier and attribute bindings defined as part of a join.
|
||||
*/
|
||||
public Iterable<AttributeBinding> getSubEntityAttributeBindingClosure() {
|
||||
List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>();
|
||||
iterables.add( getAttributeBindingClosure() );
|
||||
public AttributeBinding[] getEntitiesAttributeBindingClosure() {
|
||||
AttributeBinding[] results = getAttributeBindingClosure();
|
||||
|
||||
for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) {
|
||||
// only add attribute bindings declared for the subEntityBinding
|
||||
iterables.add( subEntityBinding.attributeBindings() );
|
||||
|
||||
results = ArrayHelper.join(
|
||||
results,
|
||||
subEntityBinding.getNonIdAttributeBindingClosure()
|
||||
);
|
||||
// TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here
|
||||
}
|
||||
return new JoinedIterable<AttributeBinding>( iterables );
|
||||
return results;
|
||||
}
|
||||
|
||||
public Iterator<TableSpecification> getTableClosureIterator() {
|
||||
if ( superEntityBinding == null ) {
|
||||
return new SingletonIterator<TableSpecification>( getPrimaryTable() );
|
||||
|
||||
public boolean isClassOrSuperclassSecondaryTable(SecondaryTable secondaryTable) {
|
||||
String secondaryTableName = secondaryTable.getSecondaryTableReference().getLogicalName().getText();
|
||||
return secondaryTables.containsKey( secondaryTableName ) ||
|
||||
( superEntityBinding != null && superEntityBinding.isClassOrSuperclassSecondaryTable( secondaryTable ) );
|
||||
}
|
||||
|
||||
public int getSecondaryTableNumber(SingularAttributeBinding attributeBinding) {
|
||||
if ( attributeBinding.getRelationalValueBindings().isEmpty() ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return new JoinedIterator<TableSpecification>(
|
||||
superEntityBinding.getTableClosureIterator(),
|
||||
new SingletonIterator<TableSpecification>( getPrimaryTable() )
|
||||
);
|
||||
int result=1;
|
||||
Value value = attributeBinding.getRelationalValueBindings().get( 0 ).getValue();
|
||||
TableSpecification table = value.getTable();
|
||||
for ( SecondaryTable secondaryTable : getEntitiesSecondaryTableClosure() ) {
|
||||
if ( secondaryTable.getSecondaryTableReference() == table ) {
|
||||
return result;
|
||||
}
|
||||
result++;
|
||||
}
|
||||
}
|
||||
public Iterator getKeyClosureIterator(){
|
||||
return null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setJpaCallbackClasses(List<JpaCallbackSource> jpaCallbackClasses) {
|
||||
this.jpaCallbackClasses = jpaCallbackClasses;
|
||||
}
|
||||
|
||||
public Iterable<JpaCallbackSource> getJpaCallbackClasses() {
|
||||
return jpaCallbackClasses;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,14 @@ public class EntityIdentifier {
|
|||
return entityIdentifierBinding.isIdentifierAttributeBinding( attributeBinding );
|
||||
}
|
||||
|
||||
public boolean isCascadeDeleteEnabled() {
|
||||
if ( getAttributeBinding() instanceof Cascadeable ) {
|
||||
Cascadeable cascadeable = Cascadeable.class.cast( getAttributeBinding() );
|
||||
cascadeable.getCascadeStyle();//todo
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getUnsavedValue() {
|
||||
ensureBound();
|
||||
return entityIdentifierBinding.getUnsavedValue();
|
||||
|
|
|
@ -25,14 +25,11 @@ package org.hibernate.metamodel.spi.relational;
|
|||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.internal.util.collections.JoinedIterable;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
|
|
|
@ -702,7 +702,7 @@ public abstract class AbstractCollectionPersister
|
|||
// isSorted = collection.isSorted();
|
||||
isArray = collectionType.isArrayType();
|
||||
isPrimitiveArray =
|
||||
collectionType.isArrayType() &&
|
||||
isArray &&
|
||||
PrimitiveType.class.isInstance(
|
||||
collection.getPluralAttributeElementBinding()
|
||||
.getHibernateTypeDescriptor()
|
||||
|
@ -840,9 +840,10 @@ public abstract class AbstractCollectionPersister
|
|||
indexColumnIsSettable = new boolean[indexSpan];
|
||||
indexColumnAliases = new String[indexSpan];
|
||||
for ( int i = 0 ; i < indexSpan ; i++ ) {
|
||||
final Value value = indexRelationalValueBindings.get( i ).getValue();
|
||||
final RelationalValueBinding rb = indexRelationalValueBindings.get( i );
|
||||
final Value value = rb.getValue();
|
||||
indexColumnAliases[ i ] = value.getAlias( dialect, null );
|
||||
if ( value instanceof Column ) {
|
||||
if ( !rb.isDerived() ) {
|
||||
indexColumnIsSettable[ i ] = true;
|
||||
Column column = ( Column ) value;
|
||||
indexColumnNames[ i ] = column.getColumnName().getText( dialect );
|
||||
|
|
|
@ -73,7 +73,6 @@ import org.hibernate.engine.spi.CascadingActions;
|
|||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper;
|
||||
|
@ -86,7 +85,6 @@ import org.hibernate.id.PostInsertIdentityPersister;
|
|||
import org.hibernate.id.insert.Binder;
|
||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
import org.hibernate.internal.FilterHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.ValueHolder;
|
||||
|
@ -94,7 +92,6 @@ import org.hibernate.internal.util.collections.ArrayHelper;
|
|||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.Expectations;
|
||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||
import org.hibernate.loader.entity.BatchingEntityLoader;
|
||||
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
||||
import org.hibernate.loader.entity.CascadeEntityLoader;
|
||||
import org.hibernate.loader.entity.EntityLoader;
|
||||
|
@ -109,15 +106,15 @@ import org.hibernate.metamodel.spi.binding.Cascadeable;
|
|||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.Fetchable;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.relational.PrimaryKey;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.property.BackrefPropertyAccessor;
|
||||
|
@ -169,6 +166,7 @@ public abstract class AbstractEntityPersister
|
|||
private final String[] rootTableKeyColumnReaders;
|
||||
private final String[] rootTableKeyColumnReaderTemplates;
|
||||
private final String[] identifierAliases;
|
||||
//how many columns are mapped by the identifier?
|
||||
private final int identifierColumnSpan;
|
||||
private final String versionColumnName;
|
||||
private final boolean hasFormulaProperties;
|
||||
|
@ -237,8 +235,8 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
private final Set affectingFetchProfileNames = new HashSet();
|
||||
|
||||
private final Map uniqueKeyLoaders = new HashMap();
|
||||
private final Map lockers = new HashMap();
|
||||
private final Map<String, EntityLoader> uniqueKeyLoaders = new HashMap<String, EntityLoader>();
|
||||
private final Map<LockMode, LockingStrategy> lockers = new HashMap<LockMode, LockingStrategy>();
|
||||
private final Map loaders = new HashMap();
|
||||
|
||||
// SQL strings
|
||||
|
@ -280,8 +278,8 @@ public abstract class AbstractEntityPersister
|
|||
private final String temporaryIdTableName;
|
||||
private final String temporaryIdTableDDL;
|
||||
|
||||
private final Map subclassPropertyAliases = new HashMap();
|
||||
private final Map subclassPropertyColumnNames = new HashMap();
|
||||
private final Map<String, String[]> subclassPropertyAliases = new HashMap<String, String[]>();
|
||||
private final Map<String, String[]> subclassPropertyColumnNames = new HashMap<String, String[]>();
|
||||
|
||||
protected final BasicEntityPropertyMapping propertyMapping;
|
||||
|
||||
|
@ -390,6 +388,19 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
return result;
|
||||
}
|
||||
protected static void initializeCustomSql(
|
||||
CustomSQL customSql,
|
||||
int i,
|
||||
String[] sqlStrings,
|
||||
boolean[] callable,
|
||||
ExecuteUpdateResultCheckStyle[] checkStyles) {
|
||||
sqlStrings[i] = customSql != null ? customSql.getSql(): null;
|
||||
callable[i] = customSql != null && customSql.isCallable();
|
||||
checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ?
|
||||
customSql.getCheckStyle() :
|
||||
ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] );
|
||||
}
|
||||
|
||||
|
||||
protected String getSQLSnapshotSelectString() {
|
||||
return sqlSnapshotSelectString;
|
||||
|
@ -866,9 +877,11 @@ public abstract class AbstractEntityPersister
|
|||
rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan];
|
||||
identifierAliases = new String[identifierColumnSpan];
|
||||
|
||||
|
||||
int i = 0;
|
||||
for ( org.hibernate.metamodel.spi.relational.Column col : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) {
|
||||
for ( int i = 0; i < identifierColumnSpan; i++ ) {
|
||||
org.hibernate.metamodel.spi.relational.Column col = entityBinding.getPrimaryTable()
|
||||
.getPrimaryKey()
|
||||
.getColumns()
|
||||
.get( i );
|
||||
rootTableKeyColumnNames[i] = col.getColumnName().getText( factory.getDialect() );
|
||||
if ( col.getReadFragment() == null ) {
|
||||
rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i];
|
||||
|
@ -878,8 +891,7 @@ public abstract class AbstractEntityPersister
|
|||
rootTableKeyColumnReaders[i] = col.getReadFragment();
|
||||
rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( col.getReadFragment(), factory );
|
||||
}
|
||||
identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getPrimaryTable() );
|
||||
i++;
|
||||
identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getHierarchyDetails().getRootEntityBinding().getPrimaryTable() );
|
||||
}
|
||||
|
||||
// VERSION
|
||||
|
@ -937,7 +949,7 @@ public abstract class AbstractEntityPersister
|
|||
List<String[]> lazyColAliases = new ArrayList<String[]>();
|
||||
|
||||
|
||||
i = 0;
|
||||
int i = 0;
|
||||
boolean foundFormula = false;
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||
|
@ -1042,7 +1054,7 @@ public abstract class AbstractEntityPersister
|
|||
List<Boolean> columnSelectables = new ArrayList<Boolean>();
|
||||
List<Boolean> propNullables = new ArrayList<Boolean>();
|
||||
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||
// entity identifier is not considered a "normal" property
|
||||
continue;
|
||||
|
@ -1835,7 +1847,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
private LockingStrategy getLocker(LockMode lockMode) {
|
||||
return ( LockingStrategy ) lockers.get( lockMode );
|
||||
return lockers.get( lockMode );
|
||||
}
|
||||
|
||||
public void lock(
|
||||
|
@ -2085,7 +2097,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
public String[] getSubclassPropertyColumnAliases(String propertyName, String suffix) {
|
||||
String rawAliases[] = ( String[] ) subclassPropertyAliases.get( propertyName );
|
||||
String rawAliases[] = subclassPropertyAliases.get( propertyName );
|
||||
|
||||
if ( rawAliases == null ) {
|
||||
return null;
|
||||
|
@ -2097,10 +2109,10 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSubclassPropertyColumnNames(String propertyName) {
|
||||
//TODO: should we allow suffixes on these ?
|
||||
return ( String[] ) subclassPropertyColumnNames.get( propertyName );
|
||||
return subclassPropertyColumnNames.get( propertyName );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2179,7 +2191,7 @@ public abstract class AbstractEntityPersister
|
|||
// ALIASES
|
||||
|
||||
// TODO: Fix when subclasses are working (HHH-6337)
|
||||
internalInitSubclassPropertyAliasesMap( null, entityBinding.getSubEntityAttributeBindingClosure() );
|
||||
internalInitSubclassPropertyAliasesMap( null, entityBinding.getEntitiesAttributeBindingClosure() );
|
||||
|
||||
// aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id'
|
||||
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
|
||||
|
@ -2266,10 +2278,12 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private void internalInitSubclassPropertyAliasesMap(String path, Iterable<AttributeBinding> attributeBindings) {
|
||||
protected static boolean isIdentifierAttributeBinding(final AttributeBinding prop){
|
||||
return prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop );
|
||||
}
|
||||
private void internalInitSubclassPropertyAliasesMap(String path, AttributeBinding[] attributeBindings) {
|
||||
for ( AttributeBinding prop : attributeBindings ) {
|
||||
if ( prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop ) ) {
|
||||
if ( isIdentifierAttributeBinding( prop ) ) {
|
||||
// ID propertie aliases are dealt with elsewhere.
|
||||
continue;
|
||||
}
|
||||
|
@ -2281,7 +2295,12 @@ public abstract class AbstractEntityPersister
|
|||
String propname = path == null ? prop.getAttribute().getName() : path + "." + prop.getAttribute().getName();
|
||||
if ( prop instanceof CompositeAttributeBinding ) {
|
||||
CompositeAttributeBinding component = (CompositeAttributeBinding) prop;
|
||||
internalInitSubclassPropertyAliasesMap( propname, component.attributeBindings() );
|
||||
AttributeBinding[] abs = new AttributeBinding[component.attributeBindingSpan()];
|
||||
int i=0;
|
||||
for(AttributeBinding ab : component.attributeBindings()){
|
||||
abs[i++] = ab;
|
||||
}
|
||||
internalInitSubclassPropertyAliasesMap( propname, abs );
|
||||
}
|
||||
else {
|
||||
int span = singularProp.getRelationalValueBindings().size();
|
||||
|
@ -2324,7 +2343,7 @@ public abstract class AbstractEntityPersister
|
|||
&& propertyName.indexOf('.')<0; //ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
|
||||
|
||||
if ( useStaticLoader ) {
|
||||
return ( EntityLoader ) uniqueKeyLoaders.get( propertyName );
|
||||
return uniqueKeyLoaders.get( propertyName );
|
||||
}
|
||||
else {
|
||||
return createUniqueKeyLoader(
|
||||
|
@ -3898,10 +3917,11 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
private boolean isAffectedByEnabledFetchProfiles(SessionImplementor session) {
|
||||
Iterator itr = session.getLoadQueryInfluencers().getEnabledFetchProfileNames().iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
if ( affectingFetchProfileNames.contains( itr.next() ) ) {
|
||||
return true;
|
||||
if ( session.getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
|
||||
for ( String name : session.getLoadQueryInfluencers().getEnabledFetchProfileNames() ) {
|
||||
if ( affectingFetchProfileNames.contains( name ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -3962,8 +3982,7 @@ public abstract class AbstractEntityPersister
|
|||
protected final boolean[] getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection) {
|
||||
final boolean[] propsToUpdate = new boolean[ entityMetamodel.getPropertySpan() ];
|
||||
final boolean[] updateability = getPropertyUpdateability(); //no need to check laziness, dirty checking handles that
|
||||
for ( int j = 0; j < dirtyProperties.length; j++ ) {
|
||||
int property = dirtyProperties[j];
|
||||
for ( int property : dirtyProperties ) {
|
||||
if ( updateability[property] ) {
|
||||
propsToUpdate[property] = true;
|
||||
}
|
||||
|
@ -4058,8 +4077,8 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
private void logDirtyProperties(int[] props) {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
for ( int i = 0; i < props.length; i++ ) {
|
||||
String propertyName = entityMetamodel.getProperties()[ props[i] ].getName();
|
||||
for ( int prop : props ) {
|
||||
String propertyName = entityMetamodel.getProperties()[prop].getName();
|
||||
LOG.trace( StringHelper.qualify( getEntityName(), propertyName ) + " is dirty" );
|
||||
}
|
||||
}
|
||||
|
@ -4220,13 +4239,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
public Boolean isTransient(Object entity, SessionImplementor session) throws HibernateException {
|
||||
final Serializable id;
|
||||
if ( canExtractIdOutOfEntity() ) {
|
||||
id = getIdentifier( entity, session );
|
||||
}
|
||||
else {
|
||||
id = null;
|
||||
}
|
||||
final Serializable id = canExtractIdOutOfEntity() ? getIdentifier( entity, session ) : null;
|
||||
// we *always* assume an instance with a null
|
||||
// identifier or no identifier property is unsaved!
|
||||
if ( id == null ) {
|
||||
|
@ -4276,7 +4289,6 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
private boolean isModifiableEntity(EntityEntry entry) {
|
||||
|
||||
return ( entry == null ? isMutable() : entry.isModifiableEntity() );
|
||||
}
|
||||
|
||||
|
@ -4566,6 +4578,20 @@ public abstract class AbstractEntityPersister
|
|||
return temporaryIdTableDDL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Here, we want to know how many properties of this persister know about.
|
||||
* <p/>
|
||||
* The properties including:
|
||||
* <ul>
|
||||
* <li>properties belongs to the current entity</li>
|
||||
* <li>properties belongs to the join entity</li>
|
||||
* <li>parent's properties, recursively</li>
|
||||
* </ul>
|
||||
*
|
||||
* note: id property is not included here
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected int getPropertySpan() {
|
||||
return entityMetamodel.getPropertySpan();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.io.Serializable;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
|
@ -35,6 +36,7 @@ import org.hibernate.MappingException;
|
|||
import org.hibernate.QueryException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -50,9 +52,12 @@ import org.hibernate.mapping.Property;
|
|||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Subclass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
|
||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SecondaryTable;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.relational.PrimaryKey;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.sql.CaseFragment;
|
||||
|
@ -67,32 +72,192 @@ import org.hibernate.type.*;
|
|||
*/
|
||||
public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||
|
||||
// the class hierarchy structure
|
||||
/**
|
||||
* Tables' count, which tables are mapped directly by the current entity ( and its parent entity, recursively, if any ),
|
||||
* including the joined tables, but sub-entities of the current entity are not included.
|
||||
*/
|
||||
private final int tableSpan;
|
||||
private final String[] tableNames;
|
||||
/**
|
||||
* Span of the tables directly mapped by this entity and super-classes, if any.
|
||||
* <p/>
|
||||
* so, <code>coreTableSpan = tableSpan - join tables span</code>
|
||||
*/
|
||||
private final int coreTableSpan;
|
||||
|
||||
/**
|
||||
* Tables' name, the tables' scope is same as {@code tableSpan}.
|
||||
* <p/>
|
||||
*
|
||||
* This array ( the table names ) is order by the following roles:
|
||||
* <ul>
|
||||
* <li>Table mapped by the root entity of current one if any</li>
|
||||
* <li>Table mapped by sub entity of the root one, recursively, till the current entity in the hierarchy level</li>
|
||||
* <li>Joined tables, also, in the top-down order of the hierarchy</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* Suppose an entity Client extends Person, mapped to the tables CLIENT and PERSON respectively.
|
||||
* For the Client entity:
|
||||
* naturalOrderTableNames -> PERSON, CLIENT; this reflects the sequence in which the tables are
|
||||
* added to the meta-data when the annotated entities are processed.
|
||||
* However, in some instances, for example when generating joins, the CLIENT table needs to be
|
||||
* the first table as it will the driving table.
|
||||
* tableNames -> CLIENT, PERSON
|
||||
*
|
||||
* <p>
|
||||
* The length of this array is <code>tableSpan</code>
|
||||
* </p>
|
||||
*/
|
||||
private final String[] naturalOrderTableNames;
|
||||
private final String[][] tableKeyColumns;
|
||||
private final String[][] tableKeyColumnReaders;
|
||||
private final String[][] tableKeyColumnReaderTemplates;
|
||||
|
||||
/**
|
||||
* This contains same elements as naturalOrderTableNames, but in different order.
|
||||
* <p/>
|
||||
*
|
||||
* As said above, elements in this array are actually composited by two parts:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Table names mapped directly by the entities of the hierarchy</li>
|
||||
* <li>Table names mapped by "join"</li>
|
||||
* </ul>
|
||||
*
|
||||
* In the first part of elements, the naturalOrderTableNames follows "root" -> "sub-entities" -> "current entity"
|
||||
*
|
||||
* here, we have a reversed order, so "current entity" -> "parent entity" -> "root entity"
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* The order of the second part is same.
|
||||
*
|
||||
* <p>
|
||||
* The length of this array is <code>tableSpan</code>
|
||||
* </p>
|
||||
*
|
||||
*/
|
||||
private final String[] tableNames;
|
||||
|
||||
/**
|
||||
* These two follow same role as above, but for the primary key columns
|
||||
*
|
||||
* <p>
|
||||
* The first dimension length of this array is <code>tableSpan</code>
|
||||
* </p>
|
||||
*/
|
||||
private final String[][] naturalOrderTableKeyColumns;
|
||||
private final String[][] tableKeyColumns;
|
||||
|
||||
/**
|
||||
* Same as above, just for different column metadata.
|
||||
*/
|
||||
private final String[][] tableKeyColumnReaders;
|
||||
private final String[][] naturalOrderTableKeyColumnReaders;
|
||||
|
||||
/**
|
||||
* Same as above, just for different column metadata.
|
||||
*/
|
||||
private final String[][] tableKeyColumnReaderTemplates;
|
||||
private final String[][] naturalOrderTableKeyColumnReaderTemplates;
|
||||
|
||||
/**
|
||||
* If the identifier is cascade delete enabled.
|
||||
* Array is ordered by the natural way ( {@see naturalOrderTableNames} )
|
||||
*
|
||||
* <p>
|
||||
* The length of this array is <code>tableSpan</code>
|
||||
* </p>
|
||||
*/
|
||||
private final boolean[] naturalOrderCascadeDeleteEnabled;
|
||||
|
||||
/**
|
||||
* <code>tableNames</code>
|
||||
* <code>synchronized tables in the entity hierarchy from top down to the current entity level, sub-entities are not included</code>
|
||||
*
|
||||
* <p>
|
||||
* The length of this array is <code>tableSpan + sync table count</code>
|
||||
* </p>
|
||||
*/
|
||||
private final String[] spaces;
|
||||
|
||||
/**
|
||||
* This array contains all the sub-entities' name of the current entity, and
|
||||
* the last element of this array is the current entity name.
|
||||
*
|
||||
* Sub-entities' name is ordered in the most derived subclasses first, from bottom to top, till the current one.
|
||||
*
|
||||
* <p>
|
||||
* The length of this array is the count of all the sub entities (recursively) of the current one + 1
|
||||
* </p>
|
||||
*/
|
||||
private final String[] subclassClosure;
|
||||
|
||||
/**
|
||||
* This is kind of same as {@see tableNames}, but it contains all the tables' name mapped by the current entity's super entities AND
|
||||
* sub entities, and joined tables mapped by the entities.
|
||||
*
|
||||
* Actually, due to the order operation, the first <code>coreTableSpan</code> elements are same as <code>tableNames</code>.
|
||||
* (table names mapped by the current entity and its super entities, joined tables are not included)
|
||||
*
|
||||
* So, this property is kind of weird to me, it has:
|
||||
*
|
||||
* 1. "current entity" -> "parent entity" -> "root entity" -> "first sub-entity" -> "second sub-entity" .... "last sub-entity"
|
||||
* 2. "root entity join table" -> ..."last entity join table"
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Though this property is named with "subclassTable" perfix, but its length is actually:
|
||||
* tableSpan + all sub-entities mapped tables' count + all sub-entities joined tables' count
|
||||
* </p>
|
||||
*/
|
||||
private final String[] subclassTableNameClosure;
|
||||
/**
|
||||
* table's primary key columns, in the same order as above
|
||||
*
|
||||
* <p>
|
||||
* The length is same as <code>subclassTableNameClosure</code>
|
||||
* </p>
|
||||
*/
|
||||
private final String[][] subclassTableKeyColumnClosure;
|
||||
|
||||
/**
|
||||
* If the table, in the order of <code>subclassTableNameClosure</code> is concreted.
|
||||
* By "concreted", here means if the table is one of current entity or its super entity mapped table
|
||||
*
|
||||
* <p>
|
||||
* The length is same as <code>subclassTableNameClosure</code>
|
||||
* </p>
|
||||
*/
|
||||
private final boolean[] isClassOrSuperclassTable;
|
||||
|
||||
// properties of this class, including inherited properties
|
||||
/**
|
||||
* The element in this array is the index of the {@see naturalOrderTableNames}, which table that the column is belonged to.
|
||||
*
|
||||
* So, this is all about the columns ( except PK ) mapped by the properties in the current entity and its parent entity, in a top down order.
|
||||
*
|
||||
* <p>
|
||||
* The length is the count of columns, mapped by the properties in the current entity and from its super entity, and joined columns.
|
||||
* </p>
|
||||
*/
|
||||
private final int[] naturalOrderPropertyTableNumbers;
|
||||
|
||||
/**
|
||||
* Same as above, but here is the index of {@see tableNames}
|
||||
*
|
||||
* <p>
|
||||
* The length is same as above.
|
||||
* </p>
|
||||
*/
|
||||
private final int[] propertyTableNumbers;
|
||||
|
||||
// the closure of all properties in the entire hierarchy including
|
||||
// subclasses and superclasses of this class
|
||||
/**
|
||||
* the closure of all properties in the entire hierarchy including
|
||||
* subclasses and superclasses of this class
|
||||
*
|
||||
* The element is the index of {@see subclassTableNameClosure}, which table that the property's relational value belongs to.
|
||||
*
|
||||
* <p>
|
||||
* The length is all the properties count in the entire hierarchy.
|
||||
* </p>
|
||||
*
|
||||
*/
|
||||
private final int[] subclassPropertyTableNumberClosure;
|
||||
|
||||
// the closure of all columns used by the entire hierarchy including
|
||||
|
@ -117,11 +282,16 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
private final Object discriminatorValue;
|
||||
private final String discriminatorSQLString;
|
||||
|
||||
// Span of the tables directly mapped by this entity and super-classes, if any
|
||||
private final int coreTableSpan;
|
||||
|
||||
// only contains values for SecondaryTables, ie. not tables part of the "coreTableSpan"
|
||||
private final boolean[] isNullableTable;
|
||||
|
||||
|
||||
private void assertOptimisticLockStyle() {
|
||||
if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) {
|
||||
throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" );
|
||||
}
|
||||
}
|
||||
//INITIALIZATION:
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public JoinedSubclassEntityPersister(
|
||||
|
@ -149,14 +319,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
discriminatorSQLString = null;
|
||||
}
|
||||
|
||||
if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) {
|
||||
throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" );
|
||||
}
|
||||
assertOptimisticLockStyle();
|
||||
|
||||
//MULTITABLES
|
||||
|
||||
final int idColumnSpan = getIdentifierColumnSpan();
|
||||
|
||||
ArrayList tables = new ArrayList();
|
||||
ArrayList keyColumns = new ArrayList();
|
||||
ArrayList keyColumnReaders = new ArrayList();
|
||||
|
@ -191,7 +358,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
//Span of the tables directly mapped by this entity and super-classes, if any
|
||||
coreTableSpan = tables.size();
|
||||
|
||||
isNullableTable = new boolean[persistentClass.getJoinClosureSpan()];
|
||||
|
||||
int tableIndex = 0;
|
||||
|
@ -241,7 +407,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
ArrayList isConcretes = new ArrayList();
|
||||
ArrayList isDeferreds = new ArrayList();
|
||||
ArrayList isLazies = new ArrayList();
|
||||
|
||||
keyColumns = new ArrayList();
|
||||
titer = persistentClass.getSubclassTableClosureIterator();
|
||||
while ( titer.hasNext() ) {
|
||||
|
@ -262,7 +427,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
keyColumns.add( key );
|
||||
}
|
||||
|
||||
//Add joins
|
||||
joinIter = persistentClass.getSubclassJoinClosureIterator();
|
||||
while ( joinIter.hasNext() ) {
|
||||
|
@ -293,7 +457,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes );
|
||||
subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds );
|
||||
subclassTableIsLazyClosure = ArrayHelper.toBooleanArray( isLazies );
|
||||
|
||||
constraintOrderedTableNames = new String[naturalOrderSubclassTableNameClosure.length];
|
||||
constraintOrderedKeyColumnNames = new String[naturalOrderSubclassTableNameClosure.length][];
|
||||
int currentPosition = 0;
|
||||
|
@ -305,9 +468,9 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
/**
|
||||
* Suppose an entity Client extends Person, mapped to the tables CLIENT and PERSON respectively.
|
||||
* For the Client entity:
|
||||
* naturalOrderTableNames -> PERSON, CLIENT; this reflects the sequence in which the tables are
|
||||
* naturalOrderTableNames -> PERSON, CLIENT; this reflects the sequence in which the tables are
|
||||
* added to the meta-data when the annotated entities are processed.
|
||||
* However, in some instances, for example when generating joins, the CLIENT table needs to be
|
||||
* However, in some instances, for example when generating joins, the CLIENT table needs to be
|
||||
* the first table as it will the driving table.
|
||||
* tableNames -> CLIENT, PERSON
|
||||
*/
|
||||
|
@ -319,12 +482,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
tableKeyColumnReaderTemplates = reverse( naturalOrderTableKeyColumnReaderTemplates, coreTableSpan );
|
||||
subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan );
|
||||
subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan );
|
||||
|
||||
spaces = ArrayHelper.join(
|
||||
tableNames,
|
||||
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
|
||||
);
|
||||
|
||||
// Custom sql
|
||||
customSQLInsert = new String[tableSpan];
|
||||
customSQLUpdate = new String[tableSpan];
|
||||
|
@ -363,7 +524,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
if ( jk != -1 ) {
|
||||
throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." );
|
||||
}
|
||||
|
||||
joinIter = persistentClass.getJoinClosureIterator();
|
||||
int j = coreTableSpan;
|
||||
while ( joinIter.hasNext() ) {
|
||||
|
@ -387,6 +547,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
j++;
|
||||
}
|
||||
|
||||
|
||||
// PROPERTIES
|
||||
int hydrateSpan = getPropertySpan();
|
||||
naturalOrderPropertyTableNumbers = new int[hydrateSpan];
|
||||
|
@ -412,7 +573,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
ArrayList columnTableNumbers = new ArrayList();
|
||||
ArrayList formulaTableNumbers = new ArrayList();
|
||||
ArrayList propTableNumbers = new ArrayList();
|
||||
|
||||
iter = persistentClass.getSubclassPropertyClosureIterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Property prop = (Property) iter.next();
|
||||
|
@ -445,8 +605,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
// SUBCLASSES
|
||||
|
||||
int subclassSpan = persistentClass.getSubclassSpan() + 1;
|
||||
subclassClosure = new String[subclassSpan];
|
||||
subclassClosure[subclassSpan - 1] = getEntityName();
|
||||
|
||||
if ( persistentClass.isPolymorphic() ) {
|
||||
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
|
||||
discriminatorValues = new String[subclassSpan];
|
||||
|
@ -470,6 +629,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
notNullColumnNames = null;
|
||||
}
|
||||
|
||||
subclassClosure = new String[subclassSpan];
|
||||
subclassClosure[subclassSpan - 1] = getEntityName();
|
||||
iter = persistentClass.getSubclassIterator();
|
||||
int k = 0;
|
||||
while ( iter.hasNext() ) {
|
||||
|
@ -508,6 +669,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
postConstruct( mapping );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public JoinedSubclassEntityPersister(
|
||||
final EntityBinding entityBinding,
|
||||
|
@ -517,104 +680,358 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
final Mapping mapping) throws HibernateException {
|
||||
|
||||
super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||
// DISCRIMINATOR
|
||||
if ( entityBinding.isPolymorphic() ) {
|
||||
try{
|
||||
discriminatorValue = entityBinding.getSubEntityBindingId();
|
||||
discriminatorSQLString = discriminatorValue.toString();
|
||||
} catch ( Exception e ){
|
||||
throw new MappingException( "Could not format discriminator value to SQL string", e );
|
||||
|
||||
assertOptimisticLockStyle();
|
||||
|
||||
final boolean isCascadeDeleteDefault = factory.getDialect().supportsCascadeDelete();
|
||||
|
||||
final EntityBinding[] entityBindings = entityBinding.getEntityBindingClosure();
|
||||
final TableSpecification[] tables = entityBinding.getTableClosure();
|
||||
final SecondaryTable[] secondaryTables = entityBinding.getSecondaryTableClosure();
|
||||
final String[] synchronizedTableNames = entityBinding.getSynchronizedTableNameClosure();
|
||||
final AttributeBinding[] attributeBindings = entityBinding.getAttributeBindingClosure();
|
||||
//todo the count of these two are not equal, which they should be
|
||||
final EntityBinding[] preOrderSubEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure();
|
||||
final EntityBinding[] postOrderSubEntityBindings = entityBinding.getPostOrderSubEntityBindingClosure();
|
||||
final TableSpecification[] subTables = entityBinding.getPreOrderSubTableClosure();
|
||||
final SecondaryTable[] subSecondaryTables = entityBinding.getSubEntitySecondaryTables();
|
||||
final AttributeBinding[] allAttributeBindings = entityBinding.getEntitiesAttributeBindingClosure();
|
||||
|
||||
final int idColumnSpan = getIdentifierColumnSpan();
|
||||
coreTableSpan = tables.length;
|
||||
final int secondaryTableSpan = secondaryTables.length;
|
||||
tableSpan = coreTableSpan + secondaryTableSpan;
|
||||
final int subclassSpan = postOrderSubEntityBindings.length;
|
||||
final int subclassSecondaryTableSpan = subSecondaryTables.length;
|
||||
final int subTableSpan = subclassSpan + subclassSecondaryTableSpan;
|
||||
final int allTableSpan = tableSpan + subTableSpan;
|
||||
final int hydrateSpan = getPropertySpan();
|
||||
isClassOrSuperclassTable = new boolean[allTableSpan];
|
||||
subclassTableSequentialSelect = new boolean[allTableSpan];
|
||||
subclassTableIsLazyClosure = new boolean[allTableSpan];
|
||||
naturalOrderTableNames = new String[tableSpan];
|
||||
naturalOrderCascadeDeleteEnabled = new boolean[tableSpan];
|
||||
|
||||
naturalOrderTableKeyColumns = new String[tableSpan][];
|
||||
naturalOrderTableKeyColumnReaders = new String[tableSpan][];
|
||||
naturalOrderTableKeyColumnReaderTemplates = new String[tableSpan][];
|
||||
//custom sql
|
||||
customSQLInsert = new String[tableSpan];
|
||||
customSQLUpdate = new String[tableSpan];
|
||||
customSQLDelete = new String[tableSpan];
|
||||
insertCallable = new boolean[tableSpan];
|
||||
updateCallable = new boolean[tableSpan];
|
||||
deleteCallable = new boolean[tableSpan];
|
||||
insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
|
||||
updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
|
||||
deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
|
||||
subclassClosure = new String[subclassSpan+1];
|
||||
subclassClosure[subclassSpan] = getEntityName();
|
||||
isNullableTable = new boolean[secondaryTableSpan];
|
||||
naturalOrderPropertyTableNumbers = new int[hydrateSpan];
|
||||
propertyTableNumbers = new int[hydrateSpan];
|
||||
constraintOrderedTableNames = new String[allTableSpan];
|
||||
constraintOrderedKeyColumnNames = new String[allTableSpan][];
|
||||
/**
|
||||
* 1. core table names
|
||||
* 2. direct sub entity table names
|
||||
* 3. core joined table names
|
||||
* 4. direct sub entity joined table names
|
||||
*/
|
||||
final String[] naturalOrderSubclassTableNameClosure = new String[allTableSpan];
|
||||
final String[][] naturalOrderSubclassTableKeyColumnClosure = new String[allTableSpan][];
|
||||
|
||||
|
||||
int tableIndex = 0;
|
||||
int allTableIndex =0;
|
||||
//first, process tables / entitybindings mapped directly by the current entitybinding and its super entitybindings
|
||||
for ( int i = 0; i < coreTableSpan; i++, tableIndex++, allTableIndex++ ) {
|
||||
final TableSpecification table = tables[i];
|
||||
naturalOrderTableNames[tableIndex] = table.getQualifiedName( factory.getDialect() );
|
||||
naturalOrderCascadeDeleteEnabled[tableIndex] = false; //todo fix me @OnDelete
|
||||
naturalOrderTableKeyColumns[tableIndex] = new String[idColumnSpan];
|
||||
naturalOrderTableKeyColumnReaders[tableIndex] = new String[idColumnSpan];
|
||||
naturalOrderTableKeyColumnReaderTemplates[tableIndex] = new String[idColumnSpan];
|
||||
PrimaryKey primaryKey = table.getPrimaryKey();
|
||||
resolvePkColumnNames(
|
||||
factory,
|
||||
primaryKey,
|
||||
naturalOrderTableKeyColumns[tableIndex],
|
||||
naturalOrderTableKeyColumnReaders[tableIndex],
|
||||
naturalOrderTableKeyColumnReaderTemplates[tableIndex]
|
||||
);
|
||||
final EntityBinding eb = entityBindings[i];
|
||||
//Custom SQL
|
||||
initializeCustomSql( eb.getCustomInsert(), tableIndex, customSQLInsert, insertCallable, insertResultCheckStyles );
|
||||
initializeCustomSql( eb.getCustomUpdate(), tableIndex, customSQLUpdate, updateCallable, updateResultCheckStyles );
|
||||
initializeCustomSql( eb.getCustomDelete(), tableIndex, customSQLDelete, deleteCallable, deleteResultCheckStyles );
|
||||
isClassOrSuperclassTable[allTableIndex] = true;//EntityBindingHelper.isClassOrSuperclassTable( entityBinding, table );
|
||||
subclassTableSequentialSelect[allTableIndex] = false;
|
||||
subclassTableIsLazyClosure[allTableIndex] = false;
|
||||
}
|
||||
|
||||
//#1
|
||||
System.arraycopy( naturalOrderTableNames, 0, naturalOrderSubclassTableNameClosure, 0, coreTableSpan );
|
||||
System.arraycopy( naturalOrderTableKeyColumns, 0, naturalOrderSubclassTableKeyColumnClosure, 0, coreTableSpan );
|
||||
//--------------------------------- directly sub entities
|
||||
final String[] naturalOrderSubTableNames = new String[subclassSpan];
|
||||
final String[][] naturalOrderSubTableKeyColumns = new String[subclassSpan][idColumnSpan];
|
||||
|
||||
for ( int i = 0; i < subclassSpan; i++, allTableIndex++ ) {
|
||||
final EntityBinding subEntityBinding = preOrderSubEntityBindings[i]; //todo post order??
|
||||
final TableSpecification table = subEntityBinding.getPrimaryTable();
|
||||
naturalOrderSubTableNames[i] = table.getQualifiedName( factory.getDialect() );
|
||||
|
||||
final PrimaryKey pk = table.getPrimaryKey();
|
||||
for(int j=0;j<idColumnSpan;j++){
|
||||
naturalOrderSubTableKeyColumns[i][j] = pk.getColumns().get( j ).getColumnName().getText( factory.getDialect() );
|
||||
}
|
||||
isClassOrSuperclassTable[allTableIndex] = false;//EntityBindingHelper.isClassOrSuperclassTable( entityBinding, table );
|
||||
subclassTableSequentialSelect[allTableIndex] = false;
|
||||
subclassTableIsLazyClosure[allTableIndex] = false;
|
||||
}
|
||||
|
||||
//#2
|
||||
System.arraycopy(
|
||||
naturalOrderSubTableNames,
|
||||
0,
|
||||
naturalOrderSubclassTableNameClosure,
|
||||
coreTableSpan,
|
||||
subclassSpan
|
||||
);
|
||||
System.arraycopy( naturalOrderSubTableKeyColumns, 0, naturalOrderSubclassTableKeyColumnClosure, coreTableSpan,
|
||||
subclassSpan );
|
||||
|
||||
|
||||
|
||||
//--------------------------------- secondary tables
|
||||
|
||||
|
||||
for ( int i = 0; i < secondaryTableSpan; i++,tableIndex++, allTableIndex++ ) {
|
||||
final SecondaryTable secondaryTable = secondaryTables[i];
|
||||
final PrimaryKey pk = secondaryTable.getSecondaryTableReference().getPrimaryKey();
|
||||
naturalOrderTableNames[tableIndex] = secondaryTable.getSecondaryTableReference()
|
||||
.getQualifiedName( factory.getDialect() );
|
||||
isNullableTable[i] = secondaryTable.isOptional();
|
||||
naturalOrderCascadeDeleteEnabled[tableIndex] = secondaryTable.isCascadeDeleteEnabled();
|
||||
|
||||
final int secondaryTablePKColumnSpan = secondaryTable.getSecondaryTableReference()
|
||||
.getPrimaryKey()
|
||||
.getColumnSpan();
|
||||
naturalOrderTableKeyColumns[tableIndex] = new String[secondaryTablePKColumnSpan];
|
||||
naturalOrderTableKeyColumnReaders[tableIndex] = new String[secondaryTablePKColumnSpan];
|
||||
naturalOrderTableKeyColumnReaderTemplates[tableIndex] = new String[secondaryTablePKColumnSpan];
|
||||
resolvePkColumnNames(
|
||||
factory,
|
||||
pk,
|
||||
naturalOrderTableKeyColumns[tableIndex],
|
||||
naturalOrderTableKeyColumnReaders[tableIndex],
|
||||
naturalOrderTableKeyColumnReaderTemplates[tableIndex]
|
||||
);
|
||||
//todo custom sql in secondary table binding
|
||||
initializeCustomSql(null, tableIndex, customSQLInsert, insertCallable, insertResultCheckStyles);
|
||||
initializeCustomSql(null, tableIndex, customSQLUpdate, updateCallable, updateResultCheckStyles);
|
||||
initializeCustomSql(null, tableIndex, customSQLDelete, deleteCallable, deleteResultCheckStyles);
|
||||
isClassOrSuperclassTable[allTableIndex] = false;//EntityBindingHelper.isClassOrSuperclassTable( entityBinding, table );
|
||||
subclassTableSequentialSelect[allTableIndex] = secondaryTable.getFetchStyle() == FetchStyle.SELECT;
|
||||
subclassTableIsLazyClosure[allTableIndex] = secondaryTable.isLazy();
|
||||
|
||||
}
|
||||
|
||||
//#3
|
||||
System.arraycopy(
|
||||
naturalOrderTableNames,
|
||||
tableSpan - coreTableSpan,
|
||||
naturalOrderSubclassTableNameClosure,
|
||||
coreTableSpan + subclassSpan,
|
||||
secondaryTableSpan
|
||||
);
|
||||
System.arraycopy(
|
||||
naturalOrderTableKeyColumns,
|
||||
tableSpan - coreTableSpan,
|
||||
naturalOrderSubclassTableKeyColumnClosure,
|
||||
coreTableSpan + subclassSpan,
|
||||
secondaryTableSpan
|
||||
);
|
||||
|
||||
//--------------------------------- direct sub entity secondary tables
|
||||
final String[] naturalOrderSubSecondaryTableNames = new String[subclassSecondaryTableSpan];
|
||||
final String[][] naturalOrderSubSecondaryTableKeyColumns = new String[subclassSecondaryTableSpan][];
|
||||
for ( int i = 0; i < subclassSecondaryTableSpan; i++, allTableIndex++ ) {
|
||||
final SecondaryTable secondaryTable = subSecondaryTables[i];
|
||||
naturalOrderSubSecondaryTableNames[i] = secondaryTable.getSecondaryTableReference().getQualifiedName( factory.getDialect() );
|
||||
final PrimaryKey pk = secondaryTable.getSecondaryTableReference().getPrimaryKey();
|
||||
naturalOrderSubSecondaryTableKeyColumns[i] = new String[pk.getColumnSpan()];
|
||||
for(int j =0;j<pk.getColumnSpan();j++){
|
||||
naturalOrderSubSecondaryTableKeyColumns[i][j]= pk.getColumns().get( j ).getColumnName().getText( factory.getDialect() );
|
||||
}
|
||||
isClassOrSuperclassTable[allTableIndex] = false;//EntityBindingHelper.isClassOrSuperclassTable( entityBinding, table );
|
||||
subclassTableSequentialSelect[allTableIndex] = secondaryTable.getFetchStyle() == FetchStyle.SELECT;
|
||||
subclassTableIsLazyClosure[allTableIndex] = secondaryTable.isLazy();
|
||||
}
|
||||
//#4
|
||||
System.arraycopy(
|
||||
naturalOrderSubSecondaryTableNames,
|
||||
0,
|
||||
naturalOrderSubclassTableNameClosure,
|
||||
tableSpan + subclassSpan,
|
||||
subclassSecondaryTableSpan
|
||||
);
|
||||
//#4
|
||||
System.arraycopy(
|
||||
naturalOrderSubSecondaryTableKeyColumns,
|
||||
0,
|
||||
naturalOrderSubclassTableKeyColumnClosure,
|
||||
tableSpan + subclassSpan,
|
||||
subclassSecondaryTableSpan
|
||||
);
|
||||
//--------------------------------- core and secondary tables
|
||||
|
||||
tableNames = reverse( naturalOrderTableNames, coreTableSpan );
|
||||
tableKeyColumns = reverse( naturalOrderTableKeyColumns, coreTableSpan );
|
||||
tableKeyColumnReaders = reverse( naturalOrderTableKeyColumnReaders, coreTableSpan );
|
||||
tableKeyColumnReaderTemplates = reverse( naturalOrderTableKeyColumnReaderTemplates, coreTableSpan );
|
||||
spaces = ArrayHelper.join( tableNames, synchronizedTableNames );
|
||||
//--------------------------------- sub entities
|
||||
|
||||
|
||||
|
||||
int currentPosition = 0;
|
||||
for ( int i = allTableSpan - 1; i >= 0; i--, currentPosition++ ) {
|
||||
constraintOrderedTableNames[currentPosition] = naturalOrderSubclassTableNameClosure[i];
|
||||
constraintOrderedKeyColumnNames[currentPosition] = naturalOrderSubclassTableKeyColumnClosure[i];
|
||||
}
|
||||
subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan );
|
||||
subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan );
|
||||
|
||||
// PROPERTIES
|
||||
|
||||
|
||||
ArrayList<Integer> columnTableNumbers = new ArrayList<Integer>();
|
||||
ArrayList<Integer> formulaTableNumbers = new ArrayList<Integer>();
|
||||
ArrayList<Integer> propTableNumbers = new ArrayList<Integer>();
|
||||
for(int i=0;i<allAttributeBindings.length;i++){
|
||||
final AttributeBinding attributeBinding = allAttributeBindings[i];
|
||||
//if this is identifier, then continue
|
||||
if ( isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||
continue;
|
||||
}
|
||||
final List<RelationalValueBinding> valueBindings;
|
||||
if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
SingularAttributeBinding singularAttributeBinding = SingularAttributeBinding.class.cast(
|
||||
attributeBinding
|
||||
);
|
||||
valueBindings = singularAttributeBinding.getRelationalValueBindings();
|
||||
}
|
||||
else {
|
||||
PluralAttributeBinding pluralAttributeBinding = PluralAttributeBinding.class.cast( attributeBinding );
|
||||
valueBindings = pluralAttributeBinding.getPluralAttributeElementBinding().getRelationalValueBindings();
|
||||
}
|
||||
RelationalValueBinding valueBinding = valueBindings.get( 0 );
|
||||
TableSpecification table = valueBinding.getValue().getTable();
|
||||
final String tableName = table.getQualifiedName( factory.getDialect() );
|
||||
if ( i < hydrateSpan ) {
|
||||
propertyTableNumbers[i] = getTableId( tableName, tableNames );
|
||||
naturalOrderPropertyTableNumbers[i] = getTableId( tableName, naturalOrderTableNames );
|
||||
}
|
||||
final int tableNumberInSubclass = getTableId( tableName, subclassTableNameClosure );
|
||||
propTableNumbers.add( tableNumberInSubclass );
|
||||
for ( RelationalValueBinding vb : valueBindings ) {
|
||||
if ( vb.isDerived() ) {
|
||||
formulaTableNumbers.add( tableNumberInSubclass );
|
||||
}
|
||||
else {
|
||||
columnTableNumbers.add( tableNumberInSubclass );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
subclassColumnTableNumberClosure = ArrayHelper.toIntArray( columnTableNumbers );
|
||||
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray( propTableNumbers );
|
||||
subclassFormulaTableNumberClosure = ArrayHelper.toIntArray( formulaTableNumbers );
|
||||
// SUBCLASSES
|
||||
|
||||
// DISCRIMINATOR
|
||||
|
||||
if ( entityBinding.isPolymorphic() ) {
|
||||
try {
|
||||
discriminatorValue = entityBinding.getSubEntityBindingId();
|
||||
discriminatorSQLString = discriminatorValue.toString();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new MappingException( "Could not format discriminator value to SQL string", e );
|
||||
}
|
||||
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
|
||||
discriminatorValues = new String[subclassSpan+1];
|
||||
discriminatorValues[subclassSpan] = discriminatorSQLString;
|
||||
notNullColumnTableNumbers = new int[subclassSpan+1];
|
||||
final int id = getTableId(
|
||||
tableNames[0], //the current entitybinding's primary table name
|
||||
subclassTableNameClosure
|
||||
);
|
||||
notNullColumnTableNumbers[subclassSpan] = id;
|
||||
notNullColumnNames = new String[subclassSpan+1];
|
||||
notNullColumnNames[subclassSpan] = subclassTableKeyColumnClosure[id][0];
|
||||
}
|
||||
else {
|
||||
discriminatorValues = null;
|
||||
notNullColumnTableNumbers = null;
|
||||
notNullColumnNames = null;
|
||||
discriminatorValue = null;
|
||||
discriminatorSQLString = null;
|
||||
}
|
||||
|
||||
|
||||
if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) {
|
||||
throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" );
|
||||
}
|
||||
|
||||
final int idColumnSpan = getIdentifierColumnSpan();
|
||||
|
||||
ArrayList<String> tables = new ArrayList<String>();
|
||||
ArrayList keyColumns = new ArrayList();
|
||||
ArrayList keyColumnReaders = new ArrayList();
|
||||
ArrayList keyColumnReaderTemplates = new ArrayList();
|
||||
ArrayList cascadeDeletes = new ArrayList();
|
||||
Iterator<TableSpecification> titer = entityBinding.getTableClosureIterator();
|
||||
while ( titer.hasNext() ){
|
||||
TableSpecification table = titer.next();
|
||||
String tableName = table.getLogicalName().getText(factory.getDialect());
|
||||
tables.add( tableName );
|
||||
String[] keyCols = new String[idColumnSpan];
|
||||
String[] keyColReaders = new String[idColumnSpan];
|
||||
String[] keyColReaderTemplates = new String[idColumnSpan];
|
||||
PrimaryKey primaryKey= table.getPrimaryKey();
|
||||
for ( int k = 0; k < idColumnSpan; k++ ) {
|
||||
org.hibernate.metamodel.spi.relational.Column column = primaryKey.getColumns().get( k );
|
||||
keyCols[k] = column.getColumnName().getText(factory.getDialect());
|
||||
keyColReaders[k] = column.getReadExpr( factory.getDialect() );
|
||||
keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||
for ( int k = 0; k < postOrderSubEntityBindings.length; k++ ) {
|
||||
final EntityBinding eb = postOrderSubEntityBindings[k];
|
||||
subclassClosure[k] = eb.getEntityName();
|
||||
try {
|
||||
if ( eb.isPolymorphic() ) {
|
||||
// we now use subclass ids that are consistent across all
|
||||
// persisters for a class hierarchy, so that the use of
|
||||
// "foo.class = Bar" works in HQL
|
||||
Integer subclassId = eb.getSubEntityBindingId();
|
||||
subclassesByDiscriminatorValue.put( subclassId, eb.getEntityName() );
|
||||
discriminatorValues[k] = subclassId.toString();
|
||||
int id = getTableId(
|
||||
eb.getPrimaryTable().getQualifiedName( factory.getDialect() ),
|
||||
subclassTableNameClosure
|
||||
);
|
||||
notNullColumnTableNumbers[k] = id;
|
||||
notNullColumnNames[k] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
|
||||
if(notNullColumnNames[k] == null){
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new MappingException( "Error parsing discriminator value", e );
|
||||
}
|
||||
keyColumns.add( keyCols );
|
||||
keyColumnReaders.add( keyColReaders );
|
||||
keyColumnReaderTemplates.add( keyColReaderTemplates );
|
||||
cascadeDeletes.add( false && factory.getDialect().supportsCascadeDelete() ); //todo add @OnDelete support
|
||||
}
|
||||
|
||||
//Span of the tables directly mapped by this entity and super-classes, if any
|
||||
coreTableSpan = tables.size();
|
||||
//todo secondary table
|
||||
isNullableTable = new boolean[]{true};
|
||||
naturalOrderTableNames = ArrayHelper.toStringArray( tables );
|
||||
naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray( keyColumns );
|
||||
naturalOrderTableKeyColumnReaders = ArrayHelper.to2DStringArray( keyColumnReaders );
|
||||
naturalOrderTableKeyColumnReaderTemplates = ArrayHelper.to2DStringArray( keyColumnReaderTemplates );
|
||||
naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray( cascadeDeletes );
|
||||
ArrayList subtables = new ArrayList();
|
||||
ArrayList isConcretes = new ArrayList();
|
||||
ArrayList isDeferreds = new ArrayList();
|
||||
ArrayList isLazies = new ArrayList();
|
||||
keyColumns = new ArrayList();
|
||||
//todo add sub class tables here
|
||||
//----------------------------------------------
|
||||
|
||||
tableSpan = -1;
|
||||
tableNames = null;
|
||||
tableKeyColumns = null;
|
||||
tableKeyColumnReaders = null;
|
||||
tableKeyColumnReaderTemplates = null;
|
||||
spaces = null;
|
||||
subclassClosure = null;
|
||||
subclassTableNameClosure = null;
|
||||
subclassTableKeyColumnClosure = null;
|
||||
isClassOrSuperclassTable = null;
|
||||
naturalOrderPropertyTableNumbers = null;
|
||||
propertyTableNumbers = null;
|
||||
subclassPropertyTableNumberClosure = null;
|
||||
subclassColumnTableNumberClosure = null;
|
||||
subclassFormulaTableNumberClosure = null;
|
||||
subclassTableSequentialSelect = null;
|
||||
subclassTableIsLazyClosure = null;
|
||||
discriminatorValues = null;
|
||||
notNullColumnNames = null;
|
||||
notNullColumnTableNumbers = null;
|
||||
constraintOrderedTableNames = null;
|
||||
constraintOrderedKeyColumnNames = null;
|
||||
//-----------------------------
|
||||
initLockers();
|
||||
initSubclassPropertyAliasesMap( entityBinding );
|
||||
|
||||
postConstruct( mapping );
|
||||
}
|
||||
|
||||
protected boolean isNullableTable(int j) {
|
||||
if ( j < coreTableSpan ) {
|
||||
return false;
|
||||
|
||||
|
||||
private void resolvePkColumnNames(SessionFactoryImplementor factory, PrimaryKey primaryKey, String[] columns, String[] readers, String[] templates) {
|
||||
for ( int k = 0; k < primaryKey.getColumnSpan(); k++ ) {
|
||||
org.hibernate.metamodel.spi.relational.Column column = primaryKey.getColumns().get( k );
|
||||
columns[k] = column.getColumnName().getText( factory.getDialect() );
|
||||
readers[k] = column.getReadExpr( factory.getDialect() );
|
||||
templates[k] = column.getTemplate(
|
||||
factory.getDialect(),
|
||||
factory.getSqlFunctionRegistry()
|
||||
);
|
||||
}
|
||||
return isNullableTable[j - coreTableSpan];
|
||||
}
|
||||
|
||||
protected boolean isNullableTable(int j) {
|
||||
return j >= coreTableSpan && isNullableTable[j - coreTableSpan];
|
||||
}
|
||||
|
||||
protected boolean isSubclassTableSequentialSelect(int j) {
|
||||
|
@ -693,14 +1110,12 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
throw new JDBCException( "could not load by id: " + MessageHelper.infoString(this, id), sqle );
|
||||
}
|
||||
}*/
|
||||
private static final void reverse(Object[] objects, int len) {
|
||||
private static void reverse(Object[] objects, int len) {
|
||||
Object[] temp = new Object[len];
|
||||
for ( int i = 0; i < len; i++ ) {
|
||||
temp[i] = objects[len - i - 1];
|
||||
}
|
||||
for ( int i = 0; i < len; i++ ) {
|
||||
objects[i] = temp[i];
|
||||
}
|
||||
System.arraycopy( temp, 0, objects, 0, len );
|
||||
}
|
||||
|
||||
|
||||
|
@ -714,20 +1129,26 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
*/
|
||||
private static String[] reverse(String[] objects, int n) {
|
||||
|
||||
int size = objects.length;
|
||||
String[] temp = new String[size];
|
||||
final int size = objects.length;
|
||||
final String[] temp = new String[size];
|
||||
|
||||
for ( int i = 0; i < n; i++ ) {
|
||||
temp[i] = objects[n - i - 1];
|
||||
}
|
||||
|
||||
for ( int i = n; i < size; i++ ) {
|
||||
temp[i] = objects[i];
|
||||
}
|
||||
System.arraycopy( objects, n, temp, n, size - n );
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String [] array = {"a", "b", "c", "d", "e"};
|
||||
array = reverse( array, 3 );
|
||||
for(String s : array){
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the first n elements of the incoming array
|
||||
*
|
||||
|
@ -743,9 +1164,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
temp[i] = objects[n - i - 1];
|
||||
}
|
||||
|
||||
for ( int i = n; i < size; i++ ) {
|
||||
temp[i] = objects[i];
|
||||
}
|
||||
System.arraycopy( objects, n, temp, n, size - n );
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
@ -870,7 +1289,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
if ( index == null ) {
|
||||
return null;
|
||||
}
|
||||
return tableNames[propertyTableNumbers[index.intValue()]];
|
||||
return tableNames[propertyTableNumbers[index]];
|
||||
}
|
||||
|
||||
public String[] getConstraintOrderedTableNameClosure() {
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -129,9 +128,9 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
private final String[][] constraintOrderedKeyColumnNames;
|
||||
|
||||
//private final Map propertyTableNumbersByName = new HashMap();
|
||||
private final Map propertyTableNumbersByNameAndSubclass = new HashMap();
|
||||
private final Map<String, Integer> propertyTableNumbersByNameAndSubclass = new HashMap<String, Integer>();
|
||||
|
||||
private final Map sequentialSelectStringsByEntityName = new HashMap();
|
||||
private final Map<String, String> sequentialSelectStringsByEntityName = new HashMap<String, String>();
|
||||
|
||||
private static final Object NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
|
||||
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not null discriminator>");
|
||||
|
@ -546,7 +545,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
isNullables.add(Boolean.FALSE);
|
||||
isLazies.add(Boolean.FALSE);
|
||||
|
||||
for ( SecondaryTable join : entityBinding.getSubclassSecondaryTableClosure() ) {
|
||||
for ( SecondaryTable join : entityBinding.getEntitiesSecondaryTableClosure() ) {
|
||||
final boolean isConcrete = entityBinding.isClassOrSuperclassSecondaryTable( join );
|
||||
isConcretes.add( isConcrete );
|
||||
boolean isDeferred = join.getFetchStyle() != FetchStyle.JOIN;
|
||||
|
@ -672,11 +671,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
//TODO: code duplication with JoinedSubclassEntityPersister
|
||||
|
||||
ArrayList columnJoinNumbers = new ArrayList();
|
||||
ArrayList formulaJoinedNumbers = new ArrayList();
|
||||
ArrayList propertyJoinNumbers = new ArrayList();
|
||||
ArrayList<Integer> columnJoinNumbers = new ArrayList<Integer>();
|
||||
ArrayList<Integer> formulaJoinedNumbers = new ArrayList<Integer>();
|
||||
ArrayList<Integer> propertyJoinNumbers = new ArrayList<Integer>();
|
||||
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||
continue; // skip identifier binding
|
||||
}
|
||||
|
@ -753,18 +752,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
postConstruct( mapping );
|
||||
}
|
||||
|
||||
private static void initializeCustomSql(
|
||||
CustomSQL customSql,
|
||||
int i,
|
||||
String[] sqlStrings,
|
||||
boolean[] callable,
|
||||
ExecuteUpdateResultCheckStyle[] checkStyles) {
|
||||
sqlStrings[i] = customSql != null ? customSql.getSql(): null;
|
||||
callable[i] = sqlStrings[i] != null && customSql.isCallable();
|
||||
checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ?
|
||||
customSql.getCheckStyle() :
|
||||
ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] );
|
||||
}
|
||||
|
||||
protected boolean isInverseTable(int j) {
|
||||
return isInverseTable[j];
|
||||
|
@ -889,9 +876,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
|
||||
String[] subclasses = getSubclassClosure();
|
||||
for ( int i=0; i<subclasses.length; i++ ) {
|
||||
final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclasses[i] );
|
||||
if ( !queryable.isAbstract() ) frag.addValue( queryable.getDiscriminatorSQLValue() );
|
||||
for ( String subclass : subclasses ) {
|
||||
final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclass );
|
||||
if ( !queryable.isAbstract() ) {
|
||||
frag.addValue( queryable.getDiscriminatorSQLValue() );
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder(50)
|
||||
|
@ -966,12 +955,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
private int getSubclassPropertyTableNumber(String propertyName, String entityName) {
|
||||
Type type = propertyMapping.toType(propertyName);
|
||||
if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) return 0;
|
||||
final Integer tabnum = (Integer) propertyTableNumbersByNameAndSubclass.get(entityName + '.' + propertyName);
|
||||
return tabnum==null ? 0 : tabnum.intValue();
|
||||
final Integer tabnum = propertyTableNumbersByNameAndSubclass.get(entityName + '.' + propertyName);
|
||||
return tabnum==null ? 0 : tabnum;
|
||||
}
|
||||
|
||||
protected String getSequentialSelect(String entityName) {
|
||||
return (String) sequentialSelectStringsByEntityName.get(entityName);
|
||||
return sequentialSelectStringsByEntityName.get(entityName);
|
||||
}
|
||||
|
||||
private String generateSequentialSelect(Loadable persister) {
|
||||
|
@ -982,7 +971,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
//figure out which tables need to be fetched
|
||||
AbstractEntityPersister subclassPersister = (AbstractEntityPersister) persister;
|
||||
HashSet tableNumbers = new HashSet();
|
||||
HashSet<Integer> tableNumbers = new HashSet<Integer>();
|
||||
String[] props = subclassPersister.getPropertyNames();
|
||||
String[] classes = subclassPersister.getPropertySubclassNames();
|
||||
for ( int i=0; i<props.length; i++ ) {
|
||||
|
@ -994,7 +983,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
if ( tableNumbers.isEmpty() ) return null;
|
||||
|
||||
//figure out which columns are needed
|
||||
ArrayList columnNumbers = new ArrayList();
|
||||
ArrayList<Integer> columnNumbers = new ArrayList<Integer>();
|
||||
final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
||||
for ( int i=0; i<getSubclassColumnClosure().length; i++ ) {
|
||||
if ( tableNumbers.contains( columnTableNumbers[i] ) ) {
|
||||
|
@ -1003,7 +992,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
|
||||
//figure out which formulas are needed
|
||||
ArrayList formulaNumbers = new ArrayList();
|
||||
ArrayList<Integer> formulaNumbers = new ArrayList<Integer>();
|
||||
final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
|
||||
for ( int i=0; i<getSubclassFormulaTemplateClosure().length; i++ ) {
|
||||
if ( tableNumbers.contains( formulaTableNumbers[i] ) ) {
|
||||
|
@ -1051,7 +1040,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
public String getPropertyTableName(String propertyName) {
|
||||
Integer index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
|
||||
if (index==null) return null;
|
||||
return qualifiedTableNames[ propertyTableNumbers[ index.intValue() ] ];
|
||||
return qualifiedTableNames[ propertyTableNumbers[ index ] ];
|
||||
}
|
||||
|
||||
public void postInstantiate() {
|
||||
|
|
|
@ -53,9 +53,7 @@ import org.hibernate.mapping.Column;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Subclass;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.spi.binding.CustomSQL;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.sql.SelectFragment;
|
||||
|
@ -247,29 +245,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
}
|
||||
|
||||
private static class CustomSQLMetadata {
|
||||
final boolean[] callable;
|
||||
final String[] sqls;
|
||||
final ExecuteUpdateResultCheckStyle[] checkStyles;
|
||||
|
||||
CustomSQLMetadata(String sql, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
|
||||
this.callable = new boolean[] { callable };
|
||||
this.sqls = new String[] { sql };
|
||||
this.checkStyles = new ExecuteUpdateResultCheckStyle[] { checkStyle };
|
||||
}
|
||||
}
|
||||
|
||||
private CustomSQLMetadata parse(CustomSQL customSql) {
|
||||
|
||||
final boolean callable = customSql != null && customSql.isCallable();
|
||||
final String sql = customSql == null ? null: customSql.getSql();
|
||||
final ExecuteUpdateResultCheckStyle checkStyle = customSql == null
|
||||
? ExecuteUpdateResultCheckStyle.COUNT
|
||||
: customSql.getCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable )
|
||||
: customSql.getCheckStyle();
|
||||
return new CustomSQLMetadata( sql, callable, checkStyle );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public UnionSubclassEntityPersister(
|
||||
|
@ -290,27 +266,20 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
|
||||
//Custom SQL
|
||||
{
|
||||
CustomSQLMetadata customSQLMetadata;
|
||||
{
|
||||
customSQLMetadata = parse( entityBinding.getCustomInsert() );
|
||||
customSQLInsert = customSQLMetadata.sqls;
|
||||
insertCallable = customSQLMetadata.callable;
|
||||
insertResultCheckStyles = customSQLMetadata.checkStyles;
|
||||
}
|
||||
{
|
||||
customSQLMetadata = parse( entityBinding.getCustomUpdate() );
|
||||
customSQLUpdate = customSQLMetadata.sqls;
|
||||
updateCallable = customSQLMetadata.callable;
|
||||
updateResultCheckStyles = customSQLMetadata.checkStyles;
|
||||
}
|
||||
{
|
||||
customSQLMetadata = parse( entityBinding.getCustomDelete() );
|
||||
customSQLDelete = customSQLMetadata.sqls;
|
||||
deleteCallable = customSQLMetadata.callable;
|
||||
deleteResultCheckStyles = customSQLMetadata.checkStyles;
|
||||
}
|
||||
}
|
||||
// Custom sql
|
||||
customSQLInsert = new String[1];
|
||||
customSQLUpdate = new String[1];
|
||||
customSQLDelete = new String[1];
|
||||
insertCallable = new boolean[1];
|
||||
updateCallable = new boolean[1];
|
||||
deleteCallable = new boolean[1];
|
||||
insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
|
||||
updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
|
||||
deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
|
||||
|
||||
initializeCustomSql( entityBinding.getCustomInsert(), 0, customSQLInsert, insertCallable, insertResultCheckStyles );
|
||||
initializeCustomSql( entityBinding.getCustomUpdate(), 0, customSQLUpdate, updateCallable, updateResultCheckStyles );
|
||||
initializeCustomSql( entityBinding.getCustomDelete(), 0, customSQLDelete, deleteCallable, deleteResultCheckStyles );
|
||||
//discriminator
|
||||
{
|
||||
discriminatorValue = entityBinding.getSubEntityBindingId();
|
||||
|
@ -329,9 +298,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
entityBinding.getEntityName()
|
||||
);
|
||||
if ( entityBinding.isPolymorphic() ) {
|
||||
Iterable<EntityBinding> iter = entityBinding.getPreOrderSubEntityBindingClosure();
|
||||
int k=1;
|
||||
for(EntityBinding subEntityBinding : iter){
|
||||
for(EntityBinding subEntityBinding : entityBinding.getPreOrderSubEntityBindingClosure()){
|
||||
subclassClosure[k++] = subEntityBinding.getEntityName();
|
||||
subclassByDiscriminatorValue.put( subEntityBinding.getSubEntityBindingId(), subEntityBinding.getEntityName() );
|
||||
}
|
||||
|
@ -351,8 +319,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
|
||||
HashSet<String> subclassTables = new HashSet<String>();
|
||||
Iterable<EntityBinding> iter = entityBinding.getPreOrderSubEntityBindingClosure();
|
||||
for ( EntityBinding subEntityBinding : iter ) {
|
||||
final EntityBinding[] subEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure();
|
||||
for ( EntityBinding subEntityBinding : entityBinding.getPreOrderSubEntityBindingClosure() ) {
|
||||
subclassTables.add( subEntityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ) );
|
||||
}
|
||||
subclassSpaces = ArrayHelper.toStringArray( subclassTables );
|
||||
|
@ -367,12 +335,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
tableNames.add( tableName );
|
||||
keyColumns.add( getIdentifierColumnNames() );
|
||||
}
|
||||
Iterator<EntityBinding> siter = new JoinedIterator<EntityBinding>(
|
||||
new SingletonIterator<EntityBinding>( entityBinding ),
|
||||
iter.iterator()
|
||||
);
|
||||
while ( siter.hasNext() ) {
|
||||
EntityBinding eb = siter.next();
|
||||
EntityBinding[] ebs = ArrayHelper.join( new EntityBinding[]{entityBinding}, subEntityBindings );
|
||||
for(final EntityBinding eb : ebs){
|
||||
TableSpecification tab = eb.getPrimaryTable();
|
||||
if ( isNotAbstractUnionTable( eb ) ) {
|
||||
String tableName = tab.getQualifiedName( factory.getDialect() );
|
||||
|
|
|
@ -412,7 +412,9 @@ public class EntityMetamodel implements Serializable {
|
|||
else {
|
||||
identifierAttributeBindingSpan = 1;
|
||||
}
|
||||
propertySpan = entityBinding.getAttributeBindingClosureSpan() - identifierAttributeBindingSpan;
|
||||
|
||||
final AttributeBinding [] attributeBindings = entityBinding.getAttributeBindingClosure();
|
||||
propertySpan = attributeBindings.length;
|
||||
|
||||
properties = new StandardProperty[propertySpan];
|
||||
List naturalIdNumbers = new ArrayList();
|
||||
|
@ -442,7 +444,7 @@ public class EntityMetamodel implements Serializable {
|
|||
boolean foundUpdateGeneratedValue = false;
|
||||
boolean foundUpdateableNaturalIdProperty = false;
|
||||
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : attributeBindings ) {
|
||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||
// skip the identifier attribute binding
|
||||
continue;
|
||||
|
|
|
@ -124,8 +124,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertFalse( noInheritanceEntityBinding.isPolymorphic() );
|
||||
assertFalse( noInheritanceEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
assertFalse( noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertEquals( 0, noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().length );
|
||||
assertEquals( 0, noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().length );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
|
@ -140,14 +140,17 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( iterator.hasNext() );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
||||
assertFalse( iterator.hasNext() );
|
||||
iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator();
|
||||
assertTrue( iterator.hasNext() );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
||||
assertFalse( iterator.hasNext() );
|
||||
iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator();
|
||||
assertTrue( iterator.hasNext() );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
||||
assertFalse( iterator.hasNext() );
|
||||
|
||||
AttributeBinding[] attributeBindings = noInheritanceEntityBinding.getAttributeBindingClosure();
|
||||
assertTrue( attributeBindings.length > 0 );
|
||||
int index =0;
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] );
|
||||
assertFalse( index < attributeBindings.length );
|
||||
attributeBindings = noInheritanceEntityBinding.getEntitiesAttributeBindingClosure();
|
||||
index = 0;
|
||||
assertTrue( attributeBindings.length > 0 );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] );
|
||||
assertFalse( index < attributeBindings.length );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -198,7 +201,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertEquals( 1, attributeBindingClosure.size() );
|
||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : rootEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding subAttributeBinding : rootEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 4, subAttributeBindings.size() );
|
||||
|
@ -225,23 +228,24 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
Iterator<EntityBinding> subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure();
|
||||
assertTrue( subEntityBindingIterator.length > 0 );
|
||||
int i = 0;
|
||||
if ( isSubclassEntityBindingFirst ) {
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertTrue( i<subEntityBindingIterator.length );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertTrue( i<subEntityBindingIterator.length );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
}
|
||||
else {
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertTrue( i<subEntityBindingIterator.length );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertTrue( i<subEntityBindingIterator.length );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
}
|
||||
assertFalse( subEntityBindingIterator.hasNext() );
|
||||
assertFalse( i<subEntityBindingIterator.length );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -261,19 +265,20 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
Iterator<EntityBinding> subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||
int i =0;
|
||||
assertTrue( subEntityBindingIterator.length > 0 );
|
||||
if ( isSubclassEntityBindingFirst ) {
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
}
|
||||
else {
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||
}
|
||||
assertFalse( subEntityBindingIterator.hasNext() );
|
||||
assertFalse( i < subEntityBindingIterator.length );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -297,8 +302,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( otherSubclassEntityBinding.isPolymorphic() );
|
||||
assertFalse( otherSubclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 );
|
||||
assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
|
@ -314,7 +319,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 2, subAttributeBindings.size() );
|
||||
|
@ -343,14 +348,16 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( subclassEntityBinding.isPolymorphic() );
|
||||
assertTrue( subclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 1, subclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
Iterator<EntityBinding> itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( itSubEntityBindings.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() );
|
||||
assertFalse( itSubEntityBindings.hasNext() );
|
||||
itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( itSubEntityBindings.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() );
|
||||
assertFalse( itSubEntityBindings.hasNext() );
|
||||
EntityBinding[] itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||
int i = 0;
|
||||
assertTrue( i < itSubEntityBindings.length );
|
||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] );
|
||||
assertFalse( i < itSubEntityBindings.length );
|
||||
itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure();
|
||||
i = 0;
|
||||
assertTrue( i < itSubEntityBindings.length );
|
||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] );
|
||||
assertFalse( i < itSubEntityBindings.length );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : subclassEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
|
@ -366,7 +373,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 3, subAttributeBindings.size() );
|
||||
|
@ -396,8 +403,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( subclassOfSubclassEntityBinding.isPolymorphic() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
|
@ -414,7 +421,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 3, subAttributeBindings.size() );
|
||||
|
|
|
@ -28,13 +28,11 @@ import java.util.Date;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class IndexTest extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
public void testIndexManyToOne() throws Exception {
|
||||
|
|
|
@ -58,7 +58,7 @@ public class OrmVersion1SupportedTest extends BaseCoreFunctionalTestCase {
|
|||
@FailureExpectedWithNewMetamodel // This doesn't actually work since this test class requires BMUnitRunner instead of
|
||||
// CustomRunner. Thus, the if block below skips the test if the new metamodel is being used.
|
||||
public void testOrm1Support() {
|
||||
if ( Boolean.getBoolean( USE_NEW_METADATA_MAPPINGS ) ) {
|
||||
if ( isMetadataUsed ) {
|
||||
return;
|
||||
}
|
||||
// need to call buildSessionFactory, because this test is not using org.hibernate.testing.junit4.CustomRunner
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.RequiresDialectFeature;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
|
@ -35,7 +34,6 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class HbmWithIdentityTest extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
public void testManyToOneAndInterface() throws Exception {
|
||||
|
|
|
@ -26,13 +26,11 @@ package org.hibernate.test.collection.ordered.joinedInheritence;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class OrderCollectionOfJoinedHierarchyTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
|
|
|
@ -59,7 +59,7 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
|
||||
@SuppressWarnings( {"UnnecessaryUnboxing", "UnnecessaryBoxing"})
|
||||
@FailureExpectedWithNewMetamodel
|
||||
//@FailureExpectedWithNewMetamodel
|
||||
public class SQLFunctionsTest extends LegacyTestCase {
|
||||
private static final Logger log = Logger.getLogger( SQLFunctionsTest.class );
|
||||
|
||||
|
@ -217,6 +217,7 @@ public class SQLFunctionsTest extends LegacyTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public void testBroken() throws Exception {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.test.naturalid.inheritance;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
@ -36,7 +35,6 @@ import static org.junit.Assert.assertSame;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class InheritedNaturalIdTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
|
|
|
@ -43,7 +43,7 @@ import static org.junit.Assert.assertTrue;
|
|||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
|
||||
public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
public String[] getMappings() {
|
||||
|
@ -82,7 +82,7 @@ public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
|
|||
|
||||
s.close();
|
||||
}
|
||||
|
||||
@FailureExpectedWithNewMetamodel
|
||||
@Test
|
||||
@SuppressWarnings( {"UnnecessaryBoxing"})
|
||||
public void testHqlQueryPlanWithEnabledFilter() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<hibernate-mapping default-lazy="false">
|
||||
<class name="org.hibernate.test.legacy.Blobber" dynamic-update="true">
|
||||
<id name="id">
|
||||
<generator class="hilo"/>
|
||||
<generator class="seqhilo"/>
|
||||
</id>
|
||||
<property name="blob" column="blob_"/>
|
||||
<property name="clob" column="clob_"/>
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.jpa.event.spi.jpa.Callback;
|
||||
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
|
||||
|
@ -62,29 +63,29 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
|||
@Override
|
||||
public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl callbackRegistry) {
|
||||
final EntityBinding entityBinding = (EntityBinding) entityObject;
|
||||
final String entityClassName = entityBinding.getEntity().getClassName();
|
||||
if ( entityClassName == null ) {
|
||||
if ( entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final Class entityClass = classLoaderService.classForName( entityClassName );
|
||||
for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) {
|
||||
callbackRegistry.addEntityCallbacks(
|
||||
entityClass,
|
||||
annotationClass,
|
||||
collectCallbacks( entityBinding, entityClass, annotationClass )
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (ClassLoadingException e) {
|
||||
throw new MappingException( "entity class not found: " + entityClassName, e );
|
||||
final Class entityClass = entityBinding.getEntity().getClassReference();
|
||||
for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) {
|
||||
callbackRegistry.addEntityCallbacks(
|
||||
entityClass,
|
||||
annotationClass,
|
||||
collectCallbacks( entityBinding, entityClass, annotationClass )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private final static Callback[] EMPTY_CALLBACK = new Callback[0];
|
||||
|
||||
private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) {
|
||||
final List<Callback> callbacks = new ArrayList<Callback>();
|
||||
for ( JpaCallbackSource jpaCallbackClass : entityBinding.getJpaCallbackClasses() ) {
|
||||
if ( entityBinding.getJpaCallbackClasses() == null || entityBinding.getJpaCallbackClasses().isEmpty() ) {
|
||||
return EMPTY_CALLBACK;
|
||||
}
|
||||
final int size = entityBinding.getJpaCallbackClasses().size();
|
||||
final Callback[] result = new Callback[size];
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
final JpaCallbackSource jpaCallbackClass = entityBinding.getJpaCallbackClasses().get( i );
|
||||
final Class listenerClass = classLoaderService.classForName( jpaCallbackClass.getName() );
|
||||
final String methodName = jpaCallbackClass.getCallbackMethod( annotationClass );
|
||||
|
||||
|
@ -100,9 +101,9 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
|||
? createListenerCallback( listenerClass, entityClass, methodName )
|
||||
: createBeanCallback( listenerClass, methodName );
|
||||
assert callback != null;
|
||||
callbacks.add(callback);
|
||||
result[i] = callback;
|
||||
}
|
||||
return callbacks.toArray(new Callback[callbacks.size()]);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Callback createListenerCallback(
|
||||
|
@ -141,24 +142,32 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
|||
return null;
|
||||
}
|
||||
|
||||
private Callback createBeanCallback( Class<?> callbackClass,
|
||||
String methodName ) {
|
||||
private Callback createBeanCallback(Class<?> callbackClass,
|
||||
String methodName) {
|
||||
Class<?> callbackSuperclass = callbackClass.getSuperclass();
|
||||
if (callbackSuperclass != null) {
|
||||
Callback callback = createBeanCallback(callbackSuperclass, methodName);
|
||||
if (callback != null) return callback;
|
||||
if ( callbackSuperclass != null ) {
|
||||
Callback callback = createBeanCallback( callbackSuperclass, methodName );
|
||||
if ( callback != null ) {
|
||||
return callback;
|
||||
}
|
||||
}
|
||||
for (Method method : callbackClass.getDeclaredMethods()) {
|
||||
if (!method.getName().equals(methodName)) continue;
|
||||
if (method.getParameterTypes().length != 0) continue;
|
||||
if (!method.isAccessible()) method.setAccessible(true);
|
||||
return new EntityCallback(method);
|
||||
for ( Method method : callbackClass.getDeclaredMethods() ) {
|
||||
if ( !method.getName().equals( methodName ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( method.getParameterTypes().length != 0 ) {
|
||||
continue;
|
||||
}
|
||||
if ( !method.isAccessible() ) {
|
||||
method.setAccessible( true );
|
||||
}
|
||||
return new EntityCallback( method );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
//To change body of implemented methods use File | Settings | File Templates.
|
||||
// N/A
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import javax.persistence.PreRemove;
|
|||
import javax.persistence.PreUpdate;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jpa.event.spi.jpa.Callback;
|
||||
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
|
||||
|
||||
|
@ -59,11 +60,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
|||
|
||||
@Override
|
||||
public boolean hasPostCreateCallbacks(Class entityClass) {
|
||||
return notEmpty( preCreates.get( entityClass ) );
|
||||
}
|
||||
|
||||
private boolean notEmpty(Callback[] callbacks) {
|
||||
return callbacks != null && callbacks.length > 0;
|
||||
return CollectionHelper.isNotEmpty( preCreates.get( entityClass ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,7 +75,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
|||
|
||||
@Override
|
||||
public boolean hasPostUpdateCallbacks(Class entityClass) {
|
||||
return notEmpty( postUpdates.get( entityClass ) );
|
||||
return CollectionHelper.isNotEmpty( postUpdates.get( entityClass ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,7 +90,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
|||
|
||||
@Override
|
||||
public boolean hasPostRemoveCallbacks(Class entityClass) {
|
||||
return notEmpty( postRemoves.get( entityClass ) );
|
||||
return CollectionHelper.isNotEmpty( postRemoves.get( entityClass ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,7 +104,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
|||
}
|
||||
|
||||
private boolean callback(Callback[] callbacks, Object bean) {
|
||||
if ( callbacks != null && callbacks.length != 0 ) {
|
||||
if ( CollectionHelper.isNotEmpty( callbacks ) ) {
|
||||
for ( Callback callback : callbacks ) {
|
||||
callback.performCallback( bean );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue