Please wait. This can take some minutes ...
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.
org.hibernate.persister.collection.AbstractCollectionPersister Maven / Gradle / Ivy
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
*
* 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.persister.collection;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.TransientObjectException;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.entry.CacheEntryStructure;
import org.hibernate.cache.entry.StructuredCollectionCacheEntry;
import org.hibernate.cache.entry.StructuredMapCacheEntry;
import org.hibernate.cache.entry.UnstructuredCacheEntry;
import org.hibernate.cfg.Configuration;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.EntityKey;
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.collection.CollectionInitializer;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.IdentifierCollection;
import org.hibernate.mapping.IndexedCollection;
import org.hibernate.mapping.List;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Table;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Alias;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.Template;
import org.hibernate.sql.ordering.antlr.ColumnMapper;
import org.hibernate.type.AbstractComponentType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.FilterHelper;
import org.hibernate.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base implementation of the QueryableCollection interface.
*
* @author Gavin King
* @see BasicCollectionPersister
* @see OneToManyPersister
*/
public abstract class AbstractCollectionPersister
implements CollectionMetadata, SQLLoadableCollection {
// TODO: encapsulate the protected instance variables!
private final String role;
//SQL statements
private final String sqlDeleteString;
private final String sqlInsertRowString;
private final String sqlUpdateRowString;
private final String sqlDeleteRowString;
private final String sqlSelectSizeString;
private final String sqlSelectRowByIndexString;
private final String sqlDetectRowByIndexString;
private final String sqlDetectRowByElementString;
protected final String sqlWhereString;
private final String sqlOrderByStringTemplate;
private final String sqlWhereStringTemplate;
private final boolean hasOrder;
protected final boolean hasWhere;
private final int baseIndex;
private final String nodeName;
private final String elementNodeName;
private final String indexNodeName;
protected final boolean indexContainsFormula;
protected final boolean elementIsPureFormula;
//types
private final Type keyType;
private final Type indexType;
protected final Type elementType;
private final Type identifierType;
//columns
protected final String[] keyColumnNames;
protected final String[] indexColumnNames;
protected final String[] indexFormulaTemplates;
protected final String[] indexFormulas;
protected final boolean[] indexColumnIsSettable;
protected final String[] elementColumnNames;
protected final String[] elementColumnWriters;
protected final String[] elementColumnReaders;
protected final String[] elementColumnReaderTemplates;
protected final String[] elementFormulaTemplates;
protected final String[] elementFormulas;
protected final boolean[] elementColumnIsSettable;
protected final boolean[] elementColumnIsInPrimaryKey;
protected final String[] indexColumnAliases;
protected final String[] elementColumnAliases;
protected final String[] keyColumnAliases;
protected final String identifierColumnName;
private final String identifierColumnAlias;
//private final String unquotedIdentifierColumnName;
protected final String qualifiedTableName;
private final String queryLoaderName;
private final boolean isPrimitiveArray;
private final boolean isArray;
protected final boolean hasIndex;
protected final boolean hasIdentifier;
private final boolean isLazy;
private final boolean isExtraLazy;
private final boolean isInverse;
private final boolean isMutable;
private final boolean isVersioned;
protected final int batchSize;
private final FetchMode fetchMode;
private final boolean hasOrphanDelete;
private final boolean subselectLoadable;
//extra information about the element type
private final Class elementClass;
private final String entityName;
private final Dialect dialect;
private final SQLExceptionConverter sqlExceptionConverter;
private final SessionFactoryImplementor factory;
private final EntityPersister ownerPersister;
private final IdentifierGenerator identifierGenerator;
private final PropertyMapping elementPropertyMapping;
private final EntityPersister elementPersister;
private final CollectionRegionAccessStrategy cacheAccessStrategy;
private final CollectionType collectionType;
private CollectionInitializer initializer;
private final CacheEntryStructure cacheEntryStructure;
// dynamic filters for the collection
private final FilterHelper filterHelper;
// dynamic filters specifically for many-to-many inside the collection
private final FilterHelper manyToManyFilterHelper;
private final String manyToManyWhereString;
private final String manyToManyWhereTemplate;
private final boolean hasManyToManyOrder;
private final String manyToManyOrderByTemplate;
// custom sql
private final boolean insertCallable;
private final boolean updateCallable;
private final boolean deleteCallable;
private final boolean deleteAllCallable;
private ExecuteUpdateResultCheckStyle insertCheckStyle;
private ExecuteUpdateResultCheckStyle updateCheckStyle;
private ExecuteUpdateResultCheckStyle deleteCheckStyle;
private ExecuteUpdateResultCheckStyle deleteAllCheckStyle;
private final Serializable[] spaces;
private Map collectionPropertyColumnAliases = new HashMap();
private Map collectionPropertyColumnNames = new HashMap();
private static final Logger log = LoggerFactory.getLogger( AbstractCollectionPersister.class );
public AbstractCollectionPersister(
final Collection collection,
final CollectionRegionAccessStrategy cacheAccessStrategy,
final Configuration cfg,
final SessionFactoryImplementor factory) throws MappingException, CacheException {
this.factory = factory;
this.cacheAccessStrategy = cacheAccessStrategy;
if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) {
cacheEntryStructure = collection.isMap() ?
( CacheEntryStructure ) new StructuredMapCacheEntry() :
( CacheEntryStructure ) new StructuredCollectionCacheEntry();
}
else {
cacheEntryStructure = new UnstructuredCacheEntry();
}
dialect = factory.getDialect();
sqlExceptionConverter = factory.getSQLExceptionConverter();
collectionType = collection.getCollectionType();
role = collection.getRole();
entityName = collection.getOwnerEntityName();
ownerPersister = factory.getEntityPersister(entityName);
queryLoaderName = collection.getLoaderName();
nodeName = collection.getNodeName();
isMutable = collection.isMutable();
Table table = collection.getCollectionTable();
fetchMode = collection.getElement().getFetchMode();
elementType = collection.getElement().getType();
//isSet = collection.isSet();
//isSorted = collection.isSorted();
isPrimitiveArray = collection.isPrimitiveArray();
isArray = collection.isArray();
subselectLoadable = collection.isSubselectLoadable();
qualifiedTableName = table.getQualifiedName(
dialect,
factory.getSettings().getDefaultCatalogName(),
factory.getSettings().getDefaultSchemaName()
);
int spacesSize = 1 + collection.getSynchronizedTables().size();
spaces = new String[spacesSize];
spaces[0] = qualifiedTableName;
Iterator iter = collection.getSynchronizedTables().iterator();
for ( int i = 1; i < spacesSize; i++ ) {
spaces[i] = (String) iter.next();
}
sqlWhereString = StringHelper.isNotEmpty( collection.getWhere() ) ? "( " + collection.getWhere() + ") " : null;
hasWhere = sqlWhereString != null;
sqlWhereStringTemplate = hasWhere ?
Template.renderWhereStringTemplate(sqlWhereString, dialect, factory.getSqlFunctionRegistry()) :
null;
hasOrphanDelete = collection.hasOrphanDelete();
int batch = collection.getBatchSize();
if ( batch == -1 ) {
batch = factory.getSettings().getDefaultBatchFetchSize();
}
batchSize = batch;
isVersioned = collection.isOptimisticLocked();
// KEY
keyType = collection.getKey().getType();
iter = collection.getKey().getColumnIterator();
int keySpan = collection.getKey().getColumnSpan();
keyColumnNames = new String[keySpan];
keyColumnAliases = new String[keySpan];
int k = 0;
while ( iter.hasNext() ) {
// NativeSQL: collect key column and auto-aliases
Column col = ( (Column) iter.next() );
keyColumnNames[k] = col.getQuotedName(dialect);
keyColumnAliases[k] = col.getAlias(dialect,collection.getOwner().getRootTable());
k++;
}
//unquotedKeyColumnNames = StringHelper.unQuote(keyColumnAliases);
//ELEMENT
String elemNode = collection.getElementNodeName();
if ( elementType.isEntityType() ) {
String entityName = ( (EntityType) elementType ).getAssociatedEntityName();
elementPersister = factory.getEntityPersister(entityName);
if ( elemNode==null ) {
elemNode = cfg.getClassMapping(entityName).getNodeName();
}
// NativeSQL: collect element column and auto-aliases
}
else {
elementPersister = null;
}
elementNodeName = elemNode;
int elementSpan = collection.getElement().getColumnSpan();
elementColumnAliases = new String[elementSpan];
elementColumnNames = new String[elementSpan];
elementColumnWriters = new String[elementSpan];
elementColumnReaders = new String[elementSpan];
elementColumnReaderTemplates = new String[elementSpan];
elementFormulaTemplates = new String[elementSpan];
elementFormulas = new String[elementSpan];
elementColumnIsSettable = new boolean[elementSpan];
elementColumnIsInPrimaryKey = new boolean[elementSpan];
boolean isPureFormula = true;
boolean hasNotNullableColumns = false;
int j = 0;
iter = collection.getElement().getColumnIterator();
while ( iter.hasNext() ) {
Selectable selectable = (Selectable) iter.next();
elementColumnAliases[j] = selectable.getAlias(dialect);
if ( selectable.isFormula() ) {
Formula form = (Formula) selectable;
elementFormulaTemplates[j] = form.getTemplate(dialect, factory.getSqlFunctionRegistry());
elementFormulas[j] = form.getFormula();
}
else {
Column col = (Column) selectable;
elementColumnNames[j] = col.getQuotedName(dialect);
elementColumnWriters[j] = col.getWriteExpr();
elementColumnReaders[j] = col.getReadExpr(dialect);
elementColumnReaderTemplates[j] = col.getTemplate(dialect, factory.getSqlFunctionRegistry());
elementColumnIsSettable[j] = true;
elementColumnIsInPrimaryKey[j] = !col.isNullable();
if ( !col.isNullable() ) {
hasNotNullableColumns = true;
}
isPureFormula = false;
}
j++;
}
elementIsPureFormula = isPureFormula;
//workaround, for backward compatibility of sets with no
//not-null columns, assume all columns are used in the
//row locator SQL
if ( !hasNotNullableColumns ) {
Arrays.fill( elementColumnIsInPrimaryKey, true );
}
// INDEX AND ROW SELECT
hasIndex = collection.isIndexed();
if (hasIndex) {
// NativeSQL: collect index column and auto-aliases
IndexedCollection indexedCollection = (IndexedCollection) collection;
indexType = indexedCollection.getIndex().getType();
int indexSpan = indexedCollection.getIndex().getColumnSpan();
iter = indexedCollection.getIndex().getColumnIterator();
indexColumnNames = new String[indexSpan];
indexFormulaTemplates = new String[indexSpan];
indexFormulas = new String[indexSpan];
indexColumnIsSettable = new boolean[indexSpan];
indexColumnAliases = new String[indexSpan];
int i = 0;
boolean hasFormula = false;
while ( iter.hasNext() ) {
Selectable s = (Selectable) iter.next();
indexColumnAliases[i] = s.getAlias(dialect);
if ( s.isFormula() ) {
Formula indexForm = (Formula) s;
indexFormulaTemplates[i] = indexForm.getTemplate(dialect, factory.getSqlFunctionRegistry());
indexFormulas[i] = indexForm.getFormula();
hasFormula = true;
}
else {
Column indexCol = (Column) s;
indexColumnNames[i] = indexCol.getQuotedName(dialect);
indexColumnIsSettable[i] = true;
}
i++;
}
indexContainsFormula = hasFormula;
baseIndex = indexedCollection.isList() ?
( (List) indexedCollection ).getBaseIndex() : 0;
indexNodeName = indexedCollection.getIndexNodeName();
}
else {
indexContainsFormula = false;
indexColumnIsSettable = null;
indexFormulaTemplates = null;
indexFormulas = null;
indexType = null;
indexColumnNames = null;
indexColumnAliases = null;
baseIndex = 0;
indexNodeName = null;
}
hasIdentifier = collection.isIdentified();
if (hasIdentifier) {
if ( collection.isOneToMany() ) {
throw new MappingException( "one-to-many collections with identifiers are not supported" );
}
IdentifierCollection idColl = (IdentifierCollection) collection;
identifierType = idColl.getIdentifier().getType();
iter = idColl.getIdentifier().getColumnIterator();
Column col = ( Column ) iter.next();
identifierColumnName = col.getQuotedName(dialect);
identifierColumnAlias = col.getAlias(dialect);
//unquotedIdentifierColumnName = identifierColumnAlias;
identifierGenerator = idColl.getIdentifier().createIdentifierGenerator(
cfg.getIdentifierGeneratorFactory(),
factory.getDialect(),
factory.getSettings().getDefaultCatalogName(),
factory.getSettings().getDefaultSchemaName(),
null
);
}
else {
identifierType = null;
identifierColumnName = null;
identifierColumnAlias = null;
//unquotedIdentifierColumnName = null;
identifierGenerator = null;
}
//GENERATE THE SQL:
//sqlSelectString = sqlSelectString();
//sqlSelectRowString = sqlSelectRowString();
if ( collection.getCustomSQLInsert() == null ) {
sqlInsertRowString = generateInsertRowString();
insertCallable = false;
insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
}
else {
sqlInsertRowString = collection.getCustomSQLInsert();
insertCallable = collection.isCustomInsertCallable();
insertCheckStyle = collection.getCustomSQLInsertCheckStyle() == null
? ExecuteUpdateResultCheckStyle.determineDefault( collection.getCustomSQLInsert(), insertCallable )
: collection.getCustomSQLInsertCheckStyle();
}
if ( collection.getCustomSQLUpdate() == null ) {
sqlUpdateRowString = generateUpdateRowString();
updateCallable = false;
updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
}
else {
sqlUpdateRowString = collection.getCustomSQLUpdate();
updateCallable = collection.isCustomUpdateCallable();
updateCheckStyle = collection.getCustomSQLUpdateCheckStyle() == null
? ExecuteUpdateResultCheckStyle.determineDefault( collection.getCustomSQLUpdate(), insertCallable )
: collection.getCustomSQLUpdateCheckStyle();
}
if ( collection.getCustomSQLDelete() == null ) {
sqlDeleteRowString = generateDeleteRowString();
deleteCallable = false;
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
}
else {
sqlDeleteRowString = collection.getCustomSQLDelete();
deleteCallable = collection.isCustomDeleteCallable();
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
}
if ( collection.getCustomSQLDeleteAll() == null ) {
sqlDeleteString = generateDeleteString();
deleteAllCallable = false;
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
}
else {
sqlDeleteString = collection.getCustomSQLDeleteAll();
deleteAllCallable = collection.isCustomDeleteAllCallable();
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
}
sqlSelectSizeString = generateSelectSizeString( collection.isIndexed() && !collection.isMap() );
sqlDetectRowByIndexString = generateDetectRowByIndexString();
sqlDetectRowByElementString = generateDetectRowByElementString();
sqlSelectRowByIndexString = generateSelectRowByIndexString();
logStaticSQL();
isLazy = collection.isLazy();
isExtraLazy = collection.isExtraLazy();
isInverse = collection.isInverse();
if ( collection.isArray() ) {
elementClass = ( (org.hibernate.mapping.Array) collection ).getElementClass();
}
else {
// for non-arrays, we don't need to know the element class
elementClass = null; //elementType.returnedClass();
}
if ( elementType.isComponentType() ) {
elementPropertyMapping = new CompositeElementPropertyMapping(
elementColumnNames,
elementColumnReaders,
elementColumnReaderTemplates,
elementFormulaTemplates,
(AbstractComponentType) elementType,
factory
);
}
else if ( !elementType.isEntityType() ) {
elementPropertyMapping = new ElementPropertyMapping(
elementColumnNames,
elementType
);
}
else {
if ( elementPersister instanceof PropertyMapping ) { //not all classpersisters implement PropertyMapping!
elementPropertyMapping = (PropertyMapping) elementPersister;
}
else {
elementPropertyMapping = new ElementPropertyMapping(
elementColumnNames,
elementType
);
}
}
hasOrder = collection.getOrderBy() != null;
if ( hasOrder ) {
ColumnMapper mapper = new ColumnMapper() {
public String[] map(String reference) {
return elementPropertyMapping.toColumns( reference );
}
};
sqlOrderByStringTemplate = Template.renderOrderByStringTemplate(
collection.getOrderBy(),
mapper,
factory,
dialect,
factory.getSqlFunctionRegistry()
);
}
else {
sqlOrderByStringTemplate = null;
}
// Handle any filters applied to this collection
filterHelper = new FilterHelper( collection.getFilterMap(), dialect, factory.getSqlFunctionRegistry() );
// Handle any filters applied to this collection for many-to-many
manyToManyFilterHelper = new FilterHelper( collection.getManyToManyFilterMap(), dialect, factory.getSqlFunctionRegistry() );
manyToManyWhereString = StringHelper.isNotEmpty( collection.getManyToManyWhere() ) ?
"( " + collection.getManyToManyWhere() + ")" :
null;
manyToManyWhereTemplate = manyToManyWhereString == null ?
null :
Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() );
hasManyToManyOrder = collection.getManyToManyOrdering() != null;
if ( hasManyToManyOrder ) {
ColumnMapper mapper = new ColumnMapper() {
public String[] map(String reference) {
return elementPropertyMapping.toColumns( reference );
}
};
manyToManyOrderByTemplate = Template.renderOrderByStringTemplate(
collection.getManyToManyOrdering(),
mapper,
factory,
dialect,
factory.getSqlFunctionRegistry()
);
}
else {
manyToManyOrderByTemplate = null;
}
initCollectionPropertyMap();
}
public void postInstantiate() throws MappingException {
initializer = queryLoaderName == null ?
createCollectionInitializer( LoadQueryInfluencers.NONE ) :
new NamedQueryCollectionInitializer( queryLoaderName, this );
}
protected void logStaticSQL() {
if ( log.isDebugEnabled() ) {
log.debug( "Static SQL for collection: " + getRole() );
if ( getSQLInsertRowString() != null ) {
log.debug( " Row insert: " + getSQLInsertRowString() );
}
if ( getSQLUpdateRowString() != null ) {
log.debug( " Row update: " + getSQLUpdateRowString() );
}
if ( getSQLDeleteRowString() != null ) {
log.debug( " Row delete: " + getSQLDeleteRowString() );
}
if ( getSQLDeleteString() != null ) {
log.debug( " One-shot delete: " + getSQLDeleteString() );
}
}
}
public void initialize(Serializable key, SessionImplementor session) throws HibernateException {
getAppropriateInitializer( key, session ).initialize( key, session );
}
protected CollectionInitializer getAppropriateInitializer(Serializable key, SessionImplementor session) {
if ( queryLoaderName != null ) {
//if there is a user-specified loader, return that
//TODO: filters!?
return initializer;
}
CollectionInitializer subselectInitializer = getSubselectInitializer( key, session );
if ( subselectInitializer != null ) {
return subselectInitializer;
}
else if ( session.getEnabledFilters().isEmpty() ) {
return initializer;
}
else {
return createCollectionInitializer( session.getLoadQueryInfluencers() );
}
}
private CollectionInitializer getSubselectInitializer(Serializable key, SessionImplementor session) {
if ( !isSubselectLoadable() ) {
return null;
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
SubselectFetch subselect = persistenceContext.getBatchFetchQueue()
.getSubselect( new EntityKey( key, getOwnerEntityPersister(), session.getEntityMode() ) );
if (subselect == null) {
return null;
}
else {
// Take care of any entities that might have
// been evicted!
Iterator iter = subselect.getResult().iterator();
while ( iter.hasNext() ) {
if ( !persistenceContext.containsEntity( (EntityKey) iter.next() ) ) {
iter.remove();
}
}
// Run a subquery loader
return createSubselectInitializer( subselect, session );
}
}
protected abstract CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SessionImplementor session);
protected abstract CollectionInitializer createCollectionInitializer(LoadQueryInfluencers loadQueryInfluencers)
throws MappingException;
public CollectionRegionAccessStrategy getCacheAccessStrategy() {
return cacheAccessStrategy;
}
public boolean hasCache() {
return cacheAccessStrategy != null;
}
public CollectionType getCollectionType() {
return collectionType;
}
protected String getSQLWhereString(String alias) {
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
}
public String getSQLOrderByString(String alias) {
return hasOrdering()
? StringHelper.replace( sqlOrderByStringTemplate, Template.TEMPLATE, alias )
: "";
}
public String getManyToManyOrderByString(String alias) {
return hasManyToManyOrdering()
? StringHelper.replace( manyToManyOrderByTemplate, Template.TEMPLATE, alias )
: "";
}
public FetchMode getFetchMode() {
return fetchMode;
}
public boolean hasOrdering() {
return hasOrder;
}
public boolean hasManyToManyOrdering() {
return isManyToMany() && hasManyToManyOrder;
}
public boolean hasWhere() {
return hasWhere;
}
protected String getSQLDeleteString() {
return sqlDeleteString;
}
protected String getSQLInsertRowString() {
return sqlInsertRowString;
}
protected String getSQLUpdateRowString() {
return sqlUpdateRowString;
}
protected String getSQLDeleteRowString() {
return sqlDeleteRowString;
}
public Type getKeyType() {
return keyType;
}
public Type getIndexType() {
return indexType;
}
public Type getElementType() {
return elementType;
}
/**
* Return the element class of an array, or null otherwise
*/
public Class getElementClass() { //needed by arrays
return elementClass;
}
public Object readElement(ResultSet rs, Object owner, String[] aliases, SessionImplementor session)
throws HibernateException, SQLException {
return getElementType().nullSafeGet( rs, aliases, session, owner );
}
public Object readIndex(ResultSet rs, String[] aliases, SessionImplementor session)
throws HibernateException, SQLException {
Object index = getIndexType().nullSafeGet( rs, aliases, session, null );
if ( index == null ) {
throw new HibernateException( "null index column for collection: " + role );
}
index = decrementIndexByBase( index );
return index;
}
protected Object decrementIndexByBase(Object index) {
if (baseIndex!=0) {
index = new Integer( ( (Integer) index ).intValue() - baseIndex );
}
return index;
}
public Object readIdentifier(ResultSet rs, String alias, SessionImplementor session)
throws HibernateException, SQLException {
Object id = getIdentifierType().nullSafeGet( rs, alias, session, null );
if ( id == null ) {
throw new HibernateException( "null identifier column for collection: " + role );
}
return id;
}
public Object readKey(ResultSet rs, String[] aliases, SessionImplementor session)
throws HibernateException, SQLException {
return getKeyType().nullSafeGet( rs, aliases, session, null );
}
/**
* Write the key to a JDBC PreparedStatement
*/
protected int writeKey(PreparedStatement st, Serializable key, int i, SessionImplementor session)
throws HibernateException, SQLException {
if ( key == null ) {
throw new NullPointerException( "null key for collection: " + role ); //an assertion
}
getKeyType().nullSafeSet( st, key, i, session );
return i + keyColumnAliases.length;
}
/**
* Write the element to a JDBC PreparedStatement
*/
protected int writeElement(PreparedStatement st, Object elt, int i, SessionImplementor session)
throws HibernateException, SQLException {
getElementType().nullSafeSet(st, elt, i, elementColumnIsSettable, session);
return i + ArrayHelper.countTrue(elementColumnIsSettable);
}
/**
* Write the index to a JDBC PreparedStatement
*/
protected int writeIndex(PreparedStatement st, Object index, int i, SessionImplementor session)
throws HibernateException, SQLException {
getIndexType().nullSafeSet( st, incrementIndexByBase(index), i, indexColumnIsSettable, session );
return i + ArrayHelper.countTrue(indexColumnIsSettable);
}
protected Object incrementIndexByBase(Object index) {
if (baseIndex!=0) {
index = new Integer( ( (Integer) index ).intValue() + baseIndex );
}
return index;
}
/**
* Write the element to a JDBC PreparedStatement
*/
protected int writeElementToWhere(PreparedStatement st, Object elt, int i, SessionImplementor session)
throws HibernateException, SQLException {
if (elementIsPureFormula) {
throw new AssertionFailure("cannot use a formula-based element in the where condition");
}
getElementType().nullSafeSet(st, elt, i, elementColumnIsInPrimaryKey, session);
return i + elementColumnAliases.length;
}
/**
* Write the index to a JDBC PreparedStatement
*/
protected int writeIndexToWhere(PreparedStatement st, Object index, int i, SessionImplementor session)
throws HibernateException, SQLException {
if (indexContainsFormula) {
throw new AssertionFailure("cannot use a formula-based index in the where condition");
}
getIndexType().nullSafeSet( st, incrementIndexByBase(index), i, session );
return i + indexColumnAliases.length;
}
/**
* Write the identifier to a JDBC PreparedStatement
*/
public int writeIdentifier(PreparedStatement st, Object id, int i, SessionImplementor session)
throws HibernateException, SQLException {
getIdentifierType().nullSafeSet( st, id, i, session );
return i + 1;
}
public boolean isPrimitiveArray() {
return isPrimitiveArray;
}
public boolean isArray() {
return isArray;
}
public String[] getKeyColumnAliases(String suffix) {
return new Alias( suffix ).toAliasStrings( keyColumnAliases );
}
public String[] getElementColumnAliases(String suffix) {
return new Alias( suffix ).toAliasStrings( elementColumnAliases );
}
public String[] getIndexColumnAliases(String suffix) {
if ( hasIndex ) {
return new Alias( suffix ).toAliasStrings( indexColumnAliases );
}
else {
return null;
}
}
public String getIdentifierColumnAlias(String suffix) {
if ( hasIdentifier ) {
return new Alias( suffix ).toAliasString( identifierColumnAlias );
}
else {
return null;
}
}
public String getIdentifierColumnName() {
if ( hasIdentifier ) {
return identifierColumnName;
} else {
return null;
}
}
/**
* Generate a list of collection index, key and element columns
*/
public String selectFragment(String alias, String columnSuffix) {
SelectFragment frag = generateSelectFragment( alias, columnSuffix );
appendElementColumns( frag, alias );
appendIndexColumns( frag, alias );
appendIdentifierColumns( frag, alias );
return frag.toFragmentString()
.substring( 2 ); //strip leading ','
}
protected String generateSelectSizeString(boolean isIntegerIndexed) {
String selectValue = isIntegerIndexed ?
"max(" + getIndexColumnNames()[0] + ") + 1": //lists, arrays
"count(" + getElementColumnNames()[0] + ")"; //sets, maps, bags
return new SimpleSelect(dialect)
.setTableName( getTableName() )
.addCondition( getKeyColumnNames(), "=?" )
.addColumn(selectValue)
.toStatementString();
}
protected String generateDetectRowByIndexString() {
if ( !hasIndex() ) {
return null;
}
return new SimpleSelect(dialect)
.setTableName( getTableName() )
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getIndexColumnNames(), "=?" )
.addCondition( indexFormulas, "=?" )
.addColumn("1")
.toStatementString();
}
protected String generateSelectRowByIndexString() {
if ( !hasIndex() ) {
return null;
}
return new SimpleSelect(dialect)
.setTableName( getTableName() )
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getIndexColumnNames(), "=?" )
.addCondition( indexFormulas, "=?" )
.addColumns( getElementColumnNames(), elementColumnAliases )
.addColumns( indexFormulas, indexColumnAliases )
.toStatementString();
}
protected String generateDetectRowByElementString() {
return new SimpleSelect(dialect)
.setTableName( getTableName() )
.addCondition( getKeyColumnNames(), "=?" )
.addCondition( getElementColumnNames(), "=?" )
.addCondition( elementFormulas, "=?" )
.addColumn("1")
.toStatementString();
}
protected SelectFragment generateSelectFragment(String alias, String columnSuffix) {
return new SelectFragment()
.setSuffix( columnSuffix )
.addColumns( alias, keyColumnNames, keyColumnAliases );
}
protected void appendElementColumns(SelectFragment frag, String elemAlias) {
for ( int i=0; i