Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
* Note that there are only 2 entries in subclassNameClosureBySubclassTable. That is because there are really only
* 2 tables here that make up the subclass mapping, the others make up the class/superclass table mappings. We
* do not need to account for those here. The "offset" is defined by the value of {@link #getTableSpan()}.
* Therefore the corresponding row in subclassNameClosureBySubclassTable for a given row in subclassTableNameClosure
* is calculated as {@code subclassTableNameClosureIndex - getTableSpan()}.
*
* As we consider each subclass table we can look into this array based on the subclass table's index and see
* which subclasses would require it to be included. E.g., given {@code TREAT( x AS JoinedEntitySubSubclass )},
* when trying to decide whether to include join to "T_JoinedEntitySubclass" (subclassTableNameClosureIndex = 1),
* we'd look at {@code subclassNameClosureBySubclassTable[0]} and see if the TREAT-AS subclass name is included in
* its values. Since {@code subclassNameClosureBySubclassTable[1]} includes "JoinedEntitySubSubclass", we'd
* consider it included.
*
* {@link #subclassTableNameClosure} also accounts for secondary tables and we properly handle those as we
* build the subclassNamesBySubclassTable array and they are therefore properly handled when we use it
*/
private final String[][] subclassNamesBySubclassTable;
/**
* Essentially we are building a mapping that we can later use to determine whether a given "subclass table"
* should be included in joins when JPA TREAT-AS is used.
*
* @param persistentClass
* @param factory
* @return
*/
private String[][] buildSubclassNamesBySubclassTableMapping(PersistentClass persistentClass, SessionFactoryImplementor factory) {
// this value represents the number of subclasses (and not the class itself)
final int numberOfSubclassTables = subclassTableNameClosure.length - coreTableSpan;
if ( numberOfSubclassTables == 0 ) {
return new String[0][];
}
final String[][] mapping = new String[numberOfSubclassTables][];
processPersistentClassHierarchy( persistentClass, true, factory, mapping );
return mapping;
}
private Set processPersistentClassHierarchy(
PersistentClass persistentClass,
boolean isBase,
SessionFactoryImplementor factory,
String[][] mapping) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// collect all the class names that indicate that the "main table" of the given PersistentClass should be
// included when one of the collected class names is used in TREAT
final Set classNames = new HashSet();
final Iterator itr = persistentClass.getDirectSubclasses();
while ( itr.hasNext() ) {
final Subclass subclass = (Subclass) itr.next();
final Set subclassSubclassNames = processPersistentClassHierarchy(
subclass,
false,
factory,
mapping
);
classNames.addAll( subclassSubclassNames );
}
classNames.add( persistentClass.getEntityName() );
if ( ! isBase ) {
MappedSuperclass msc = persistentClass.getSuperMappedSuperclass();
while ( msc != null ) {
classNames.add( msc.getMappedClass().getName() );
msc = msc.getSuperMappedSuperclass();
}
associateSubclassNamesToSubclassTableIndexes( persistentClass, classNames, mapping, factory );
}
return classNames;
}
private void associateSubclassNamesToSubclassTableIndexes(
PersistentClass persistentClass,
Set classNames,
String[][] mapping,
SessionFactoryImplementor factory) {
final String tableName = persistentClass.getTable().getQualifiedName(
factory.getDialect(),
factory.getSettings().getDefaultCatalogName(),
factory.getSettings().getDefaultSchemaName()
);
associateSubclassNamesToSubclassTableIndex( tableName, classNames, mapping );
Iterator itr = persistentClass.getJoinIterator();
while ( itr.hasNext() ) {
final Join join = (Join) itr.next();
final String secondaryTableName = join.getTable().getQualifiedName(
factory.getDialect(),
factory.getSettings().getDefaultCatalogName(),
factory.getSettings().getDefaultSchemaName()
);
associateSubclassNamesToSubclassTableIndex( secondaryTableName, classNames, mapping );
}
}
private void associateSubclassNamesToSubclassTableIndex(
String tableName,
Set classNames,
String[][] mapping) {
// find the table's entry in the subclassTableNameClosure array
boolean found = false;
for ( int i = 0; i < subclassTableNameClosure.length; i++ ) {
if ( subclassTableNameClosure[i].equals( tableName ) ) {
found = true;
final int index = i - coreTableSpan;
if ( index < 0 || index >= mapping.length ) {
throw new IllegalStateException(
String.format(
"Encountered 'subclass table index' [%s] was outside expected range ( [%s] < i < [%s] )",
index,
0,
mapping.length
)
);
}
mapping[index] = classNames.toArray( new String[ classNames.size() ] );
break;
}
}
if ( !found ) {
throw new IllegalStateException(
String.format(
"Was unable to locate subclass table [%s] in 'subclassTableNameClosure'",
tableName
)
);
}
}
protected boolean isNullableTable(int j) {
if ( j < coreTableSpan ) {
return false;
}
return isNullableTable[j - coreTableSpan];
}
protected boolean isSubclassTableSequentialSelect(int j) {
return subclassTableSequentialSelect[j] && !isClassOrSuperclassTable[j];
}
/*public void postInstantiate() throws MappingException {
super.postInstantiate();
//TODO: other lock modes?
loader = createEntityLoader(LockMode.NONE, CollectionHelper.EMPTY_MAP);
}*/
public String getSubclassPropertyTableName(int i) {
return subclassTableNameClosure[subclassPropertyTableNumberClosure[i]];
}
public Type getDiscriminatorType() {
return discriminatorType;
}
public Object getDiscriminatorValue() {
return discriminatorValue;
}
@Override
public String getDiscriminatorSQLValue() {
return discriminatorSQLString;
}
@Override
public String getDiscriminatorColumnName() {
return explicitDiscriminatorColumnName == null
? super.getDiscriminatorColumnName()
: explicitDiscriminatorColumnName;
}
@Override
public String getDiscriminatorColumnReaders() {
return getDiscriminatorColumnName();
}
@Override
public String getDiscriminatorColumnReaderTemplate() {
return getDiscriminatorColumnName();
}
protected String getDiscriminatorAlias() {
return discriminatorAlias;
}
public String getSubclassForDiscriminatorValue(Object value) {
return (String) subclassesByDiscriminatorValue.get( value );
}
@Override
protected void addDiscriminatorToInsert(Insert insert) {
if ( explicitDiscriminatorColumnName != null ) {
insert.addColumn( explicitDiscriminatorColumnName, getDiscriminatorSQLValue() );
}
}
public Serializable[] getPropertySpaces() {
return spaces; // don't need subclass tables, because they can't appear in conditions
}
protected String getTableName(int j) {
return naturalOrderTableNames[j];
}
protected String[] getKeyColumns(int j) {
return naturalOrderTableKeyColumns[j];
}
protected boolean isTableCascadeDeleteEnabled(int j) {
return naturalOrderCascadeDeleteEnabled[j];
}
protected boolean isPropertyOfTable(int property, int j) {
return naturalOrderPropertyTableNumbers[property] == j;
}
/**
* Load an instance using either the forUpdateLoader or the outer joining loader,
* depending upon the value of the lock parameter
*/
/*public Object load(Serializable id, Object optionalObject, LockMode lockMode, SessionImplementor session)
throws HibernateException {
if ( log.isTraceEnabled() ) log.trace( "Materializing entity: " + MessageHelper.infoString(this, id) );
final UniqueEntityLoader loader = hasQueryLoader() ?
getQueryLoader() :
this.loader;
try {
final Object result = loader.load(id, optionalObject, session);
if (result!=null) lock(id, getVersion(result), result, lockMode, session);
return result;
}
catch (SQLException sqle) {
throw new JDBCException( "could not load by id: " + MessageHelper.infoString(this, id), sqle );
}
}*/
private static final void reverse(Object[] objects, int len) {
Object[] temp = new Object[len];
for ( int i = 0; i < len; i++ ) {
temp[i] = objects[len - i - 1];
}
for ( int i = 0; i < len; i++ ) {
objects[i] = temp[i];
}
}
/**
* Reverse the first n elements of the incoming array
*
* @param objects
* @param n
*
* @return New array with the first n elements in reversed order
*/
private static String[] reverse(String[] objects, int n) {
int size = objects.length;
String[] temp = new String[size];
for ( int i = 0; i < n; i++ ) {
temp[i] = objects[n - i - 1];
}
for ( int i = n; i < size; i++ ) {
temp[i] = objects[i];
}
return temp;
}
/**
* Reverse the first n elements of the incoming array
*
* @param objects
* @param n
*
* @return New array with the first n elements in reversed order
*/
private static String[][] reverse(String[][] objects, int n) {
int size = objects.length;
String[][] temp = new String[size][];
for ( int i = 0; i < n; i++ ) {
temp[i] = objects[n - i - 1];
}
for ( int i = n; i < size; i++ ) {
temp[i] = objects[i];
}
return temp;
}
public String fromTableFragment(String alias) {
return getTableName() + ' ' + alias;
}
public String getTableName() {
return tableNames[0];
}
public void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
if ( hasSubclasses() ) {
if ( explicitDiscriminatorColumnName == null ) {
select.setExtraSelectList( discriminatorFragment( name ), getDiscriminatorAlias() );
}
else {
if ( getEntityMetamodel().getSuperclass() != null ) {
name = generateTableAlias( name, getRootHierarchyClassTableIndex() );
}
select.addColumn( name, explicitDiscriminatorColumnName, discriminatorAlias );
}
}
}
private int getRootHierarchyClassTableIndex() {
final String rootHierarchyClassTableName = naturalOrderTableNames[0];
for ( int i = 0; i < subclassTableNameClosure.length; i++ ) {
if ( subclassTableNameClosure[i].equals( rootHierarchyClassTableName ) ) {
return i;
}
}
return 0;
}
private CaseFragment discriminatorFragment(String alias) {
CaseFragment cases = getFactory().getDialect().createCaseFragment();
for ( int i = 0; i < discriminatorValues.length; i++ ) {
cases.addWhenColumnNotNull(
generateTableAlias( alias, notNullColumnTableNumbers[i] ),
notNullColumnNames[i],
discriminatorValues[i]
);
}
return cases;
}
@Override
public String filterFragment(String alias) {
return hasWhere()
? " and " + getSQLWhereString( generateFilterConditionAlias( alias ) )
: "";
}
@Override
public String filterFragment(String alias, Set treatAsDeclarations) {
return filterFragment( alias );
}
public String generateFilterConditionAlias(String rootAlias) {
return generateTableAlias( rootAlias, tableSpan - 1 );
}
public String[] getIdentifierColumnNames() {
return tableKeyColumns[0];
}
public String[] getIdentifierColumnReaderTemplates() {
return tableKeyColumnReaderTemplates[0];
}
public String[] getIdentifierColumnReaders() {
return tableKeyColumnReaders[0];
}
public String[] toColumns(String alias, String propertyName) throws QueryException {
if ( ENTITY_CLASS.equals( propertyName ) ) {
if ( explicitDiscriminatorColumnName == null ) {
return new String[] { discriminatorFragment( alias ).toFragmentString() };
}
else {
return new String[] { StringHelper.qualify( alias, explicitDiscriminatorColumnName ) };
}
}
else {
return super.toColumns( alias, propertyName );
}
}
protected int[] getPropertyTableNumbersInSelect() {
return propertyTableNumbers;
}
protected int getSubclassPropertyTableNumber(int i) {
return subclassPropertyTableNumberClosure[i];
}
public int getTableSpan() {
return tableSpan;
}
public boolean isMultiTable() {
return true;
}
protected int[] getSubclassColumnTableNumberClosure() {
return subclassColumnTableNumberClosure;
}
protected int[] getSubclassFormulaTableNumberClosure() {
return subclassFormulaTableNumberClosure;
}
protected int[] getPropertyTableNumbers() {
return naturalOrderPropertyTableNumbers;
}
protected String[] getSubclassTableKeyColumns(int j) {
return subclassTableKeyColumnClosure[j];
}
public String getSubclassTableName(int j) {
return subclassTableNameClosure[j];
}
public int getSubclassTableSpan() {
return subclassTableNameClosure.length;
}
protected boolean isSubclassTableLazy(int j) {
return subclassTableIsLazyClosure[j];
}
protected boolean isClassOrSuperclassTable(int j) {
return isClassOrSuperclassTable[j];
}
@Override
protected boolean isSubclassTableIndicatedByTreatAsDeclarations(
int subclassTableNumber,
Set treatAsDeclarations) {
if ( treatAsDeclarations == null || treatAsDeclarations.isEmpty() ) {
return false;
}
final String[] inclusionSubclassNameClosure = getSubclassNameClosureBySubclassTable( subclassTableNumber );
// NOTE : we assume the entire hierarchy is joined-subclass here
for ( String subclassName : treatAsDeclarations ) {
for ( String inclusionSubclassName : inclusionSubclassNameClosure ) {
if ( inclusionSubclassName.equals( subclassName ) ) {
return true;
}
}
}
return false;
}
private String[] getSubclassNameClosureBySubclassTable(int subclassTableNumber) {
final int index = subclassTableNumber - getTableSpan();
if ( index > subclassNamesBySubclassTable.length ) {
throw new IllegalArgumentException(
"Given subclass table number is outside expected range [" + subclassNamesBySubclassTable.length
+ "] as defined by subclassTableNameClosure/subclassClosure"
);
}
return subclassNamesBySubclassTable[index];
}
public String getPropertyTableName(String propertyName) {
Integer index = getEntityMetamodel().getPropertyIndexOrNull( propertyName );
if ( index == null ) {
return null;
}
return tableNames[propertyTableNumbers[index]];
}
public String[] getConstraintOrderedTableNameClosure() {
return constraintOrderedTableNames;
}
public String[][] getContraintOrderedTableKeyColumnClosure() {
return constraintOrderedKeyColumnNames;
}
public String getRootTableName() {
return naturalOrderTableNames[0];
}
public String getRootTableAlias(String drivingAlias) {
return generateTableAlias( drivingAlias, getTableId( getRootTableName(), tableNames ) );
}
public Declarer getSubclassPropertyDeclarer(String propertyPath) {
if ( "class".equals( propertyPath ) ) {
// special case where we need to force include all subclass joins
return Declarer.SUBCLASS;
}
return super.getSubclassPropertyDeclarer( propertyPath );
}
@Override
public int determineTableNumberForColumn(String columnName) {
// HHH-7630: In case the naturalOrder/identifier column is explicitly given in the ordering, check here.
for ( int i = 0, max = naturalOrderTableKeyColumns.length; i < max; i++ ) {
final String[] keyColumns = naturalOrderTableKeyColumns[i];
if ( ArrayHelper.contains( keyColumns, columnName ) ) {
return naturalOrderPropertyTableNumbers[i];
}
}
final String[] subclassColumnNameClosure = getSubclassColumnClosure();
for ( int i = 0, max = subclassColumnNameClosure.length; i < max; i++ ) {
final boolean quoted = subclassColumnNameClosure[i].startsWith( "\"" )
&& subclassColumnNameClosure[i].endsWith( "\"" );
if ( quoted ) {
if ( subclassColumnNameClosure[i].equals( columnName ) ) {
return getSubclassColumnTableNumberClosure()[i];
}
}
else {
if ( subclassColumnNameClosure[i].equalsIgnoreCase( columnName ) ) {
return getSubclassColumnTableNumberClosure()[i];
}
}
}
throw new HibernateException( "Could not locate table which owns column [" + columnName + "] referenced in order-by mapping" );
}
@Override
public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) {
return new DynamicFilterAliasGenerator(subclassTableNameClosure, rootAlias);
}
}