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) {
|
public static Column getSingleColumn(AttributeBinding attributeBinding) {
|
||||||
if ( !( attributeBinding instanceof SingularAttributeBinding ) ) {
|
if ( !( attributeBinding.getAttribute().isSingular() ) ) {
|
||||||
// TODO verify that's correct (HF)
|
// TODO verify that's correct (HF)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ public class SchemaModificationHelper {
|
||||||
RelationalValueBinding valueBinding = basicAttributeBinding.getRelationalValueBindings().get( 0 );
|
RelationalValueBinding valueBinding = basicAttributeBinding.getRelationalValueBindings().get( 0 );
|
||||||
Value value = valueBinding.getValue();
|
Value value = valueBinding.getValue();
|
||||||
|
|
||||||
if ( !( value instanceof Column ) ) {
|
if ( valueBinding.isDerived() ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,7 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
return enabledFetchProfileNames != null && !enabledFetchProfileNames.isEmpty();
|
return enabledFetchProfileNames != null && !enabledFetchProfileNames.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set getEnabledFetchProfileNames() {
|
public Set<String> getEnabledFetchProfileNames() {
|
||||||
return enabledFetchProfileNames;
|
return enabledFetchProfileNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,21 @@ public final class ArrayHelper {
|
||||||
return list;
|
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) {
|
public static String[] join(String[] x, String[] y) {
|
||||||
String[] result = new String[ x.length + y.length ];
|
String[] result = new String[ x.length + y.length ];
|
||||||
System.arraycopy( x, 0, result, 0, x.length );
|
System.arraycopy( x, 0, result, 0, x.length );
|
||||||
|
@ -181,7 +196,12 @@ public final class ArrayHelper {
|
||||||
}
|
}
|
||||||
return result;
|
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) {
|
public static int[] join(int[] x, int[] y) {
|
||||||
int[] result = new int[ x.length + y.length ];
|
int[] result = new int[ x.length + y.length ];
|
||||||
System.arraycopy( x, 0, result, 0, x.length );
|
System.arraycopy( x, 0, result, 0, x.length );
|
||||||
|
|
|
@ -457,7 +457,7 @@ public class AttributeBuilder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
|
if ( attributeBinding.getAttribute().isSingular() ) {
|
||||||
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||||
|
|
||||||
final PersistentAttributeType jpaAttributeType;
|
final PersistentAttributeType jpaAttributeType;
|
||||||
|
|
|
@ -531,7 +531,7 @@ public class Binder {
|
||||||
// ensure version is non-nullable
|
// ensure version is non-nullable
|
||||||
for ( RelationalValueBinding valueBinding : version.getVersioningAttributeBinding()
|
for ( RelationalValueBinding valueBinding : version.getVersioningAttributeBinding()
|
||||||
.getRelationalValueBindings() ) {
|
.getRelationalValueBindings() ) {
|
||||||
if ( valueBinding.getValue() instanceof Column ) {
|
if ( !valueBinding.isDerived() ) {
|
||||||
( (Column) valueBinding.getValue() ).setNullable( false );
|
( (Column) valueBinding.getValue() ).setNullable( false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2283,7 +2283,7 @@ public class Binder {
|
||||||
primaryKey.addColumn( foreignKeyColumn );
|
primaryKey.addColumn( foreignKeyColumn );
|
||||||
}
|
}
|
||||||
for ( final RelationalValueBinding elementValueBinding : elementBinding.getRelationalValueBindings() ) {
|
for ( final RelationalValueBinding elementValueBinding : elementBinding.getRelationalValueBindings() ) {
|
||||||
if ( elementValueBinding.getValue() instanceof Column && !elementValueBinding.isNullable() ) {
|
if ( !elementValueBinding.isDerived() && !elementValueBinding.isNullable() ) {
|
||||||
primaryKey.addColumn( (Column) elementValueBinding.getValue() );
|
primaryKey.addColumn( (Column) elementValueBinding.getValue() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3023,7 +3023,7 @@ public class Binder {
|
||||||
primaryKey.addColumn( foreignKeyColumn );
|
primaryKey.addColumn( foreignKeyColumn );
|
||||||
}
|
}
|
||||||
for ( RelationalValueBinding relationalValueBinding : indexBinding.getRelationalValueBindings() ) {
|
for ( RelationalValueBinding relationalValueBinding : indexBinding.getRelationalValueBindings() ) {
|
||||||
if ( relationalValueBinding.getValue() instanceof Column ) {
|
if ( !relationalValueBinding.isDerived() ) {
|
||||||
primaryKey.addColumn( (Column) relationalValueBinding.getValue() );
|
primaryKey.addColumn( (Column) relationalValueBinding.getValue() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,16 +367,16 @@ public class BindHelper {
|
||||||
|
|
||||||
private static AttributeBinding getRecursiveAttributeBinding(
|
private static AttributeBinding getRecursiveAttributeBinding(
|
||||||
EntityBinding entityBinding, String propertyPath) {
|
EntityBinding entityBinding, String propertyPath) {
|
||||||
Iterable<AttributeBinding> attributeBindings
|
// Iterable<AttributeBinding> attributeBindings
|
||||||
= entityBinding.getAttributeBindingClosure();
|
// = entityBinding.getAttributeBindingClosure();
|
||||||
StringTokenizer st = new StringTokenizer( propertyPath, "." );
|
// StringTokenizer st = new StringTokenizer( propertyPath, "." );
|
||||||
AttributeBinding attributeBinding = null;
|
AttributeBinding attributeBinding = null;
|
||||||
while ( st.hasMoreElements() ) {
|
// while ( st.hasMoreElements() ) {
|
||||||
String element = st.nextToken();
|
// String element = st.nextToken();
|
||||||
for ( AttributeBinding binding : attributeBindings ) {
|
// for ( AttributeBinding binding : attributeBindings ) {
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return attributeBinding;
|
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;
|
package org.hibernate.metamodel.internal.source.hbm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.jaxb.spi.hbm.EntityElement;
|
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.JaxbJoinedSubclassElement;
|
||||||
|
import org.hibernate.jaxb.spi.hbm.JaxbKeyElement;
|
||||||
import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement;
|
import org.hibernate.jaxb.spi.hbm.JaxbSubclassElement;
|
||||||
import org.hibernate.jaxb.spi.hbm.TableInformationSource;
|
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.EntitySource;
|
||||||
import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource;
|
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.SubclassEntitySource;
|
||||||
import org.hibernate.metamodel.spi.source.TableSpecificationSource;
|
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 {
|
public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implements SubclassEntitySource {
|
||||||
private final EntitySource container;
|
private final EntitySource container;
|
||||||
private final TableSpecificationSource primaryTable;
|
private final TableSpecificationSource primaryTable;
|
||||||
|
private final boolean isJoinedSubclass;
|
||||||
|
private final JaxbKeyElement key;
|
||||||
|
private final List<PrimaryKeyJoinColumnSource> primaryKeyJoinColumnSources;
|
||||||
protected SubclassEntitySourceImpl(
|
protected SubclassEntitySourceImpl(
|
||||||
MappingDocument sourceMappingDocument,
|
MappingDocument sourceMappingDocument,
|
||||||
EntityElement entityElement,
|
EntityElement entityElement,
|
||||||
|
@ -50,6 +57,45 @@ public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implement
|
||||||
this.primaryTable = TableInformationSource.class.isInstance( entityElement )
|
this.primaryTable = TableInformationSource.class.isInstance( entityElement )
|
||||||
? Helper.createTableSource( sourceMappingDocument(), (TableInformationSource) entityElement, this )
|
? Helper.createTableSource( sourceMappingDocument(), (TableInformationSource) entityElement, this )
|
||||||
: null;
|
: 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();
|
afterInstantiation();
|
||||||
}
|
}
|
||||||
|
@ -73,14 +119,14 @@ public class SubclassEntitySourceImpl extends AbstractEntitySourceImpl implement
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getJoinedForeignKeyName() {
|
public String getJoinedForeignKeyName() {
|
||||||
if ( JaxbJoinedSubclassElement.class.isInstance( entityElement() ) ) {
|
if ( isJoinedSubclass ) {
|
||||||
return ( (JaxbJoinedSubclassElement) entityElement() ).getKey().getForeignKey();
|
return key.getForeignKey();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PrimaryKeyJoinColumnSource> getPrimaryKeyJoinColumnSources() {
|
public List<PrimaryKeyJoinColumnSource> getPrimaryKeyJoinColumnSources() {
|
||||||
return null;
|
return primaryKeyJoinColumnSources;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
|
||||||
@Override
|
@Override
|
||||||
public AttributeBinding locateAttributeBinding(List<Value> values) {
|
public AttributeBinding locateAttributeBinding(List<Value> values) {
|
||||||
for ( AttributeBinding attributeBinding : attributeBindingMapInternal().values() ) {
|
for ( AttributeBinding attributeBinding : attributeBindingMapInternal().values() ) {
|
||||||
if ( !SingularAttributeBinding.class.isInstance( attributeBinding ) ) {
|
if ( !attributeBinding.getAttribute().isSingular() ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SingularAttributeBinding basicAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
SingularAttributeBinding basicAttributeBinding = (SingularAttributeBinding) attributeBinding;
|
||||||
|
|
|
@ -24,18 +24,16 @@
|
||||||
package org.hibernate.metamodel.spi.binding;
|
package org.hibernate.metamodel.spi.binding;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
|
||||||
import org.hibernate.internal.FilterConfiguration;
|
import org.hibernate.internal.FilterConfiguration;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.ValueHolder;
|
import org.hibernate.internal.util.ValueHolder;
|
||||||
|
@ -158,7 +156,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPolymorphic() {
|
public boolean isPolymorphic() {
|
||||||
return superEntityBinding != null ||
|
return !isRoot() ||
|
||||||
hierarchyDetails.getEntityDiscriminator() != null ||
|
hierarchyDetails.getEntityDiscriminator() != null ||
|
||||||
!subEntityBindings.isEmpty();
|
!subEntityBindings.isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -167,71 +165,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
||||||
return !subEntityBindings.isEmpty();
|
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() {
|
public Entity getEntity() {
|
||||||
return entity;
|
return entity;
|
||||||
|
@ -317,79 +251,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
||||||
public void addSecondaryTable(SecondaryTable secondaryTable) {
|
public void addSecondaryTable(SecondaryTable secondaryTable) {
|
||||||
secondaryTables.put( secondaryTable.getSecondaryTableReference().getLogicalName().getText(), secondaryTable );
|
secondaryTables.put( secondaryTable.getSecondaryTableReference().getLogicalName().getText(), secondaryTable );
|
||||||
}
|
}
|
||||||
|
public Map<String, SecondaryTable> getSecondaryTables() {
|
||||||
public int getSecondaryTableClosureSpan() {
|
return secondaryTables;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,27 +532,56 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributeBinding locateAttributeBindingByPath(String path) {
|
|
||||||
if ( path == null ) {
|
public void setJpaCallbackClasses(List<JpaCallbackSource> jpaCallbackClasses) {
|
||||||
throw new IllegalArgumentException( "path must be non-null." );
|
this.jpaCallbackClasses = jpaCallbackClasses;
|
||||||
}
|
}
|
||||||
final String pathDelimiter = "\\.";
|
|
||||||
String[] tokens = path.split( pathDelimiter );
|
public Iterable<JpaCallbackSource> getJpaCallbackClasses() {
|
||||||
AttributeBinding attributeBinding = locateAttributeBinding( tokens[ 0 ] );
|
return jpaCallbackClasses;
|
||||||
if ( attributeBinding == null ) {
|
|
||||||
return superEntityBinding == null ? null : superEntityBinding.locateAttributeBindingByPath( path );
|
|
||||||
}
|
}
|
||||||
for ( int i = 1 ; i < tokens.length && attributeBinding != null ; i++ ) {
|
//--------------------------
|
||||||
if ( ! attributeBinding.getAttribute().isSingular() ||
|
//meta methods for persister , to improve performance, these methods below should really be replaced as ValueHolder
|
||||||
! ( (SingularAttribute) attributeBinding.getAttribute() ).getSingularAttributeType().isAggregate() ) {
|
//and only be called in persister -- after build MetadataImpl
|
||||||
// TODO: improve this message!!!
|
|
||||||
throw new MappingException( "improve this!!!" );
|
|
||||||
|
public TableSpecification[] getTableClosure() {
|
||||||
|
if ( isRoot() ) {
|
||||||
|
return new TableSpecification[] { getPrimaryTable() };
|
||||||
}
|
}
|
||||||
AttributeBindingContainer attributeBindingContainer = (AttributeBindingContainer) attributeBinding;
|
return ArrayHelper.join( superEntityBinding.getTableClosure(), getPrimaryTable() );
|
||||||
attributeBinding = attributeBindingContainer.locateAttributeBinding( tokens[ i ] );
|
|
||||||
}
|
}
|
||||||
return attributeBinding;
|
|
||||||
|
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
|
* Gets the number of attribute bindings defined on this class, including the
|
||||||
|
@ -700,9 +592,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
||||||
*/
|
*/
|
||||||
public int getAttributeBindingClosureSpan() {
|
public int getAttributeBindingClosureSpan() {
|
||||||
// TODO: update account for join attribute bindings
|
// TODO: update account for join attribute bindings
|
||||||
return superEntityBinding != null ?
|
return isRoot() ? getNonIdAttributeBindingClosure().length :
|
||||||
superEntityBinding.getAttributeBindingClosureSpan() + attributeBindingMap.size() :
|
superEntityBinding.getAttributeBindingClosureSpan() + getNonIdAttributeBindingClosure().length;
|
||||||
attributeBindingMap.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -712,19 +603,127 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
|
||||||
*
|
*
|
||||||
* @return The attribute bindings.
|
* @return The attribute bindings.
|
||||||
*/
|
*/
|
||||||
public Iterable<AttributeBinding> getAttributeBindingClosure() {
|
public AttributeBinding[] getAttributeBindingClosure() {
|
||||||
// TODO: update size to account for joins
|
// TODO: update size to account for joins
|
||||||
Iterable<AttributeBinding> iterable;
|
if ( isRoot() ) {
|
||||||
if ( superEntityBinding != null ) {
|
return getNonIdAttributeBindingClosure();
|
||||||
List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>( 2 );
|
|
||||||
iterables.add( superEntityBinding.getAttributeBindingClosure() );
|
|
||||||
iterables.add( attributeBindings() );
|
|
||||||
iterable = new JoinedIterable<AttributeBinding>( iterables );
|
|
||||||
}
|
}
|
||||||
else {
|
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
|
* sub-EntityBinding, starting from the root of the hierarchy; includes
|
||||||
* the identifier and attribute bindings defined as part of a join.
|
* the identifier and attribute bindings defined as part of a join.
|
||||||
*/
|
*/
|
||||||
public Iterable<AttributeBinding> getSubEntityAttributeBindingClosure() {
|
public AttributeBinding[] getEntitiesAttributeBindingClosure() {
|
||||||
List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>();
|
AttributeBinding[] results = getAttributeBindingClosure();
|
||||||
iterables.add( getAttributeBindingClosure() );
|
|
||||||
for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) {
|
for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) {
|
||||||
// only add attribute bindings declared for the subEntityBinding
|
// 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
|
// 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 ) {
|
public boolean isClassOrSuperclassSecondaryTable(SecondaryTable secondaryTable) {
|
||||||
return new SingletonIterator<TableSpecification>( getPrimaryTable() );
|
String secondaryTableName = secondaryTable.getSecondaryTableReference().getLogicalName().getText();
|
||||||
}
|
return secondaryTables.containsKey( secondaryTableName ) ||
|
||||||
else {
|
( superEntityBinding != null && superEntityBinding.isClassOrSuperclassSecondaryTable( secondaryTable ) );
|
||||||
return new JoinedIterator<TableSpecification>(
|
|
||||||
superEntityBinding.getTableClosureIterator(),
|
|
||||||
new SingletonIterator<TableSpecification>( getPrimaryTable() )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public Iterator getKeyClosureIterator(){
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJpaCallbackClasses(List<JpaCallbackSource> jpaCallbackClasses) {
|
public int getSecondaryTableNumber(SingularAttributeBinding attributeBinding) {
|
||||||
this.jpaCallbackClasses = jpaCallbackClasses;
|
if ( attributeBinding.getRelationalValueBindings().isEmpty() ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<JpaCallbackSource> getJpaCallbackClasses() {
|
|
||||||
return jpaCallbackClasses;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,14 @@ public class EntityIdentifier {
|
||||||
return entityIdentifierBinding.isIdentifierAttributeBinding( attributeBinding );
|
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() {
|
public String getUnsavedValue() {
|
||||||
ensureBound();
|
ensureBound();
|
||||||
return entityIdentifierBinding.getUnsavedValue();
|
return entityIdentifierBinding.getUnsavedValue();
|
||||||
|
|
|
@ -25,14 +25,11 @@ package org.hibernate.metamodel.spi.relational;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.internal.util.collections.JoinedIterable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Strong Liu <stliu@hibernate.org>
|
* @author Strong Liu <stliu@hibernate.org>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -702,7 +702,7 @@ public abstract class AbstractCollectionPersister
|
||||||
// isSorted = collection.isSorted();
|
// isSorted = collection.isSorted();
|
||||||
isArray = collectionType.isArrayType();
|
isArray = collectionType.isArrayType();
|
||||||
isPrimitiveArray =
|
isPrimitiveArray =
|
||||||
collectionType.isArrayType() &&
|
isArray &&
|
||||||
PrimitiveType.class.isInstance(
|
PrimitiveType.class.isInstance(
|
||||||
collection.getPluralAttributeElementBinding()
|
collection.getPluralAttributeElementBinding()
|
||||||
.getHibernateTypeDescriptor()
|
.getHibernateTypeDescriptor()
|
||||||
|
@ -840,9 +840,10 @@ public abstract class AbstractCollectionPersister
|
||||||
indexColumnIsSettable = new boolean[indexSpan];
|
indexColumnIsSettable = new boolean[indexSpan];
|
||||||
indexColumnAliases = new String[indexSpan];
|
indexColumnAliases = new String[indexSpan];
|
||||||
for ( int i = 0 ; i < indexSpan ; i++ ) {
|
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 );
|
indexColumnAliases[ i ] = value.getAlias( dialect, null );
|
||||||
if ( value instanceof Column ) {
|
if ( !rb.isDerived() ) {
|
||||||
indexColumnIsSettable[ i ] = true;
|
indexColumnIsSettable[ i ] = true;
|
||||||
Column column = ( Column ) value;
|
Column column = ( Column ) value;
|
||||||
indexColumnNames[ i ] = column.getColumnName().getText( dialect );
|
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.EntityEntry;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.engine.spi.PersistenceContext.NaturalIdHelper;
|
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.Binder;
|
||||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.FilterConfiguration;
|
|
||||||
import org.hibernate.internal.FilterHelper;
|
import org.hibernate.internal.FilterHelper;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.ValueHolder;
|
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.Expectation;
|
||||||
import org.hibernate.jdbc.Expectations;
|
import org.hibernate.jdbc.Expectations;
|
||||||
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
import org.hibernate.jdbc.TooManyRowsAffectedException;
|
||||||
import org.hibernate.loader.entity.BatchingEntityLoader;
|
|
||||||
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
|
||||||
import org.hibernate.loader.entity.CascadeEntityLoader;
|
import org.hibernate.loader.entity.CascadeEntityLoader;
|
||||||
import org.hibernate.loader.entity.EntityLoader;
|
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.CompositeAttributeBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
|
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.EntityBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.Fetchable;
|
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.PluralAttributeBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
import org.hibernate.metamodel.spi.binding.PluralAttributeElementBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
|
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.binding.SingularAttributeBinding;
|
||||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||||
|
import org.hibernate.metamodel.spi.relational.PrimaryKey;
|
||||||
import org.hibernate.metamodel.spi.relational.Value;
|
import org.hibernate.metamodel.spi.relational.Value;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.property.BackrefPropertyAccessor;
|
import org.hibernate.property.BackrefPropertyAccessor;
|
||||||
|
@ -169,6 +166,7 @@ public abstract class AbstractEntityPersister
|
||||||
private final String[] rootTableKeyColumnReaders;
|
private final String[] rootTableKeyColumnReaders;
|
||||||
private final String[] rootTableKeyColumnReaderTemplates;
|
private final String[] rootTableKeyColumnReaderTemplates;
|
||||||
private final String[] identifierAliases;
|
private final String[] identifierAliases;
|
||||||
|
//how many columns are mapped by the identifier?
|
||||||
private final int identifierColumnSpan;
|
private final int identifierColumnSpan;
|
||||||
private final String versionColumnName;
|
private final String versionColumnName;
|
||||||
private final boolean hasFormulaProperties;
|
private final boolean hasFormulaProperties;
|
||||||
|
@ -237,8 +235,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
private final Set affectingFetchProfileNames = new HashSet();
|
private final Set affectingFetchProfileNames = new HashSet();
|
||||||
|
|
||||||
private final Map uniqueKeyLoaders = new HashMap();
|
private final Map<String, EntityLoader> uniqueKeyLoaders = new HashMap<String, EntityLoader>();
|
||||||
private final Map lockers = new HashMap();
|
private final Map<LockMode, LockingStrategy> lockers = new HashMap<LockMode, LockingStrategy>();
|
||||||
private final Map loaders = new HashMap();
|
private final Map loaders = new HashMap();
|
||||||
|
|
||||||
// SQL strings
|
// SQL strings
|
||||||
|
@ -280,8 +278,8 @@ public abstract class AbstractEntityPersister
|
||||||
private final String temporaryIdTableName;
|
private final String temporaryIdTableName;
|
||||||
private final String temporaryIdTableDDL;
|
private final String temporaryIdTableDDL;
|
||||||
|
|
||||||
private final Map subclassPropertyAliases = new HashMap();
|
private final Map<String, String[]> subclassPropertyAliases = new HashMap<String, String[]>();
|
||||||
private final Map subclassPropertyColumnNames = new HashMap();
|
private final Map<String, String[]> subclassPropertyColumnNames = new HashMap<String, String[]>();
|
||||||
|
|
||||||
protected final BasicEntityPropertyMapping propertyMapping;
|
protected final BasicEntityPropertyMapping propertyMapping;
|
||||||
|
|
||||||
|
@ -390,6 +388,19 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
return result;
|
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() {
|
protected String getSQLSnapshotSelectString() {
|
||||||
return sqlSnapshotSelectString;
|
return sqlSnapshotSelectString;
|
||||||
|
@ -866,9 +877,11 @@ public abstract class AbstractEntityPersister
|
||||||
rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan];
|
rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan];
|
||||||
identifierAliases = new String[identifierColumnSpan];
|
identifierAliases = new String[identifierColumnSpan];
|
||||||
|
|
||||||
|
for ( int i = 0; i < identifierColumnSpan; i++ ) {
|
||||||
int i = 0;
|
org.hibernate.metamodel.spi.relational.Column col = entityBinding.getPrimaryTable()
|
||||||
for ( org.hibernate.metamodel.spi.relational.Column col : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) {
|
.getPrimaryKey()
|
||||||
|
.getColumns()
|
||||||
|
.get( i );
|
||||||
rootTableKeyColumnNames[i] = col.getColumnName().getText( factory.getDialect() );
|
rootTableKeyColumnNames[i] = col.getColumnName().getText( factory.getDialect() );
|
||||||
if ( col.getReadFragment() == null ) {
|
if ( col.getReadFragment() == null ) {
|
||||||
rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i];
|
rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i];
|
||||||
|
@ -878,8 +891,7 @@ public abstract class AbstractEntityPersister
|
||||||
rootTableKeyColumnReaders[i] = col.getReadFragment();
|
rootTableKeyColumnReaders[i] = col.getReadFragment();
|
||||||
rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( col.getReadFragment(), factory );
|
rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( col.getReadFragment(), factory );
|
||||||
}
|
}
|
||||||
identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getPrimaryTable() );
|
identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getHierarchyDetails().getRootEntityBinding().getPrimaryTable() );
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VERSION
|
// VERSION
|
||||||
|
@ -937,7 +949,7 @@ public abstract class AbstractEntityPersister
|
||||||
List<String[]> lazyColAliases = new ArrayList<String[]>();
|
List<String[]> lazyColAliases = new ArrayList<String[]>();
|
||||||
|
|
||||||
|
|
||||||
i = 0;
|
int i = 0;
|
||||||
boolean foundFormula = false;
|
boolean foundFormula = false;
|
||||||
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
||||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||||
|
@ -1042,7 +1054,7 @@ public abstract class AbstractEntityPersister
|
||||||
List<Boolean> columnSelectables = new ArrayList<Boolean>();
|
List<Boolean> columnSelectables = new ArrayList<Boolean>();
|
||||||
List<Boolean> propNullables = 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 ) ) {
|
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||||
// entity identifier is not considered a "normal" property
|
// entity identifier is not considered a "normal" property
|
||||||
continue;
|
continue;
|
||||||
|
@ -1835,7 +1847,7 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
private LockingStrategy getLocker(LockMode lockMode) {
|
private LockingStrategy getLocker(LockMode lockMode) {
|
||||||
return ( LockingStrategy ) lockers.get( lockMode );
|
return lockers.get( lockMode );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock(
|
public void lock(
|
||||||
|
@ -2085,7 +2097,7 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getSubclassPropertyColumnAliases(String propertyName, String suffix) {
|
public String[] getSubclassPropertyColumnAliases(String propertyName, String suffix) {
|
||||||
String rawAliases[] = ( String[] ) subclassPropertyAliases.get( propertyName );
|
String rawAliases[] = subclassPropertyAliases.get( propertyName );
|
||||||
|
|
||||||
if ( rawAliases == null ) {
|
if ( rawAliases == null ) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -2097,10 +2109,10 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public String[] getSubclassPropertyColumnNames(String propertyName) {
|
public String[] getSubclassPropertyColumnNames(String propertyName) {
|
||||||
//TODO: should we allow suffixes on these ?
|
//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
|
// ALIASES
|
||||||
|
|
||||||
// TODO: Fix when subclasses are working (HHH-6337)
|
// 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'
|
// aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id'
|
||||||
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
|
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
|
||||||
|
@ -2266,10 +2278,12 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
protected static boolean isIdentifierAttributeBinding(final AttributeBinding prop){
|
||||||
private void internalInitSubclassPropertyAliasesMap(String path, Iterable<AttributeBinding> attributeBindings) {
|
return prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop );
|
||||||
|
}
|
||||||
|
private void internalInitSubclassPropertyAliasesMap(String path, AttributeBinding[] attributeBindings) {
|
||||||
for ( AttributeBinding prop : attributeBindings ) {
|
for ( AttributeBinding prop : attributeBindings ) {
|
||||||
if ( prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop ) ) {
|
if ( isIdentifierAttributeBinding( prop ) ) {
|
||||||
// ID propertie aliases are dealt with elsewhere.
|
// ID propertie aliases are dealt with elsewhere.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2295,12 @@ public abstract class AbstractEntityPersister
|
||||||
String propname = path == null ? prop.getAttribute().getName() : path + "." + prop.getAttribute().getName();
|
String propname = path == null ? prop.getAttribute().getName() : path + "." + prop.getAttribute().getName();
|
||||||
if ( prop instanceof CompositeAttributeBinding ) {
|
if ( prop instanceof CompositeAttributeBinding ) {
|
||||||
CompositeAttributeBinding component = (CompositeAttributeBinding) prop;
|
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 {
|
else {
|
||||||
int span = singularProp.getRelationalValueBindings().size();
|
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
|
&& propertyName.indexOf('.')<0; //ugly little workaround for fact that createUniqueKeyLoaders() does not handle component properties
|
||||||
|
|
||||||
if ( useStaticLoader ) {
|
if ( useStaticLoader ) {
|
||||||
return ( EntityLoader ) uniqueKeyLoaders.get( propertyName );
|
return uniqueKeyLoaders.get( propertyName );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createUniqueKeyLoader(
|
return createUniqueKeyLoader(
|
||||||
|
@ -3898,12 +3917,13 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAffectedByEnabledFetchProfiles(SessionImplementor session) {
|
private boolean isAffectedByEnabledFetchProfiles(SessionImplementor session) {
|
||||||
Iterator itr = session.getLoadQueryInfluencers().getEnabledFetchProfileNames().iterator();
|
if ( session.getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
|
||||||
while ( itr.hasNext() ) {
|
for ( String name : session.getLoadQueryInfluencers().getEnabledFetchProfileNames() ) {
|
||||||
if ( affectingFetchProfileNames.contains( itr.next() ) ) {
|
if ( affectingFetchProfileNames.contains( name ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3962,8 +3982,7 @@ public abstract class AbstractEntityPersister
|
||||||
protected final boolean[] getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection) {
|
protected final boolean[] getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection) {
|
||||||
final boolean[] propsToUpdate = new boolean[ entityMetamodel.getPropertySpan() ];
|
final boolean[] propsToUpdate = new boolean[ entityMetamodel.getPropertySpan() ];
|
||||||
final boolean[] updateability = getPropertyUpdateability(); //no need to check laziness, dirty checking handles that
|
final boolean[] updateability = getPropertyUpdateability(); //no need to check laziness, dirty checking handles that
|
||||||
for ( int j = 0; j < dirtyProperties.length; j++ ) {
|
for ( int property : dirtyProperties ) {
|
||||||
int property = dirtyProperties[j];
|
|
||||||
if ( updateability[property] ) {
|
if ( updateability[property] ) {
|
||||||
propsToUpdate[property] = true;
|
propsToUpdate[property] = true;
|
||||||
}
|
}
|
||||||
|
@ -4058,8 +4077,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
private void logDirtyProperties(int[] props) {
|
private void logDirtyProperties(int[] props) {
|
||||||
if ( LOG.isTraceEnabled() ) {
|
if ( LOG.isTraceEnabled() ) {
|
||||||
for ( int i = 0; i < props.length; i++ ) {
|
for ( int prop : props ) {
|
||||||
String propertyName = entityMetamodel.getProperties()[ props[i] ].getName();
|
String propertyName = entityMetamodel.getProperties()[prop].getName();
|
||||||
LOG.trace( StringHelper.qualify( getEntityName(), propertyName ) + " is dirty" );
|
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 {
|
public Boolean isTransient(Object entity, SessionImplementor session) throws HibernateException {
|
||||||
final Serializable id;
|
final Serializable id = canExtractIdOutOfEntity() ? getIdentifier( entity, session ) : null;
|
||||||
if ( canExtractIdOutOfEntity() ) {
|
|
||||||
id = getIdentifier( entity, session );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
id = null;
|
|
||||||
}
|
|
||||||
// we *always* assume an instance with a null
|
// we *always* assume an instance with a null
|
||||||
// identifier or no identifier property is unsaved!
|
// identifier or no identifier property is unsaved!
|
||||||
if ( id == null ) {
|
if ( id == null ) {
|
||||||
|
@ -4276,7 +4289,6 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isModifiableEntity(EntityEntry entry) {
|
private boolean isModifiableEntity(EntityEntry entry) {
|
||||||
|
|
||||||
return ( entry == null ? isMutable() : entry.isModifiableEntity() );
|
return ( entry == null ? isMutable() : entry.isModifiableEntity() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4566,6 +4578,20 @@ public abstract class AbstractEntityPersister
|
||||||
return temporaryIdTableDDL;
|
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() {
|
protected int getPropertySpan() {
|
||||||
return entityMetamodel.getPropertySpan();
|
return entityMetamodel.getPropertySpan();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
|
@ -35,6 +36,7 @@ import org.hibernate.MappingException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||||
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.OptimisticLockStyle;
|
import org.hibernate.engine.OptimisticLockStyle;
|
||||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
@ -50,9 +52,12 @@ import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.mapping.Subclass;
|
import org.hibernate.mapping.Subclass;
|
||||||
import org.hibernate.mapping.Table;
|
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.EntityBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
|
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||||
import org.hibernate.metamodel.spi.relational.DerivedValue;
|
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.PrimaryKey;
|
||||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||||
import org.hibernate.sql.CaseFragment;
|
import org.hibernate.sql.CaseFragment;
|
||||||
|
@ -67,32 +72,192 @@ import org.hibernate.type.*;
|
||||||
*/
|
*/
|
||||||
public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
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 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[] 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[][] naturalOrderTableKeyColumns;
|
||||||
|
private final String[][] tableKeyColumns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as above, just for different column metadata.
|
||||||
|
*/
|
||||||
|
private final String[][] tableKeyColumnReaders;
|
||||||
private final String[][] naturalOrderTableKeyColumnReaders;
|
private final String[][] naturalOrderTableKeyColumnReaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as above, just for different column metadata.
|
||||||
|
*/
|
||||||
|
private final String[][] tableKeyColumnReaderTemplates;
|
||||||
private final String[][] naturalOrderTableKeyColumnReaderTemplates;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
private final int[] subclassPropertyTableNumberClosure;
|
||||||
|
|
||||||
// the closure of all columns used by the entire hierarchy including
|
// 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 Object discriminatorValue;
|
||||||
private final String discriminatorSQLString;
|
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"
|
// only contains values for SecondaryTables, ie. not tables part of the "coreTableSpan"
|
||||||
private final boolean[] isNullableTable;
|
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:
|
//INITIALIZATION:
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
@SuppressWarnings( {"UnusedDeclaration"})
|
||||||
public JoinedSubclassEntityPersister(
|
public JoinedSubclassEntityPersister(
|
||||||
|
@ -149,14 +319,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
discriminatorSQLString = null;
|
discriminatorSQLString = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) {
|
assertOptimisticLockStyle();
|
||||||
throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
//MULTITABLES
|
//MULTITABLES
|
||||||
|
|
||||||
final int idColumnSpan = getIdentifierColumnSpan();
|
final int idColumnSpan = getIdentifierColumnSpan();
|
||||||
|
|
||||||
ArrayList tables = new ArrayList();
|
ArrayList tables = new ArrayList();
|
||||||
ArrayList keyColumns = new ArrayList();
|
ArrayList keyColumns = new ArrayList();
|
||||||
ArrayList keyColumnReaders = 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
|
//Span of the tables directly mapped by this entity and super-classes, if any
|
||||||
coreTableSpan = tables.size();
|
coreTableSpan = tables.size();
|
||||||
|
|
||||||
isNullableTable = new boolean[persistentClass.getJoinClosureSpan()];
|
isNullableTable = new boolean[persistentClass.getJoinClosureSpan()];
|
||||||
|
|
||||||
int tableIndex = 0;
|
int tableIndex = 0;
|
||||||
|
@ -241,7 +407,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
ArrayList isConcretes = new ArrayList();
|
ArrayList isConcretes = new ArrayList();
|
||||||
ArrayList isDeferreds = new ArrayList();
|
ArrayList isDeferreds = new ArrayList();
|
||||||
ArrayList isLazies = new ArrayList();
|
ArrayList isLazies = new ArrayList();
|
||||||
|
|
||||||
keyColumns = new ArrayList();
|
keyColumns = new ArrayList();
|
||||||
titer = persistentClass.getSubclassTableClosureIterator();
|
titer = persistentClass.getSubclassTableClosureIterator();
|
||||||
while ( titer.hasNext() ) {
|
while ( titer.hasNext() ) {
|
||||||
|
@ -262,7 +427,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
}
|
}
|
||||||
keyColumns.add( key );
|
keyColumns.add( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add joins
|
//Add joins
|
||||||
joinIter = persistentClass.getSubclassJoinClosureIterator();
|
joinIter = persistentClass.getSubclassJoinClosureIterator();
|
||||||
while ( joinIter.hasNext() ) {
|
while ( joinIter.hasNext() ) {
|
||||||
|
@ -293,7 +457,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes );
|
isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes );
|
||||||
subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds );
|
subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds );
|
||||||
subclassTableIsLazyClosure = ArrayHelper.toBooleanArray( isLazies );
|
subclassTableIsLazyClosure = ArrayHelper.toBooleanArray( isLazies );
|
||||||
|
|
||||||
constraintOrderedTableNames = new String[naturalOrderSubclassTableNameClosure.length];
|
constraintOrderedTableNames = new String[naturalOrderSubclassTableNameClosure.length];
|
||||||
constraintOrderedKeyColumnNames = new String[naturalOrderSubclassTableNameClosure.length][];
|
constraintOrderedKeyColumnNames = new String[naturalOrderSubclassTableNameClosure.length][];
|
||||||
int currentPosition = 0;
|
int currentPosition = 0;
|
||||||
|
@ -319,12 +482,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
tableKeyColumnReaderTemplates = reverse( naturalOrderTableKeyColumnReaderTemplates, coreTableSpan );
|
tableKeyColumnReaderTemplates = reverse( naturalOrderTableKeyColumnReaderTemplates, coreTableSpan );
|
||||||
subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan );
|
subclassTableNameClosure = reverse( naturalOrderSubclassTableNameClosure, coreTableSpan );
|
||||||
subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan );
|
subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan );
|
||||||
|
|
||||||
spaces = ArrayHelper.join(
|
spaces = ArrayHelper.join(
|
||||||
tableNames,
|
tableNames,
|
||||||
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
|
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
|
||||||
);
|
);
|
||||||
|
|
||||||
// Custom sql
|
// Custom sql
|
||||||
customSQLInsert = new String[tableSpan];
|
customSQLInsert = new String[tableSpan];
|
||||||
customSQLUpdate = new String[tableSpan];
|
customSQLUpdate = new String[tableSpan];
|
||||||
|
@ -363,7 +524,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
if ( jk != -1 ) {
|
if ( jk != -1 ) {
|
||||||
throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." );
|
throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." );
|
||||||
}
|
}
|
||||||
|
|
||||||
joinIter = persistentClass.getJoinClosureIterator();
|
joinIter = persistentClass.getJoinClosureIterator();
|
||||||
int j = coreTableSpan;
|
int j = coreTableSpan;
|
||||||
while ( joinIter.hasNext() ) {
|
while ( joinIter.hasNext() ) {
|
||||||
|
@ -387,6 +547,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// PROPERTIES
|
// PROPERTIES
|
||||||
int hydrateSpan = getPropertySpan();
|
int hydrateSpan = getPropertySpan();
|
||||||
naturalOrderPropertyTableNumbers = new int[hydrateSpan];
|
naturalOrderPropertyTableNumbers = new int[hydrateSpan];
|
||||||
|
@ -412,7 +573,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
ArrayList columnTableNumbers = new ArrayList();
|
ArrayList columnTableNumbers = new ArrayList();
|
||||||
ArrayList formulaTableNumbers = new ArrayList();
|
ArrayList formulaTableNumbers = new ArrayList();
|
||||||
ArrayList propTableNumbers = new ArrayList();
|
ArrayList propTableNumbers = new ArrayList();
|
||||||
|
|
||||||
iter = persistentClass.getSubclassPropertyClosureIterator();
|
iter = persistentClass.getSubclassPropertyClosureIterator();
|
||||||
while ( iter.hasNext() ) {
|
while ( iter.hasNext() ) {
|
||||||
Property prop = (Property) iter.next();
|
Property prop = (Property) iter.next();
|
||||||
|
@ -445,8 +605,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
// SUBCLASSES
|
// SUBCLASSES
|
||||||
|
|
||||||
int subclassSpan = persistentClass.getSubclassSpan() + 1;
|
int subclassSpan = persistentClass.getSubclassSpan() + 1;
|
||||||
subclassClosure = new String[subclassSpan];
|
|
||||||
subclassClosure[subclassSpan - 1] = getEntityName();
|
|
||||||
if ( persistentClass.isPolymorphic() ) {
|
if ( persistentClass.isPolymorphic() ) {
|
||||||
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
|
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
|
||||||
discriminatorValues = new String[subclassSpan];
|
discriminatorValues = new String[subclassSpan];
|
||||||
|
@ -470,6 +629,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
notNullColumnNames = null;
|
notNullColumnNames = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subclassClosure = new String[subclassSpan];
|
||||||
|
subclassClosure[subclassSpan - 1] = getEntityName();
|
||||||
iter = persistentClass.getSubclassIterator();
|
iter = persistentClass.getSubclassIterator();
|
||||||
int k = 0;
|
int k = 0;
|
||||||
while ( iter.hasNext() ) {
|
while ( iter.hasNext() ) {
|
||||||
|
@ -508,6 +669,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
postConstruct( mapping );
|
postConstruct( mapping );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
@SuppressWarnings( {"UnusedDeclaration"})
|
||||||
public JoinedSubclassEntityPersister(
|
public JoinedSubclassEntityPersister(
|
||||||
final EntityBinding entityBinding,
|
final EntityBinding entityBinding,
|
||||||
|
@ -517,104 +680,358 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
final Mapping mapping) throws HibernateException {
|
final Mapping mapping) throws HibernateException {
|
||||||
|
|
||||||
super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory );
|
||||||
|
|
||||||
|
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
|
// DISCRIMINATOR
|
||||||
|
|
||||||
if ( entityBinding.isPolymorphic() ) {
|
if ( entityBinding.isPolymorphic() ) {
|
||||||
try {
|
try {
|
||||||
discriminatorValue = entityBinding.getSubEntityBindingId();
|
discriminatorValue = entityBinding.getSubEntityBindingId();
|
||||||
discriminatorSQLString = discriminatorValue.toString();
|
discriminatorSQLString = discriminatorValue.toString();
|
||||||
} catch ( Exception e ){
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
throw new MappingException( "Could not format discriminator value to SQL string", 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 {
|
else {
|
||||||
|
discriminatorValues = null;
|
||||||
|
notNullColumnTableNumbers = null;
|
||||||
|
notNullColumnNames = null;
|
||||||
discriminatorValue = null;
|
discriminatorValue = null;
|
||||||
discriminatorSQLString = null;
|
discriminatorSQLString = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( int k = 0; k < postOrderSubEntityBindings.length; k++ ) {
|
||||||
if ( optimisticLockStyle() == OptimisticLockStyle.ALL || optimisticLockStyle() == OptimisticLockStyle.DIRTY ) {
|
final EntityBinding eb = postOrderSubEntityBindings[k];
|
||||||
throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" );
|
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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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() );
|
|
||||||
}
|
|
||||||
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();
|
initLockers();
|
||||||
initSubclassPropertyAliasesMap( entityBinding );
|
initSubclassPropertyAliasesMap( entityBinding );
|
||||||
|
|
||||||
postConstruct( mapping );
|
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) {
|
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 );
|
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];
|
Object[] temp = new Object[len];
|
||||||
for ( int i = 0; i < len; i++ ) {
|
for ( int i = 0; i < len; i++ ) {
|
||||||
temp[i] = objects[len - i - 1];
|
temp[i] = objects[len - i - 1];
|
||||||
}
|
}
|
||||||
for ( int i = 0; i < len; i++ ) {
|
System.arraycopy( temp, 0, objects, 0, len );
|
||||||
objects[i] = temp[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -714,20 +1129,26 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
*/
|
*/
|
||||||
private static String[] reverse(String[] objects, int n) {
|
private static String[] reverse(String[] objects, int n) {
|
||||||
|
|
||||||
int size = objects.length;
|
final int size = objects.length;
|
||||||
String[] temp = new String[size];
|
final String[] temp = new String[size];
|
||||||
|
|
||||||
for ( int i = 0; i < n; i++ ) {
|
for ( int i = 0; i < n; i++ ) {
|
||||||
temp[i] = objects[n - i - 1];
|
temp[i] = objects[n - i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = n; i < size; i++ ) {
|
System.arraycopy( objects, n, temp, n, size - n );
|
||||||
temp[i] = objects[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return temp;
|
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
|
* Reverse the first n elements of the incoming array
|
||||||
*
|
*
|
||||||
|
@ -743,9 +1164,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
temp[i] = objects[n - i - 1];
|
temp[i] = objects[n - i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = n; i < size; i++ ) {
|
System.arraycopy( objects, n, temp, n, size - n );
|
||||||
temp[i] = objects[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
@ -870,7 +1289,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
if ( index == null ) {
|
if ( index == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return tableNames[propertyTableNumbers[index.intValue()]];
|
return tableNames[propertyTableNumbers[index]];
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getConstraintOrderedTableNameClosure() {
|
public String[] getConstraintOrderedTableNameClosure() {
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||||
import org.hibernate.cfg.NotYetImplementedException;
|
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
@ -129,9 +128,9 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
private final String[][] constraintOrderedKeyColumnNames;
|
private final String[][] constraintOrderedKeyColumnNames;
|
||||||
|
|
||||||
//private final Map propertyTableNumbersByName = new HashMap();
|
//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 NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
|
||||||
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not 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);
|
isNullables.add(Boolean.FALSE);
|
||||||
isLazies.add(Boolean.FALSE);
|
isLazies.add(Boolean.FALSE);
|
||||||
|
|
||||||
for ( SecondaryTable join : entityBinding.getSubclassSecondaryTableClosure() ) {
|
for ( SecondaryTable join : entityBinding.getEntitiesSecondaryTableClosure() ) {
|
||||||
final boolean isConcrete = entityBinding.isClassOrSuperclassSecondaryTable( join );
|
final boolean isConcrete = entityBinding.isClassOrSuperclassSecondaryTable( join );
|
||||||
isConcretes.add( isConcrete );
|
isConcretes.add( isConcrete );
|
||||||
boolean isDeferred = join.getFetchStyle() != FetchStyle.JOIN;
|
boolean isDeferred = join.getFetchStyle() != FetchStyle.JOIN;
|
||||||
|
@ -672,11 +671,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
//TODO: code duplication with JoinedSubclassEntityPersister
|
//TODO: code duplication with JoinedSubclassEntityPersister
|
||||||
|
|
||||||
ArrayList columnJoinNumbers = new ArrayList();
|
ArrayList<Integer> columnJoinNumbers = new ArrayList<Integer>();
|
||||||
ArrayList formulaJoinedNumbers = new ArrayList();
|
ArrayList<Integer> formulaJoinedNumbers = new ArrayList<Integer>();
|
||||||
ArrayList propertyJoinNumbers = new ArrayList();
|
ArrayList<Integer> propertyJoinNumbers = new ArrayList<Integer>();
|
||||||
|
|
||||||
for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) {
|
for ( AttributeBinding attributeBinding : entityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||||
continue; // skip identifier binding
|
continue; // skip identifier binding
|
||||||
}
|
}
|
||||||
|
@ -753,18 +752,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
postConstruct( mapping );
|
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) {
|
protected boolean isInverseTable(int j) {
|
||||||
return isInverseTable[j];
|
return isInverseTable[j];
|
||||||
|
@ -889,9 +876,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] subclasses = getSubclassClosure();
|
String[] subclasses = getSubclassClosure();
|
||||||
for ( int i=0; i<subclasses.length; i++ ) {
|
for ( String subclass : subclasses ) {
|
||||||
final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclasses[i] );
|
final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclass );
|
||||||
if ( !queryable.isAbstract() ) frag.addValue( queryable.getDiscriminatorSQLValue() );
|
if ( !queryable.isAbstract() ) {
|
||||||
|
frag.addValue( queryable.getDiscriminatorSQLValue() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder buf = new StringBuilder(50)
|
StringBuilder buf = new StringBuilder(50)
|
||||||
|
@ -966,12 +955,12 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
private int getSubclassPropertyTableNumber(String propertyName, String entityName) {
|
private int getSubclassPropertyTableNumber(String propertyName, String entityName) {
|
||||||
Type type = propertyMapping.toType(propertyName);
|
Type type = propertyMapping.toType(propertyName);
|
||||||
if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) return 0;
|
if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) return 0;
|
||||||
final Integer tabnum = (Integer) propertyTableNumbersByNameAndSubclass.get(entityName + '.' + propertyName);
|
final Integer tabnum = propertyTableNumbersByNameAndSubclass.get(entityName + '.' + propertyName);
|
||||||
return tabnum==null ? 0 : tabnum.intValue();
|
return tabnum==null ? 0 : tabnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSequentialSelect(String entityName) {
|
protected String getSequentialSelect(String entityName) {
|
||||||
return (String) sequentialSelectStringsByEntityName.get(entityName);
|
return sequentialSelectStringsByEntityName.get(entityName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateSequentialSelect(Loadable persister) {
|
private String generateSequentialSelect(Loadable persister) {
|
||||||
|
@ -982,7 +971,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
//figure out which tables need to be fetched
|
//figure out which tables need to be fetched
|
||||||
AbstractEntityPersister subclassPersister = (AbstractEntityPersister) persister;
|
AbstractEntityPersister subclassPersister = (AbstractEntityPersister) persister;
|
||||||
HashSet tableNumbers = new HashSet();
|
HashSet<Integer> tableNumbers = new HashSet<Integer>();
|
||||||
String[] props = subclassPersister.getPropertyNames();
|
String[] props = subclassPersister.getPropertyNames();
|
||||||
String[] classes = subclassPersister.getPropertySubclassNames();
|
String[] classes = subclassPersister.getPropertySubclassNames();
|
||||||
for ( int i=0; i<props.length; i++ ) {
|
for ( int i=0; i<props.length; i++ ) {
|
||||||
|
@ -994,7 +983,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
if ( tableNumbers.isEmpty() ) return null;
|
if ( tableNumbers.isEmpty() ) return null;
|
||||||
|
|
||||||
//figure out which columns are needed
|
//figure out which columns are needed
|
||||||
ArrayList columnNumbers = new ArrayList();
|
ArrayList<Integer> columnNumbers = new ArrayList<Integer>();
|
||||||
final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
|
||||||
for ( int i=0; i<getSubclassColumnClosure().length; i++ ) {
|
for ( int i=0; i<getSubclassColumnClosure().length; i++ ) {
|
||||||
if ( tableNumbers.contains( columnTableNumbers[i] ) ) {
|
if ( tableNumbers.contains( columnTableNumbers[i] ) ) {
|
||||||
|
@ -1003,7 +992,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
}
|
}
|
||||||
|
|
||||||
//figure out which formulas are needed
|
//figure out which formulas are needed
|
||||||
ArrayList formulaNumbers = new ArrayList();
|
ArrayList<Integer> formulaNumbers = new ArrayList<Integer>();
|
||||||
final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
|
final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
|
||||||
for ( int i=0; i<getSubclassFormulaTemplateClosure().length; i++ ) {
|
for ( int i=0; i<getSubclassFormulaTemplateClosure().length; i++ ) {
|
||||||
if ( tableNumbers.contains( formulaTableNumbers[i] ) ) {
|
if ( tableNumbers.contains( formulaTableNumbers[i] ) ) {
|
||||||
|
@ -1051,7 +1040,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
public String getPropertyTableName(String propertyName) {
|
public String getPropertyTableName(String propertyName) {
|
||||||
Integer index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
|
Integer index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
|
||||||
if (index==null) return null;
|
if (index==null) return null;
|
||||||
return qualifiedTableNames[ propertyTableNumbers[ index.intValue() ] ];
|
return qualifiedTableNames[ propertyTableNumbers[ index ] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postInstantiate() {
|
public void postInstantiate() {
|
||||||
|
|
|
@ -53,9 +53,7 @@ import org.hibernate.mapping.Column;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Subclass;
|
import org.hibernate.mapping.Subclass;
|
||||||
import org.hibernate.mapping.Table;
|
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.EntityBinding;
|
||||||
import org.hibernate.metamodel.spi.binding.InheritanceType;
|
|
||||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||||
import org.hibernate.metamodel.spi.relational.Value;
|
import org.hibernate.metamodel.spi.relational.Value;
|
||||||
import org.hibernate.sql.SelectFragment;
|
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"})
|
@SuppressWarnings( {"UnusedDeclaration"})
|
||||||
public UnionSubclassEntityPersister(
|
public UnionSubclassEntityPersister(
|
||||||
|
@ -290,27 +266,20 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
|
|
||||||
//Custom SQL
|
//Custom SQL
|
||||||
{
|
// Custom sql
|
||||||
CustomSQLMetadata customSQLMetadata;
|
customSQLInsert = new String[1];
|
||||||
{
|
customSQLUpdate = new String[1];
|
||||||
customSQLMetadata = parse( entityBinding.getCustomInsert() );
|
customSQLDelete = new String[1];
|
||||||
customSQLInsert = customSQLMetadata.sqls;
|
insertCallable = new boolean[1];
|
||||||
insertCallable = customSQLMetadata.callable;
|
updateCallable = new boolean[1];
|
||||||
insertResultCheckStyles = customSQLMetadata.checkStyles;
|
deleteCallable = new boolean[1];
|
||||||
}
|
insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
|
||||||
{
|
updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
|
||||||
customSQLMetadata = parse( entityBinding.getCustomUpdate() );
|
deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[1];
|
||||||
customSQLUpdate = customSQLMetadata.sqls;
|
|
||||||
updateCallable = customSQLMetadata.callable;
|
initializeCustomSql( entityBinding.getCustomInsert(), 0, customSQLInsert, insertCallable, insertResultCheckStyles );
|
||||||
updateResultCheckStyles = customSQLMetadata.checkStyles;
|
initializeCustomSql( entityBinding.getCustomUpdate(), 0, customSQLUpdate, updateCallable, updateResultCheckStyles );
|
||||||
}
|
initializeCustomSql( entityBinding.getCustomDelete(), 0, customSQLDelete, deleteCallable, deleteResultCheckStyles );
|
||||||
{
|
|
||||||
customSQLMetadata = parse( entityBinding.getCustomDelete() );
|
|
||||||
customSQLDelete = customSQLMetadata.sqls;
|
|
||||||
deleteCallable = customSQLMetadata.callable;
|
|
||||||
deleteResultCheckStyles = customSQLMetadata.checkStyles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//discriminator
|
//discriminator
|
||||||
{
|
{
|
||||||
discriminatorValue = entityBinding.getSubEntityBindingId();
|
discriminatorValue = entityBinding.getSubEntityBindingId();
|
||||||
|
@ -329,9 +298,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
entityBinding.getEntityName()
|
entityBinding.getEntityName()
|
||||||
);
|
);
|
||||||
if ( entityBinding.isPolymorphic() ) {
|
if ( entityBinding.isPolymorphic() ) {
|
||||||
Iterable<EntityBinding> iter = entityBinding.getPreOrderSubEntityBindingClosure();
|
|
||||||
int k=1;
|
int k=1;
|
||||||
for(EntityBinding subEntityBinding : iter){
|
for(EntityBinding subEntityBinding : entityBinding.getPreOrderSubEntityBindingClosure()){
|
||||||
subclassClosure[k++] = subEntityBinding.getEntityName();
|
subclassClosure[k++] = subEntityBinding.getEntityName();
|
||||||
subclassByDiscriminatorValue.put( subEntityBinding.getSubEntityBindingId(), subEntityBinding.getEntityName() );
|
subclassByDiscriminatorValue.put( subEntityBinding.getSubEntityBindingId(), subEntityBinding.getEntityName() );
|
||||||
}
|
}
|
||||||
|
@ -351,8 +319,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSet<String> subclassTables = new HashSet<String>();
|
HashSet<String> subclassTables = new HashSet<String>();
|
||||||
Iterable<EntityBinding> iter = entityBinding.getPreOrderSubEntityBindingClosure();
|
final EntityBinding[] subEntityBindings = entityBinding.getPreOrderSubEntityBindingClosure();
|
||||||
for ( EntityBinding subEntityBinding : iter ) {
|
for ( EntityBinding subEntityBinding : entityBinding.getPreOrderSubEntityBindingClosure() ) {
|
||||||
subclassTables.add( subEntityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ) );
|
subclassTables.add( subEntityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ) );
|
||||||
}
|
}
|
||||||
subclassSpaces = ArrayHelper.toStringArray( subclassTables );
|
subclassSpaces = ArrayHelper.toStringArray( subclassTables );
|
||||||
|
@ -367,12 +335,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
tableNames.add( tableName );
|
tableNames.add( tableName );
|
||||||
keyColumns.add( getIdentifierColumnNames() );
|
keyColumns.add( getIdentifierColumnNames() );
|
||||||
}
|
}
|
||||||
Iterator<EntityBinding> siter = new JoinedIterator<EntityBinding>(
|
EntityBinding[] ebs = ArrayHelper.join( new EntityBinding[]{entityBinding}, subEntityBindings );
|
||||||
new SingletonIterator<EntityBinding>( entityBinding ),
|
for(final EntityBinding eb : ebs){
|
||||||
iter.iterator()
|
|
||||||
);
|
|
||||||
while ( siter.hasNext() ) {
|
|
||||||
EntityBinding eb = siter.next();
|
|
||||||
TableSpecification tab = eb.getPrimaryTable();
|
TableSpecification tab = eb.getPrimaryTable();
|
||||||
if ( isNotAbstractUnionTable( eb ) ) {
|
if ( isNotAbstractUnionTable( eb ) ) {
|
||||||
String tableName = tab.getQualifiedName( factory.getDialect() );
|
String tableName = tab.getQualifiedName( factory.getDialect() );
|
||||||
|
|
|
@ -412,7 +412,9 @@ public class EntityMetamodel implements Serializable {
|
||||||
else {
|
else {
|
||||||
identifierAttributeBindingSpan = 1;
|
identifierAttributeBindingSpan = 1;
|
||||||
}
|
}
|
||||||
propertySpan = entityBinding.getAttributeBindingClosureSpan() - identifierAttributeBindingSpan;
|
|
||||||
|
final AttributeBinding [] attributeBindings = entityBinding.getAttributeBindingClosure();
|
||||||
|
propertySpan = attributeBindings.length;
|
||||||
|
|
||||||
properties = new StandardProperty[propertySpan];
|
properties = new StandardProperty[propertySpan];
|
||||||
List naturalIdNumbers = new ArrayList();
|
List naturalIdNumbers = new ArrayList();
|
||||||
|
@ -442,7 +444,7 @@ public class EntityMetamodel implements Serializable {
|
||||||
boolean foundUpdateGeneratedValue = false;
|
boolean foundUpdateGeneratedValue = false;
|
||||||
boolean foundUpdateableNaturalIdProperty = false;
|
boolean foundUpdateableNaturalIdProperty = false;
|
||||||
|
|
||||||
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
for ( AttributeBinding attributeBinding : attributeBindings ) {
|
||||||
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( attributeBinding ) ) {
|
||||||
// skip the identifier attribute binding
|
// skip the identifier attribute binding
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -124,8 +124,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertFalse( noInheritanceEntityBinding.isPolymorphic() );
|
assertFalse( noInheritanceEntityBinding.isPolymorphic() );
|
||||||
assertFalse( noInheritanceEntityBinding.hasSubEntityBindings() );
|
assertFalse( noInheritanceEntityBinding.hasSubEntityBindings() );
|
||||||
assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingClosureSpan() );
|
assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingClosureSpan() );
|
||||||
assertFalse( noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
assertEquals( 0, noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().length );
|
||||||
assertFalse( noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
assertEquals( 0, noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().length );
|
||||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.attributeBindings() ) {
|
for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.attributeBindings() ) {
|
||||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||||
|
@ -140,14 +140,17 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( iterator.hasNext() );
|
assertTrue( iterator.hasNext() );
|
||||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
||||||
assertFalse( iterator.hasNext() );
|
assertFalse( iterator.hasNext() );
|
||||||
iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator();
|
|
||||||
assertTrue( iterator.hasNext() );
|
AttributeBinding[] attributeBindings = noInheritanceEntityBinding.getAttributeBindingClosure();
|
||||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
assertTrue( attributeBindings.length > 0 );
|
||||||
assertFalse( iterator.hasNext() );
|
int index =0;
|
||||||
iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator();
|
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] );
|
||||||
assertTrue( iterator.hasNext() );
|
assertFalse( index < attributeBindings.length );
|
||||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
|
attributeBindings = noInheritanceEntityBinding.getEntitiesAttributeBindingClosure();
|
||||||
assertFalse( iterator.hasNext() );
|
index = 0;
|
||||||
|
assertTrue( attributeBindings.length > 0 );
|
||||||
|
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] );
|
||||||
|
assertFalse( index < attributeBindings.length );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -198,7 +201,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertEquals( 1, attributeBindingClosure.size() );
|
assertEquals( 1, attributeBindingClosure.size() );
|
||||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding subAttributeBinding : rootEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
for ( AttributeBinding subAttributeBinding : rootEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||||
}
|
}
|
||||||
assertEquals( 4, subAttributeBindings.size() );
|
assertEquals( 4, subAttributeBindings.size() );
|
||||||
|
@ -225,23 +228,24 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||||
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
||||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
||||||
Iterator<EntityBinding> subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure().iterator();
|
EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure();
|
||||||
assertTrue( subEntityBindingIterator.hasNext() );
|
assertTrue( subEntityBindingIterator.length > 0 );
|
||||||
|
int i = 0;
|
||||||
if ( isSubclassEntityBindingFirst ) {
|
if ( isSubclassEntityBindingFirst ) {
|
||||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertTrue( subEntityBindingIterator.hasNext() );
|
assertTrue( i<subEntityBindingIterator.length );
|
||||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertTrue( subEntityBindingIterator.hasNext() );
|
assertTrue( i<subEntityBindingIterator.length );
|
||||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertTrue( subEntityBindingIterator.hasNext() );
|
assertTrue( i<subEntityBindingIterator.length );
|
||||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertTrue( subEntityBindingIterator.hasNext() );
|
assertTrue( i<subEntityBindingIterator.length );
|
||||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
}
|
}
|
||||||
assertFalse( subEntityBindingIterator.hasNext() );
|
assertFalse( i<subEntityBindingIterator.length );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -261,19 +265,20 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||||
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
||||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
||||||
Iterator<EntityBinding> subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure().iterator();
|
EntityBinding[] subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||||
assertTrue( subEntityBindingIterator.hasNext() );
|
int i =0;
|
||||||
|
assertTrue( subEntityBindingIterator.length > 0 );
|
||||||
if ( isSubclassEntityBindingFirst ) {
|
if ( isSubclassEntityBindingFirst ) {
|
||||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( otherSubclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
assertSame( subclassEntityBinding, subEntityBindingIterator[i++] );
|
||||||
}
|
}
|
||||||
assertFalse( subEntityBindingIterator.hasNext() );
|
assertFalse( i < subEntityBindingIterator.length );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -297,8 +302,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( otherSubclassEntityBinding.isPolymorphic() );
|
assertTrue( otherSubclassEntityBinding.isPolymorphic() );
|
||||||
assertFalse( otherSubclassEntityBinding.hasSubEntityBindings() );
|
assertFalse( otherSubclassEntityBinding.hasSubEntityBindings() );
|
||||||
assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||||
assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 );
|
||||||
assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 );
|
||||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.attributeBindings() ) {
|
for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.attributeBindings() ) {
|
||||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||||
|
@ -314,7 +319,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||||
assertTrue( attributeBindingClosure.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
assertTrue( attributeBindingClosure.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
||||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||||
}
|
}
|
||||||
assertEquals( 2, subAttributeBindings.size() );
|
assertEquals( 2, subAttributeBindings.size() );
|
||||||
|
@ -343,14 +348,16 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( subclassEntityBinding.isPolymorphic() );
|
assertTrue( subclassEntityBinding.isPolymorphic() );
|
||||||
assertTrue( subclassEntityBinding.hasSubEntityBindings() );
|
assertTrue( subclassEntityBinding.hasSubEntityBindings() );
|
||||||
assertEquals( 1, subclassEntityBinding.getSubEntityBindingClosureSpan() );
|
assertEquals( 1, subclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||||
Iterator<EntityBinding> itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator();
|
EntityBinding[] itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||||
assertTrue( itSubEntityBindings.hasNext() );
|
int i = 0;
|
||||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() );
|
assertTrue( i < itSubEntityBindings.length );
|
||||||
assertFalse( itSubEntityBindings.hasNext() );
|
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] );
|
||||||
itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator();
|
assertFalse( i < itSubEntityBindings.length );
|
||||||
assertTrue( itSubEntityBindings.hasNext() );
|
itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure();
|
||||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() );
|
i = 0;
|
||||||
assertFalse( itSubEntityBindings.hasNext() );
|
assertTrue( i < itSubEntityBindings.length );
|
||||||
|
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings[i++] );
|
||||||
|
assertFalse( i < itSubEntityBindings.length );
|
||||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding attributeBinding : subclassEntityBinding.attributeBindings() ) {
|
for ( AttributeBinding attributeBinding : subclassEntityBinding.attributeBindings() ) {
|
||||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||||
|
@ -366,7 +373,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||||
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||||
}
|
}
|
||||||
assertEquals( 3, subAttributeBindings.size() );
|
assertEquals( 3, subAttributeBindings.size() );
|
||||||
|
@ -396,8 +403,8 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( subclassOfSubclassEntityBinding.isPolymorphic() );
|
assertTrue( subclassOfSubclassEntityBinding.isPolymorphic() );
|
||||||
assertFalse( subclassOfSubclassEntityBinding.hasSubEntityBindings() );
|
assertFalse( subclassOfSubclassEntityBinding.hasSubEntityBindings() );
|
||||||
assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||||
assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().length > 0 );
|
||||||
assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().length > 0 );
|
||||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.attributeBindings() ) {
|
for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.attributeBindings() ) {
|
||||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||||
|
@ -414,7 +421,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
||||||
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||||
assertTrue( attributeBindingClosure.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
assertTrue( attributeBindingClosure.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||||
for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getEntitiesAttributeBindingClosure() ) {
|
||||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||||
}
|
}
|
||||||
assertEquals( 3, subAttributeBindings.size() );
|
assertEquals( 3, subAttributeBindings.size() );
|
||||||
|
|
|
@ -28,13 +28,11 @@ import java.util.Date;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@FailureExpectedWithNewMetamodel
|
|
||||||
public class IndexTest extends BaseCoreFunctionalTestCase {
|
public class IndexTest extends BaseCoreFunctionalTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void testIndexManyToOne() throws Exception {
|
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
|
@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.
|
// CustomRunner. Thus, the if block below skips the test if the new metamodel is being used.
|
||||||
public void testOrm1Support() {
|
public void testOrm1Support() {
|
||||||
if ( Boolean.getBoolean( USE_NEW_METADATA_MAPPINGS ) ) {
|
if ( isMetadataUsed ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// need to call buildSessionFactory, because this test is not using org.hibernate.testing.junit4.CustomRunner
|
// 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.Session;
|
||||||
import org.hibernate.testing.DialectChecks;
|
import org.hibernate.testing.DialectChecks;
|
||||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.RequiresDialectFeature;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
|
@ -35,7 +34,6 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
|
@RequiresDialectFeature(DialectChecks.SupportsIdentityColumns.class)
|
||||||
@FailureExpectedWithNewMetamodel
|
|
||||||
public class HbmWithIdentityTest extends BaseCoreFunctionalTestCase {
|
public class HbmWithIdentityTest extends BaseCoreFunctionalTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void testManyToOneAndInterface() throws Exception {
|
public void testManyToOneAndInterface() throws Exception {
|
||||||
|
|
|
@ -26,13 +26,11 @@ package org.hibernate.test.collection.ordered.joinedInheritence;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@FailureExpectedWithNewMetamodel
|
|
||||||
public class OrderCollectionOfJoinedHierarchyTest extends BaseCoreFunctionalTestCase {
|
public class OrderCollectionOfJoinedHierarchyTest extends BaseCoreFunctionalTestCase {
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
|
|
@ -59,7 +59,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings( {"UnnecessaryUnboxing", "UnnecessaryBoxing"})
|
@SuppressWarnings( {"UnnecessaryUnboxing", "UnnecessaryBoxing"})
|
||||||
@FailureExpectedWithNewMetamodel
|
//@FailureExpectedWithNewMetamodel
|
||||||
public class SQLFunctionsTest extends LegacyTestCase {
|
public class SQLFunctionsTest extends LegacyTestCase {
|
||||||
private static final Logger log = Logger.getLogger( SQLFunctionsTest.class );
|
private static final Logger log = Logger.getLogger( SQLFunctionsTest.class );
|
||||||
|
|
||||||
|
@ -217,6 +217,7 @@ public class SQLFunctionsTest extends LegacyTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@FailureExpectedWithNewMetamodel
|
||||||
public void testBroken() throws Exception {
|
public void testBroken() throws Exception {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
Transaction t = s.beginTransaction();
|
Transaction t = s.beginTransaction();
|
||||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.test.naturalid.inheritance;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
@ -36,7 +35,6 @@ import static org.junit.Assert.assertSame;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@FailureExpectedWithNewMetamodel
|
|
||||||
public class InheritedNaturalIdTest extends BaseCoreFunctionalTestCase {
|
public class InheritedNaturalIdTest extends BaseCoreFunctionalTestCase {
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
|
|
@ -43,7 +43,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
*
|
*
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
@FailureExpectedWithNewMetamodel
|
|
||||||
public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
|
public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
|
||||||
@Override
|
@Override
|
||||||
public String[] getMappings() {
|
public String[] getMappings() {
|
||||||
|
@ -82,7 +82,7 @@ public class GetHqlQueryPlanTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
@FailureExpectedWithNewMetamodel
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings( {"UnnecessaryBoxing"})
|
@SuppressWarnings( {"UnnecessaryBoxing"})
|
||||||
public void testHqlQueryPlanWithEnabledFilter() {
|
public void testHqlQueryPlanWithEnabledFilter() {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<hibernate-mapping default-lazy="false">
|
<hibernate-mapping default-lazy="false">
|
||||||
<class name="org.hibernate.test.legacy.Blobber" dynamic-update="true">
|
<class name="org.hibernate.test.legacy.Blobber" dynamic-update="true">
|
||||||
<id name="id">
|
<id name="id">
|
||||||
<generator class="hilo"/>
|
<generator class="seqhilo"/>
|
||||||
</id>
|
</id>
|
||||||
<property name="blob" column="blob_"/>
|
<property name="blob" column="blob_"/>
|
||||||
<property name="clob" column="clob_"/>
|
<property name="clob" column="clob_"/>
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.jpa.event.spi.jpa.Callback;
|
import org.hibernate.jpa.event.spi.jpa.Callback;
|
||||||
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
|
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
|
||||||
|
@ -62,13 +63,10 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
||||||
@Override
|
@Override
|
||||||
public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl callbackRegistry) {
|
public void processCallbacksForEntity(Object entityObject, CallbackRegistryImpl callbackRegistry) {
|
||||||
final EntityBinding entityBinding = (EntityBinding) entityObject;
|
final EntityBinding entityBinding = (EntityBinding) entityObject;
|
||||||
final String entityClassName = entityBinding.getEntity().getClassName();
|
if ( entityBinding.getHierarchyDetails().getEntityMode() != EntityMode.POJO ) {
|
||||||
if ( entityClassName == null ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final Class entityClass = entityBinding.getEntity().getClassReference();
|
||||||
try {
|
|
||||||
final Class entityClass = classLoaderService.classForName( entityClassName );
|
|
||||||
for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) {
|
for ( Class annotationClass : CALLBACK_ANNOTATION_CLASSES ) {
|
||||||
callbackRegistry.addEntityCallbacks(
|
callbackRegistry.addEntityCallbacks(
|
||||||
entityClass,
|
entityClass,
|
||||||
|
@ -77,14 +75,17 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ClassLoadingException e) {
|
|
||||||
throw new MappingException( "entity class not found: " + entityClassName, e );
|
private final static Callback[] EMPTY_CALLBACK = new Callback[0];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) {
|
private Callback[] collectCallbacks(EntityBinding entityBinding, Class entityClass, Class annotationClass) {
|
||||||
final List<Callback> callbacks = new ArrayList<Callback>();
|
if ( entityBinding.getJpaCallbackClasses() == null || entityBinding.getJpaCallbackClasses().isEmpty() ) {
|
||||||
for ( JpaCallbackSource jpaCallbackClass : entityBinding.getJpaCallbackClasses() ) {
|
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 Class listenerClass = classLoaderService.classForName( jpaCallbackClass.getName() );
|
||||||
final String methodName = jpaCallbackClass.getCallbackMethod( annotationClass );
|
final String methodName = jpaCallbackClass.getCallbackMethod( annotationClass );
|
||||||
|
|
||||||
|
@ -100,9 +101,9 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
||||||
? createListenerCallback( listenerClass, entityClass, methodName )
|
? createListenerCallback( listenerClass, entityClass, methodName )
|
||||||
: createBeanCallback( listenerClass, methodName );
|
: createBeanCallback( listenerClass, methodName );
|
||||||
assert callback != null;
|
assert callback != null;
|
||||||
callbacks.add(callback);
|
result[i] = callback;
|
||||||
}
|
}
|
||||||
return callbacks.toArray(new Callback[callbacks.size()]);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Callback createListenerCallback(
|
private Callback createListenerCallback(
|
||||||
|
@ -146,12 +147,20 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
||||||
Class<?> callbackSuperclass = callbackClass.getSuperclass();
|
Class<?> callbackSuperclass = callbackClass.getSuperclass();
|
||||||
if ( callbackSuperclass != null ) {
|
if ( callbackSuperclass != null ) {
|
||||||
Callback callback = createBeanCallback( callbackSuperclass, methodName );
|
Callback callback = createBeanCallback( callbackSuperclass, methodName );
|
||||||
if (callback != null) return callback;
|
if ( callback != null ) {
|
||||||
|
return callback;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for ( Method method : callbackClass.getDeclaredMethods() ) {
|
for ( Method method : callbackClass.getDeclaredMethods() ) {
|
||||||
if (!method.getName().equals(methodName)) continue;
|
if ( !method.getName().equals( methodName ) ) {
|
||||||
if (method.getParameterTypes().length != 0) continue;
|
continue;
|
||||||
if (!method.isAccessible()) method.setAccessible(true);
|
}
|
||||||
|
if ( method.getParameterTypes().length != 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( !method.isAccessible() ) {
|
||||||
|
method.setAccessible( true );
|
||||||
|
}
|
||||||
return new EntityCallback( method );
|
return new EntityCallback( method );
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -159,6 +168,6 @@ public class CallbackProcessorImpl implements CallbackProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
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 javax.persistence.PreUpdate;
|
||||||
import java.util.HashMap;
|
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.Callback;
|
||||||
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
|
import org.hibernate.jpa.event.spi.jpa.CallbackRegistry;
|
||||||
|
|
||||||
|
@ -59,11 +60,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPostCreateCallbacks(Class entityClass) {
|
public boolean hasPostCreateCallbacks(Class entityClass) {
|
||||||
return notEmpty( preCreates.get( entityClass ) );
|
return CollectionHelper.isNotEmpty( preCreates.get( entityClass ) );
|
||||||
}
|
|
||||||
|
|
||||||
private boolean notEmpty(Callback[] callbacks) {
|
|
||||||
return callbacks != null && callbacks.length > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,7 +75,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPostUpdateCallbacks(Class entityClass) {
|
public boolean hasPostUpdateCallbacks(Class entityClass) {
|
||||||
return notEmpty( postUpdates.get( entityClass ) );
|
return CollectionHelper.isNotEmpty( postUpdates.get( entityClass ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,7 +90,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPostRemoveCallbacks(Class entityClass) {
|
public boolean hasPostRemoveCallbacks(Class entityClass) {
|
||||||
return notEmpty( postRemoves.get( entityClass ) );
|
return CollectionHelper.isNotEmpty( postRemoves.get( entityClass ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,7 +104,7 @@ public class CallbackRegistryImpl implements CallbackRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean callback(Callback[] callbacks, Object bean) {
|
private boolean callback(Callback[] callbacks, Object bean) {
|
||||||
if ( callbacks != null && callbacks.length != 0 ) {
|
if ( CollectionHelper.isNotEmpty( callbacks ) ) {
|
||||||
for ( Callback callback : callbacks ) {
|
for ( Callback callback : callbacks ) {
|
||||||
callback.performCallback( bean );
|
callback.performCallback( bean );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue