1
//$Id: AbstractCollectionPersister.java 10901 2006-11-30 21:50:48Z epbernard $
2
package org.hibernate.persister.collection;
4
import java.io.Serializable;
5
import java.sql.PreparedStatement;
6
import java.sql.ResultSet;
7
import java.sql.SQLException;
8
import java.util.Arrays;
9
import java.util.HashMap;
10
import java.util.Iterator;
13
import org.apache.commons.logging.Log;
14
import org.apache.commons.logging.LogFactory;
15
import org.hibernate.AssertionFailure;
16
import org.hibernate.FetchMode;
17
import org.hibernate.HibernateException;
18
import org.hibernate.MappingException;
19
import org.hibernate.QueryException;
20
import org.hibernate.TransientObjectException;
21
import org.hibernate.jdbc.Expectation;
22
import org.hibernate.jdbc.Expectations;
23
import org.hibernate.cache.CacheConcurrencyStrategy;
24
import org.hibernate.cache.CacheException;
25
import org.hibernate.cache.entry.CacheEntryStructure;
26
import org.hibernate.cache.entry.StructuredCollectionCacheEntry;
27
import org.hibernate.cache.entry.StructuredMapCacheEntry;
28
import org.hibernate.cache.entry.UnstructuredCacheEntry;
29
import org.hibernate.cfg.Configuration;
30
import org.hibernate.collection.PersistentCollection;
31
import org.hibernate.dialect.Dialect;
32
import org.hibernate.engine.EntityKey;
33
import org.hibernate.engine.PersistenceContext;
34
import org.hibernate.engine.SessionFactoryImplementor;
35
import org.hibernate.engine.SessionImplementor;
36
import org.hibernate.engine.SubselectFetch;
37
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
38
import org.hibernate.exception.JDBCExceptionHelper;
39
import org.hibernate.exception.SQLExceptionConverter;
40
import org.hibernate.id.IdentifierGenerator;
41
import org.hibernate.loader.collection.CollectionInitializer;
42
import org.hibernate.mapping.Collection;
43
import org.hibernate.mapping.Column;
44
import org.hibernate.mapping.Formula;
45
import org.hibernate.mapping.IdentifierCollection;
46
import org.hibernate.mapping.IndexedCollection;
47
import org.hibernate.mapping.List;
48
import org.hibernate.mapping.Selectable;
49
import org.hibernate.mapping.Table;
50
import org.hibernate.metadata.CollectionMetadata;
51
import org.hibernate.persister.entity.EntityPersister;
52
import org.hibernate.persister.entity.Loadable;
53
import org.hibernate.persister.entity.PropertyMapping;
54
import org.hibernate.pretty.MessageHelper;
55
import org.hibernate.sql.Alias;
56
import org.hibernate.sql.SelectFragment;
57
import org.hibernate.sql.SimpleSelect;
58
import org.hibernate.sql.Template;
59
import org.hibernate.type.AbstractComponentType;
60
import org.hibernate.type.CollectionType;
61
import org.hibernate.type.EntityType;
62
import org.hibernate.type.Type;
63
import org.hibernate.util.ArrayHelper;
64
import org.hibernate.util.CollectionHelper;
65
import org.hibernate.util.FilterHelper;
66
import org.hibernate.util.StringHelper;
70
* Base implementation of the <tt>QueryableCollection</tt> interface.
73
* @see BasicCollectionPersister
74
* @see OneToManyPersister
76
public abstract class AbstractCollectionPersister
77
implements CollectionMetadata, SQLLoadableCollection {
78
// TODO: encapsulate the protected instance variables!
80
private final String role;
83
private final String sqlDeleteString;
84
private final String sqlInsertRowString;
85
private final String sqlUpdateRowString;
86
private final String sqlDeleteRowString;
87
private final String sqlSelectSizeString;
88
private final String sqlSelectRowByIndexString;
89
private final String sqlDetectRowByIndexString;
90
private final String sqlDetectRowByElementString;
92
private final String sqlOrderByString;
93
protected final String sqlWhereString;
94
private final String sqlOrderByStringTemplate;
95
private final String sqlWhereStringTemplate;
96
private final boolean hasOrder;
97
protected final boolean hasWhere;
98
private final int baseIndex;
100
private final String nodeName;
101
private final String elementNodeName;
102
private final String indexNodeName;
104
protected final boolean indexContainsFormula;
105
protected final boolean elementIsPureFormula;
108
private final Type keyType;
109
private final Type indexType;
110
protected final Type elementType;
111
private final Type identifierType;
114
protected final String[] keyColumnNames;
115
protected final String[] indexColumnNames;
116
protected final String[] indexFormulaTemplates;
117
protected final String[] indexFormulas;
118
protected final boolean[] indexColumnIsSettable;
119
protected final String[] elementColumnNames;
120
protected final String[] elementFormulaTemplates;
121
protected final String[] elementFormulas;
122
protected final boolean[] elementColumnIsSettable;
123
protected final boolean[] elementColumnIsInPrimaryKey;
124
protected final String[] indexColumnAliases;
125
protected final String[] elementColumnAliases;
126
protected final String[] keyColumnAliases;
128
protected final String identifierColumnName;
129
private final String identifierColumnAlias;
130
//private final String unquotedIdentifierColumnName;
132
protected final String qualifiedTableName;
134
private final String queryLoaderName;
136
private final boolean isPrimitiveArray;
137
private final boolean isArray;
138
protected final boolean hasIndex;
139
protected final boolean hasIdentifier;
140
private final boolean isLazy;
141
private final boolean isExtraLazy;
142
private final boolean isInverse;
143
private final boolean isMutable;
144
private final boolean isVersioned;
145
protected final int batchSize;
146
private final FetchMode fetchMode;
147
private final boolean hasOrphanDelete;
148
private final boolean subselectLoadable;
150
//extra information about the element type
151
private final Class elementClass;
152
private final String entityName;
154
private final Dialect dialect;
155
private final SQLExceptionConverter sqlExceptionConverter;
156
private final SessionFactoryImplementor factory;
157
private final EntityPersister ownerPersister;
158
private final IdentifierGenerator identifierGenerator;
159
private final PropertyMapping elementPropertyMapping;
160
private final EntityPersister elementPersister;
161
private final CacheConcurrencyStrategy cache;
162
private final CollectionType collectionType;
163
private CollectionInitializer initializer;
165
private final CacheEntryStructure cacheEntryStructure;
167
// dynamic filters for the collection
168
private final FilterHelper filterHelper;
170
// dynamic filters specifically for many-to-many inside the collection
171
private final FilterHelper manyToManyFilterHelper;
173
private final String manyToManyWhereString;
174
private final String manyToManyWhereTemplate;
176
private final String manyToManyOrderByString;
177
private final String manyToManyOrderByTemplate;
180
private final boolean insertCallable;
181
private final boolean updateCallable;
182
private final boolean deleteCallable;
183
private final boolean deleteAllCallable;
184
private ExecuteUpdateResultCheckStyle insertCheckStyle;
185
private ExecuteUpdateResultCheckStyle updateCheckStyle;
186
private ExecuteUpdateResultCheckStyle deleteCheckStyle;
187
private ExecuteUpdateResultCheckStyle deleteAllCheckStyle;
189
private final Serializable[] spaces;
191
private Map collectionPropertyColumnAliases = new HashMap();
192
private Map collectionPropertyColumnNames = new HashMap();
194
private static final Log log = LogFactory.getLog( AbstractCollectionPersister.class );
196
public AbstractCollectionPersister(
197
final Collection collection,
198
final CacheConcurrencyStrategy cache,
199
final Configuration cfg,
200
final SessionFactoryImplementor factory)
201
throws MappingException, CacheException {
203
this.factory = factory;
205
if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) {
206
cacheEntryStructure = collection.isMap() ?
207
(CacheEntryStructure) new StructuredMapCacheEntry() :
208
(CacheEntryStructure) new StructuredCollectionCacheEntry();
211
cacheEntryStructure = new UnstructuredCacheEntry();
214
dialect = factory.getDialect();
215
sqlExceptionConverter = factory.getSQLExceptionConverter();
216
collectionType = collection.getCollectionType();
217
role = collection.getRole();
218
entityName = collection.getOwnerEntityName();
219
ownerPersister = factory.getEntityPersister(entityName);
220
queryLoaderName = collection.getLoaderName();
221
nodeName = collection.getNodeName();
222
isMutable = collection.isMutable();
224
Table table = collection.getCollectionTable();
225
fetchMode = collection.getElement().getFetchMode();
226
elementType = collection.getElement().getType();
227
//isSet = collection.isSet();
228
//isSorted = collection.isSorted();
229
isPrimitiveArray = collection.isPrimitiveArray();
230
isArray = collection.isArray();
231
subselectLoadable = collection.isSubselectLoadable();
233
qualifiedTableName = table.getQualifiedName(
235
factory.getSettings().getDefaultCatalogName(),
236
factory.getSettings().getDefaultSchemaName()
239
int spacesSize = 1 + collection.getSynchronizedTables().size();
240
spaces = new String[spacesSize];
241
spaces[0] = qualifiedTableName;
242
Iterator iter = collection.getSynchronizedTables().iterator();
243
for ( int i = 1; i < spacesSize; i++ ) {
244
spaces[i] = (String) iter.next();
247
sqlOrderByString = collection.getOrderBy();
248
hasOrder = sqlOrderByString != null;
249
sqlOrderByStringTemplate = hasOrder ?
250
Template.renderOrderByStringTemplate(sqlOrderByString, dialect, factory.getSqlFunctionRegistry()) :
252
sqlWhereString = StringHelper.isNotEmpty( collection.getWhere() ) ? "( " + collection.getWhere() + ") " : null;
253
hasWhere = sqlWhereString != null;
254
sqlWhereStringTemplate = hasWhere ?
255
Template.renderWhereStringTemplate(sqlWhereString, dialect, factory.getSqlFunctionRegistry()) :
258
hasOrphanDelete = collection.hasOrphanDelete();
260
int batch = collection.getBatchSize();
262
batch = factory.getSettings().getDefaultBatchFetchSize();
266
isVersioned = collection.isOptimisticLocked();
270
keyType = collection.getKey().getType();
271
iter = collection.getKey().getColumnIterator();
272
int keySpan = collection.getKey().getColumnSpan();
273
keyColumnNames = new String[keySpan];
274
keyColumnAliases = new String[keySpan];
276
while ( iter.hasNext() ) {
277
// NativeSQL: collect key column and auto-aliases
278
Column col = ( (Column) iter.next() );
279
keyColumnNames[k] = col.getQuotedName(dialect);
280
keyColumnAliases[k] = col.getAlias(dialect);
284
//unquotedKeyColumnNames = StringHelper.unQuote(keyColumnAliases);
288
String elemNode = collection.getElementNodeName();
289
if ( elementType.isEntityType() ) {
290
String entityName = ( (EntityType) elementType ).getAssociatedEntityName();
291
elementPersister = factory.getEntityPersister(entityName);
292
if ( elemNode==null ) {
293
elemNode = cfg.getClassMapping(entityName).getNodeName();
295
// NativeSQL: collect element column and auto-aliases
299
elementPersister = null;
301
elementNodeName = elemNode;
303
int elementSpan = collection.getElement().getColumnSpan();
304
elementColumnAliases = new String[elementSpan];
305
elementColumnNames = new String[elementSpan];
306
elementFormulaTemplates = new String[elementSpan];
307
elementFormulas = new String[elementSpan];
308
elementColumnIsSettable = new boolean[elementSpan];
309
elementColumnIsInPrimaryKey = new boolean[elementSpan];
310
boolean isPureFormula = true;
311
boolean hasNotNullableColumns = false;
313
iter = collection.getElement().getColumnIterator();
314
while ( iter.hasNext() ) {
315
Selectable selectable = (Selectable) iter.next();
316
elementColumnAliases[j] = selectable.getAlias(dialect);
317
if ( selectable.isFormula() ) {
318
Formula form = (Formula) selectable;
319
elementFormulaTemplates[j] = form.getTemplate(dialect, factory.getSqlFunctionRegistry());
320
elementFormulas[j] = form.getFormula();
323
Column col = (Column) selectable;
324
elementColumnNames[j] = col.getQuotedName(dialect);
325
elementColumnIsSettable[j] = true;
326
elementColumnIsInPrimaryKey[j] = !col.isNullable();
327
if ( !col.isNullable() ) {
328
hasNotNullableColumns = true;
330
isPureFormula = false;
334
elementIsPureFormula = isPureFormula;
336
//workaround, for backward compatibility of sets with no
337
//not-null columns, assume all columns are used in the
339
if ( !hasNotNullableColumns ) {
340
Arrays.fill( elementColumnIsInPrimaryKey, true );
344
// INDEX AND ROW SELECT
346
hasIndex = collection.isIndexed();
348
// NativeSQL: collect index column and auto-aliases
349
IndexedCollection indexedCollection = (IndexedCollection) collection;
350
indexType = indexedCollection.getIndex().getType();
351
int indexSpan = indexedCollection.getIndex().getColumnSpan();
352
iter = indexedCollection.getIndex().getColumnIterator();
353
indexColumnNames = new String[indexSpan];
354
indexFormulaTemplates = new String[indexSpan];
355
indexFormulas = new String[indexSpan];
356
indexColumnIsSettable = new boolean[indexSpan];
357
indexColumnAliases = new String[indexSpan];
359
boolean hasFormula = false;
360
while ( iter.hasNext() ) {
361
Selectable s = (Selectable) iter.next();
362
indexColumnAliases[i] = s.getAlias(dialect);
363
if ( s.isFormula() ) {
364
Formula indexForm = (Formula) s;
365
indexFormulaTemplates[i] = indexForm.getTemplate(dialect, factory.getSqlFunctionRegistry());
366
indexFormulas[i] = indexForm.getFormula();
370
Column indexCol = (Column) s;
371
indexColumnNames[i] = indexCol.getQuotedName(dialect);
372
indexColumnIsSettable[i] = true;
376
indexContainsFormula = hasFormula;
377
baseIndex = indexedCollection.isList() ?
378
( (List) indexedCollection ).getBaseIndex() : 0;
380
indexNodeName = indexedCollection.getIndexNodeName();
384
indexContainsFormula = false;
385
indexColumnIsSettable = null;
386
indexFormulaTemplates = null;
387
indexFormulas = null;
389
indexColumnNames = null;
390
indexColumnAliases = null;
392
indexNodeName = null;
395
hasIdentifier = collection.isIdentified();
397
if ( collection.isOneToMany() ) {
398
throw new MappingException( "one-to-many collections with identifiers are not supported" );
400
IdentifierCollection idColl = (IdentifierCollection) collection;
401
identifierType = idColl.getIdentifier().getType();
402
iter = idColl.getIdentifier().getColumnIterator();
403
Column col = ( Column ) iter.next();
404
identifierColumnName = col.getQuotedName(dialect);
405
identifierColumnAlias = col.getAlias(dialect);
406
//unquotedIdentifierColumnName = identifierColumnAlias;
407
identifierGenerator = idColl.getIdentifier().createIdentifierGenerator(
408
factory.getDialect(),
409
factory.getSettings().getDefaultCatalogName(),
410
factory.getSettings().getDefaultSchemaName(),
415
identifierType = null;
416
identifierColumnName = null;
417
identifierColumnAlias = null;
418
//unquotedIdentifierColumnName = null;
419
identifierGenerator = null;
424
//sqlSelectString = sqlSelectString();
425
//sqlSelectRowString = sqlSelectRowString();
427
if ( collection.getCustomSQLInsert() == null ) {
428
sqlInsertRowString = generateInsertRowString();
429
insertCallable = false;
430
insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
433
sqlInsertRowString = collection.getCustomSQLInsert();
434
insertCallable = collection.isCustomInsertCallable();
435
insertCheckStyle = collection.getCustomSQLInsertCheckStyle() == null
436
? ExecuteUpdateResultCheckStyle.determineDefault( collection.getCustomSQLInsert(), insertCallable )
437
: collection.getCustomSQLInsertCheckStyle();
440
if ( collection.getCustomSQLUpdate() == null ) {
441
sqlUpdateRowString = generateUpdateRowString();
442
updateCallable = false;
443
updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
446
sqlUpdateRowString = collection.getCustomSQLUpdate();
447
updateCallable = collection.isCustomUpdateCallable();
448
updateCheckStyle = collection.getCustomSQLUpdateCheckStyle() == null
449
? ExecuteUpdateResultCheckStyle.determineDefault( collection.getCustomSQLUpdate(), insertCallable )
450
: collection.getCustomSQLUpdateCheckStyle();
453
if ( collection.getCustomSQLDelete() == null ) {
454
sqlDeleteRowString = generateDeleteRowString();
455
deleteCallable = false;
456
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
459
sqlDeleteRowString = collection.getCustomSQLDelete();
460
deleteCallable = collection.isCustomDeleteCallable();
461
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
464
if ( collection.getCustomSQLDeleteAll() == null ) {
465
sqlDeleteString = generateDeleteString();
466
deleteAllCallable = false;
467
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
470
sqlDeleteString = collection.getCustomSQLDeleteAll();
471
deleteAllCallable = collection.isCustomDeleteAllCallable();
472
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
475
sqlSelectSizeString = generateSelectSizeString( collection.isIndexed() && !collection.isMap() );
476
sqlDetectRowByIndexString = generateDetectRowByIndexString();
477
sqlDetectRowByElementString = generateDetectRowByElementString();
478
sqlSelectRowByIndexString = generateSelectRowByIndexString();
482
isLazy = collection.isLazy();
483
isExtraLazy = collection.isExtraLazy();
485
isInverse = collection.isInverse();
487
if ( collection.isArray() ) {
488
elementClass = ( (org.hibernate.mapping.Array) collection ).getElementClass();
491
// for non-arrays, we don't need to know the element class
492
elementClass = null; //elementType.returnedClass();
495
if ( elementType.isComponentType() ) {
496
elementPropertyMapping = new CompositeElementPropertyMapping(
498
elementFormulaTemplates,
499
(AbstractComponentType) elementType,
503
else if ( !elementType.isEntityType() ) {
504
elementPropertyMapping = new ElementPropertyMapping(
510
if ( elementPersister instanceof PropertyMapping ) { //not all classpersisters implement PropertyMapping!
511
elementPropertyMapping = (PropertyMapping) elementPersister;
514
elementPropertyMapping = new ElementPropertyMapping(
521
// Handle any filters applied to this collection
522
filterHelper = new FilterHelper( collection.getFilterMap(), dialect, factory.getSqlFunctionRegistry() );
524
// Handle any filters applied to this collection for many-to-many
525
manyToManyFilterHelper = new FilterHelper( collection.getManyToManyFilterMap(), dialect, factory.getSqlFunctionRegistry() );
526
manyToManyWhereString = StringHelper.isNotEmpty( collection.getManyToManyWhere() ) ?
527
"( " + collection.getManyToManyWhere() + " )" :
529
manyToManyWhereTemplate = manyToManyWhereString == null ?
531
Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() );
532
manyToManyOrderByString = collection.getManyToManyOrdering();
533
manyToManyOrderByTemplate = manyToManyOrderByString == null
535
: Template.renderOrderByStringTemplate( manyToManyOrderByString, factory.getDialect(), factory.getSqlFunctionRegistry() );
537
initCollectionPropertyMap();
540
public void postInstantiate() throws MappingException {
541
initializer = queryLoaderName == null ?
542
createCollectionInitializer( CollectionHelper.EMPTY_MAP ) :
543
new NamedQueryCollectionInitializer( queryLoaderName, this );
546
protected void logStaticSQL() {
547
if ( log.isDebugEnabled() ) {
548
log.debug( "Static SQL for collection: " + getRole() );
549
if ( getSQLInsertRowString() != null ) {
550
log.debug( " Row insert: " + getSQLInsertRowString() );
552
if ( getSQLUpdateRowString() != null ) {
553
log.debug( " Row update: " + getSQLUpdateRowString() );
555
if ( getSQLDeleteRowString() != null ) {
556
log.debug( " Row delete: " + getSQLDeleteRowString() );
558
if ( getSQLDeleteString() != null ) {
559
log.debug( " One-shot delete: " + getSQLDeleteString() );
564
public void initialize(Serializable key, SessionImplementor session) throws HibernateException {
565
getAppropriateInitializer( key, session ).initialize( key, session );
568
protected CollectionInitializer getAppropriateInitializer(Serializable key, SessionImplementor session) {
569
if ( queryLoaderName != null ) {
570
//if there is a user-specified loader, return that
574
CollectionInitializer subselectInitializer = getSubselectInitializer( key, session );
575
if ( subselectInitializer != null ) {
576
return subselectInitializer;
578
else if ( session.getEnabledFilters().isEmpty() ) {
582
return createCollectionInitializer( session.getEnabledFilters() );
586
private CollectionInitializer getSubselectInitializer(Serializable key, SessionImplementor session) {
588
if ( !isSubselectLoadable() ) {
592
final PersistenceContext persistenceContext = session.getPersistenceContext();
594
SubselectFetch subselect = persistenceContext.getBatchFetchQueue()
595
.getSubselect( new EntityKey( key, getOwnerEntityPersister(), session.getEntityMode() ) );
597
if (subselect == null) {
602
// Take care of any entities that might have
604
Iterator iter = subselect.getResult().iterator();
605
while ( iter.hasNext() ) {
606
if ( !persistenceContext.containsEntity( (EntityKey) iter.next() ) ) {
611
// Run a subquery loader
612
return createSubselectInitializer( subselect, session );
616
protected abstract CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SessionImplementor session);
618
protected abstract CollectionInitializer createCollectionInitializer(Map enabledFilters)
619
throws MappingException;
621
public CacheConcurrencyStrategy getCache() {
625
public boolean hasCache() {
626
return cache != null;
629
public CollectionType getCollectionType() {
630
return collectionType;
633
protected String getSQLWhereString(String alias) {
634
return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
637
public String getSQLOrderByString(String alias) {
638
return hasOrdering() ?
639
StringHelper.replace( sqlOrderByStringTemplate, Template.TEMPLATE, alias ) : "";
642
public String getManyToManyOrderByString(String alias) {
643
if ( isManyToMany() && manyToManyOrderByString != null ) {
644
return StringHelper.replace( manyToManyOrderByTemplate, Template.TEMPLATE, alias );
650
public FetchMode getFetchMode() {
654
public boolean hasOrdering() {
658
public boolean hasManyToManyOrdering() {
659
return isManyToMany() && manyToManyOrderByTemplate != null;
662
public boolean hasWhere() {
666
protected String getSQLDeleteString() {
667
return sqlDeleteString;
670
protected String getSQLInsertRowString() {
671
return sqlInsertRowString;
674
protected String getSQLUpdateRowString() {
675
return sqlUpdateRowString;
678
protected String getSQLDeleteRowString() {
679
return sqlDeleteRowString;
682
public Type getKeyType() {
686
public Type getIndexType() {
690
public Type getElementType() {
695
* Return the element class of an array, or null otherwise
697
public Class getElementClass() { //needed by arrays
701
public Object readElement(ResultSet rs, Object owner, String[] aliases, SessionImplementor session)
702
throws HibernateException, SQLException {
703
return getElementType().nullSafeGet( rs, aliases, session, owner );
706
public Object readIndex(ResultSet rs, String[] aliases, SessionImplementor session)
707
throws HibernateException, SQLException {
708
Object index = getIndexType().nullSafeGet( rs, aliases, session, null );
709
if ( index == null ) {
710
throw new HibernateException( "null index column for collection: " + role );
712
index = decrementIndexByBase( index );
716
protected Object decrementIndexByBase(Object index) {
718
index = new Integer( ( (Integer) index ).intValue() - baseIndex );
723
public Object readIdentifier(ResultSet rs, String alias, SessionImplementor session)
724
throws HibernateException, SQLException {
725
Object id = getIdentifierType().nullSafeGet( rs, alias, session, null );
727
throw new HibernateException( "null identifier column for collection: " + role );
732
public Object readKey(ResultSet rs, String[] aliases, SessionImplementor session)
733
throws HibernateException, SQLException {
734
return getKeyType().nullSafeGet( rs, aliases, session, null );
738
* Write the key to a JDBC <tt>PreparedStatement</tt>
740
protected int writeKey(PreparedStatement st, Serializable key, int i, SessionImplementor session)
741
throws HibernateException, SQLException {
744
throw new NullPointerException( "null key for collection: " + role ); //an assertion
746
getKeyType().nullSafeSet( st, key, i, session );
747
return i + keyColumnAliases.length;
751
* Write the element to a JDBC <tt>PreparedStatement</tt>
753
protected int writeElement(PreparedStatement st, Object elt, int i, SessionImplementor session)
754
throws HibernateException, SQLException {
755
getElementType().nullSafeSet(st, elt, i, elementColumnIsSettable, session);
756
return i + ArrayHelper.countTrue(elementColumnIsSettable);
761
* Write the index to a JDBC <tt>PreparedStatement</tt>
763
protected int writeIndex(PreparedStatement st, Object index, int i, SessionImplementor session)
764
throws HibernateException, SQLException {
765
getIndexType().nullSafeSet( st, incrementIndexByBase(index), i, indexColumnIsSettable, session );
766
return i + ArrayHelper.countTrue(indexColumnIsSettable);
769
protected Object incrementIndexByBase(Object index) {
771
index = new Integer( ( (Integer) index ).intValue() + baseIndex );
777
* Write the element to a JDBC <tt>PreparedStatement</tt>
779
protected int writeElementToWhere(PreparedStatement st, Object elt, int i, SessionImplementor session)
780
throws HibernateException, SQLException {
781
if (elementIsPureFormula) {
782
throw new AssertionFailure("cannot use a formula-based element in the where condition");
784
getElementType().nullSafeSet(st, elt, i, elementColumnIsInPrimaryKey, session);
785
return i + elementColumnAliases.length;
790
* Write the index to a JDBC <tt>PreparedStatement</tt>
792
protected int writeIndexToWhere(PreparedStatement st, Object index, int i, SessionImplementor session)
793
throws HibernateException, SQLException {
794
if (indexContainsFormula) {
795
throw new AssertionFailure("cannot use a formula-based index in the where condition");
797
getIndexType().nullSafeSet( st, incrementIndexByBase(index), i, session );
798
return i + indexColumnAliases.length;
802
* Write the identifier to a JDBC <tt>PreparedStatement</tt>
804
public int writeIdentifier(PreparedStatement st, Object id, int i, SessionImplementor session)
805
throws HibernateException, SQLException {
807
getIdentifierType().nullSafeSet( st, id, i, session );
811
public boolean isPrimitiveArray() {
812
return isPrimitiveArray;
815
public boolean isArray() {
819
public String[] getKeyColumnAliases(String suffix) {
820
return new Alias( suffix ).toAliasStrings( keyColumnAliases );
823
public String[] getElementColumnAliases(String suffix) {
824
return new Alias( suffix ).toAliasStrings( elementColumnAliases );
827
public String[] getIndexColumnAliases(String suffix) {
829
return new Alias( suffix ).toAliasStrings( indexColumnAliases );
836
public String getIdentifierColumnAlias(String suffix) {
837
if ( hasIdentifier ) {
838
return new Alias( suffix ).toAliasString( identifierColumnAlias );
845
public String getIdentifierColumnName() {
846
if ( hasIdentifier ) {
847
return identifierColumnName;
854
* Generate a list of collection index, key and element columns
856
public String selectFragment(String alias, String columnSuffix) {
857
SelectFragment frag = generateSelectFragment( alias, columnSuffix );
858
appendElementColumns( frag, alias );
859
appendIndexColumns( frag, alias );
860
appendIdentifierColumns( frag, alias );
862
return frag.toFragmentString()
863
.substring( 2 ); //strip leading ','
866
protected String generateSelectSizeString(boolean isIntegerIndexed) {
867
String selectValue = isIntegerIndexed ?
868
"max(" + getIndexColumnNames()[0] + ") + 1": //lists, arrays
869
"count(" + getElementColumnNames()[0] + ")"; //sets, maps, bags
870
return new SimpleSelect(dialect)
871
.setTableName( getTableName() )
872
.addCondition( getKeyColumnNames(), "=?" )
873
.addColumn(selectValue)
874
.toStatementString();
877
protected String generateDetectRowByIndexString() {
881
return new SimpleSelect(dialect)
882
.setTableName( getTableName() )
883
.addCondition( getKeyColumnNames(), "=?" )
884
.addCondition( getIndexColumnNames(), "=?" )
885
.addCondition( indexFormulas, "=?" )
887
.toStatementString();
890
protected String generateSelectRowByIndexString() {
894
return new SimpleSelect(dialect)
895
.setTableName( getTableName() )
896
.addCondition( getKeyColumnNames(), "=?" )
897
.addCondition( getIndexColumnNames(), "=?" )
898
.addCondition( indexFormulas, "=?" )
899
.addColumns( getElementColumnNames(), elementColumnAliases )
900
.addColumns( indexFormulas, indexColumnAliases )
901
.toStatementString();
904
protected String generateDetectRowByElementString() {
905
return new SimpleSelect(dialect)
906
.setTableName( getTableName() )
907
.addCondition( getKeyColumnNames(), "=?" )
908
.addCondition( getElementColumnNames(), "=?" )
909
.addCondition( elementFormulas, "=?" )
911
.toStatementString();
914
protected SelectFragment generateSelectFragment(String alias, String columnSuffix) {
915
return new SelectFragment()
916
.setSuffix( columnSuffix )
917
.addColumns( alias, keyColumnNames, keyColumnAliases );
920
protected void appendElementColumns(SelectFragment frag, String elemAlias) {
921
for ( int i=0; i<elementColumnIsSettable.length; i++ ) {
922
if ( elementColumnIsSettable[i] ) {
923
frag.addColumn( elemAlias, elementColumnNames[i], elementColumnAliases[i] );
926
frag.addFormula( elemAlias, elementFormulaTemplates[i], elementColumnAliases[i] );
931
protected void appendIndexColumns(SelectFragment frag, String alias) {
933
for ( int i=0; i<indexColumnIsSettable.length; i++ ) {
934
if ( indexColumnIsSettable[i] ) {
935
frag.addColumn( alias, indexColumnNames[i], indexColumnAliases[i] );
938
frag.addFormula( alias, indexFormulaTemplates[i], indexColumnAliases[i] );
944
protected void appendIdentifierColumns(SelectFragment frag, String alias) {
945
if ( hasIdentifier ) {
946
frag.addColumn( alias, identifierColumnName, identifierColumnAlias );
950
public String[] getIndexColumnNames() {
951
return indexColumnNames;
954
public String[] getIndexFormulas() {
955
return indexFormulas;
958
public String[] getIndexColumnNames(String alias) {
959
return qualify(alias, indexColumnNames, indexFormulaTemplates);
963
public String[] getElementColumnNames(String alias) {
964
return qualify(alias, elementColumnNames, elementFormulaTemplates);
967
private static String[] qualify(String alias, String[] columnNames, String[] formulaTemplates) {
968
int span = columnNames.length;
969
String[] result = new String[span];
970
for (int i=0; i<span; i++) {
971
if ( columnNames[i]==null ) {
972
result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, alias );
975
result[i] = StringHelper.qualify( alias, columnNames[i] );
981
public String[] getElementColumnNames() {
982
return elementColumnNames; //TODO: something with formulas...
985
public String[] getKeyColumnNames() {
986
return keyColumnNames;
989
public boolean hasIndex() {
993
public boolean isLazy() {
997
public boolean isInverse() {
1001
public String getTableName() {
1002
return qualifiedTableName;
1005
public void remove(Serializable id, SessionImplementor session) throws HibernateException {
1007
if ( !isInverse && isRowDeleteEnabled() ) {
1009
if ( log.isDebugEnabled() ) {
1011
"Deleting collection: " +
1012
MessageHelper.collectionInfoString( this, id, getFactory() )
1016
// Remove all the old entries
1020
PreparedStatement st = null;
1021
Expectation expectation = Expectations.appropriateExpectation( getDeleteAllCheckStyle() );
1022
boolean callable = isDeleteAllCallable();
1023
boolean useBatch = expectation.canBeBatched();
1024
String sql = getSQLDeleteString();
1027
st = session.getBatcher().prepareBatchCallableStatement( sql );
1030
st = session.getBatcher().prepareBatchStatement( sql );
1035
st = session.getBatcher().prepareCallableStatement( sql );
1038
st = session.getBatcher().prepareStatement( sql );
1044
offset+= expectation.prepare( st );
1046
writeKey( st, id, offset, session );
1048
session.getBatcher().addToBatch( expectation );
1051
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
1054
catch ( SQLException sqle ) {
1056
session.getBatcher().abortBatch( sqle );
1062
session.getBatcher().closeStatement( st );
1066
if ( log.isDebugEnabled() ) {
1067
log.debug( "done deleting collection" );
1070
catch ( SQLException sqle ) {
1071
throw JDBCExceptionHelper.convert(
1072
sqlExceptionConverter,
1074
"could not delete collection: " +
1075
MessageHelper.collectionInfoString( this, id, getFactory() ),
1076
getSQLDeleteString()
1084
public void recreate(PersistentCollection collection, Serializable id, SessionImplementor session)
1085
throws HibernateException {
1087
if ( !isInverse && isRowInsertEnabled() ) {
1089
if ( log.isDebugEnabled() ) {
1091
"Inserting collection: " +
1092
MessageHelper.collectionInfoString( this, id, getFactory() )
1097
//create all the new entries
1098
Iterator entries = collection.entries(this);
1099
if ( entries.hasNext() ) {
1100
collection.preInsert( this );
1103
while ( entries.hasNext() ) {
1105
final Object entry = entries.next();
1106
if ( collection.entryExists( entry, i ) ) {
1108
PreparedStatement st = null;
1109
Expectation expectation = Expectations.appropriateExpectation( getInsertCheckStyle() );
1110
boolean callable = isInsertCallable();
1111
boolean useBatch = expectation.canBeBatched();
1112
String sql = getSQLInsertRowString();
1116
st = session.getBatcher().prepareBatchCallableStatement( sql );
1119
st = session.getBatcher().prepareBatchStatement( sql );
1124
st = session.getBatcher().prepareCallableStatement( sql );
1127
st = session.getBatcher().prepareStatement( sql );
1133
offset+= expectation.prepare( st );
1135
//TODO: copy/paste from insertRows()
1136
int loc = writeKey( st, id, offset, session );
1137
if ( hasIdentifier ) {
1138
loc = writeIdentifier( st, collection.getIdentifier(entry, i), loc, session );
1140
if ( hasIndex /*&& !indexIsFormula*/ ) {
1141
loc = writeIndex( st, collection.getIndex(entry, i, this), loc, session );
1143
loc = writeElement(st, collection.getElement(entry), loc, session );
1146
session.getBatcher().addToBatch( expectation );
1149
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
1152
collection.afterRowInsert( this, entry, i );
1155
catch ( SQLException sqle ) {
1157
session.getBatcher().abortBatch( sqle );
1163
session.getBatcher().closeStatement( st );
1171
if ( log.isDebugEnabled() ) {
1172
log.debug( "done inserting collection: " + count + " rows inserted" );
1177
if ( log.isDebugEnabled() ) {
1178
log.debug( "collection was empty" );
1182
catch ( SQLException sqle ) {
1183
throw JDBCExceptionHelper.convert(
1184
sqlExceptionConverter,
1186
"could not insert collection: " +
1187
MessageHelper.collectionInfoString( this, id, getFactory() ),
1188
getSQLInsertRowString()
1194
protected boolean isRowDeleteEnabled() {
1198
public void deleteRows(PersistentCollection collection, Serializable id, SessionImplementor session)
1199
throws HibernateException {
1201
if ( !isInverse && isRowDeleteEnabled() ) {
1203
if ( log.isDebugEnabled() ) {
1205
"Deleting rows of collection: " +
1206
MessageHelper.collectionInfoString( this, id, getFactory() )
1210
boolean deleteByIndex = !isOneToMany() && hasIndex && !indexContainsFormula;
1213
//delete all the deleted entries
1214
Iterator deletes = collection.getDeletes( this, !deleteByIndex );
1215
if ( deletes.hasNext() ) {
1218
while ( deletes.hasNext() ) {
1219
PreparedStatement st = null;
1220
Expectation expectation = Expectations.appropriateExpectation( getDeleteCheckStyle() );
1221
boolean callable = isDeleteCallable();
1222
boolean useBatch = expectation.canBeBatched();
1223
String sql = getSQLDeleteRowString();
1227
st = session.getBatcher().prepareBatchCallableStatement( sql );
1230
st = session.getBatcher().prepareBatchStatement( sql );
1235
st = session.getBatcher().prepareCallableStatement( sql );
1238
st = session.getBatcher().prepareStatement( sql );
1243
expectation.prepare( st );
1245
Object entry = deletes.next();
1247
if ( hasIdentifier ) {
1248
writeIdentifier( st, entry, loc, session );
1251
loc = writeKey( st, id, loc, session );
1252
if ( deleteByIndex ) {
1253
writeIndexToWhere( st, entry, loc, session );
1256
writeElementToWhere( st, entry, loc, session );
1261
session.getBatcher().addToBatch( expectation );
1264
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
1268
catch ( SQLException sqle ) {
1270
session.getBatcher().abortBatch( sqle );
1276
session.getBatcher().closeStatement( st );
1280
if ( log.isDebugEnabled() ) {
1281
log.debug( "done deleting collection rows: " + count + " deleted" );
1286
if ( log.isDebugEnabled() ) {
1287
log.debug( "no rows to delete" );
1291
catch ( SQLException sqle ) {
1292
throw JDBCExceptionHelper.convert(
1293
sqlExceptionConverter,
1295
"could not delete collection rows: " +
1296
MessageHelper.collectionInfoString( this, id, getFactory() ),
1297
getSQLDeleteRowString()
1303
protected boolean isRowInsertEnabled() {
1307
public void insertRows(PersistentCollection collection, Serializable id, SessionImplementor session)
1308
throws HibernateException {
1310
if ( !isInverse && isRowInsertEnabled() ) {
1312
if ( log.isDebugEnabled() ) {
1314
"Inserting rows of collection: " +
1315
MessageHelper.collectionInfoString( this, id, getFactory() )
1320
//insert all the new entries
1321
collection.preInsert( this );
1322
Iterator entries = collection.entries( this );
1323
Expectation expectation = Expectations.appropriateExpectation( getInsertCheckStyle() );
1324
boolean callable = isInsertCallable();
1325
boolean useBatch = expectation.canBeBatched();
1326
String sql = getSQLInsertRowString();
1329
while ( entries.hasNext() ) {
1331
Object entry = entries.next();
1332
PreparedStatement st = null;
1333
if ( collection.needsInserting( entry, i, elementType ) ) {
1338
st = session.getBatcher().prepareBatchCallableStatement( sql );
1341
st = session.getBatcher().prepareBatchStatement( sql );
1347
st = session.getBatcher().prepareCallableStatement( sql );
1350
st = session.getBatcher().prepareStatement( sql );
1355
offset += expectation.prepare( st );
1356
//TODO: copy/paste from recreate()
1357
offset = writeKey( st, id, offset, session );
1358
if ( hasIdentifier ) {
1359
offset = writeIdentifier( st, collection.getIdentifier(entry, i), offset, session );
1361
if ( hasIndex /*&& !indexIsFormula*/ ) {
1362
offset = writeIndex( st, collection.getIndex(entry, i, this), offset, session );
1364
writeElement(st, collection.getElement(entry), offset, session );
1367
session.getBatcher().addToBatch( expectation );
1370
expectation.verifyOutcome( st.executeUpdate(), st, -1 );
1372
collection.afterRowInsert( this, entry, i );
1375
catch ( SQLException sqle ) {
1377
session.getBatcher().abortBatch( sqle );
1383
session.getBatcher().closeStatement( st );
1389
if ( log.isDebugEnabled() ) {
1390
log.debug( "done inserting rows: " + count + " inserted" );
1393
catch ( SQLException sqle ) {
1394
throw JDBCExceptionHelper.convert(
1395
sqlExceptionConverter,
1397
"could not insert collection rows: " +
1398
MessageHelper.collectionInfoString( this, id, getFactory() ),
1399
getSQLInsertRowString()
1407
public String getRole() {
1411
public String getOwnerEntityName() {
1415
public EntityPersister getOwnerEntityPersister() {
1416
return ownerPersister;
1419
public IdentifierGenerator getIdentifierGenerator() {
1420
return identifierGenerator;
1423
public Type getIdentifierType() {
1424
return identifierType;
1427
public boolean hasOrphanDelete() {
1428
return hasOrphanDelete;
1431
public Type toType(String propertyName) throws QueryException {
1432
if ( "index".equals( propertyName ) ) {
1435
return elementPropertyMapping.toType( propertyName );
1438
public abstract boolean isManyToMany();
1440
public String getManyToManyFilterFragment(String alias, Map enabledFilters) {
1441
StringBuffer buffer = new StringBuffer();
1442
manyToManyFilterHelper.render( buffer, alias, enabledFilters );
1444
if ( manyToManyWhereString != null ) {
1445
buffer.append( " and " )
1446
.append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, alias ) );
1449
return buffer.toString();
1452
public String[] toColumns(String alias, String propertyName)
1453
throws QueryException {
1455
if ( "index".equals( propertyName ) ) {
1456
if ( isManyToMany() ) {
1457
throw new QueryException( "index() function not supported for many-to-many association" );
1459
return StringHelper.qualify( alias, indexColumnNames );
1462
return elementPropertyMapping.toColumns( alias, propertyName );
1465
public String[] toColumns(String propertyName)
1466
throws QueryException {
1468
if ( "index".equals( propertyName ) ) {
1469
if ( isManyToMany() ) {
1470
throw new QueryException( "index() function not supported for many-to-many association" );
1472
return indexColumnNames;
1475
return elementPropertyMapping.toColumns( propertyName );
1478
public Type getType() {
1479
return elementPropertyMapping.getType(); //==elementType ??
1482
public String getName() {
1486
public EntityPersister getElementPersister() {
1487
if ( elementPersister == null ) {
1488
throw new AssertionFailure( "not an association" );
1490
return ( Loadable ) elementPersister;
1493
public boolean isCollection() {
1497
public Serializable[] getCollectionSpaces() {
1501
protected abstract String generateDeleteString();
1503
protected abstract String generateDeleteRowString();
1505
protected abstract String generateUpdateRowString();
1507
protected abstract String generateInsertRowString();
1509
public void updateRows(PersistentCollection collection, Serializable id, SessionImplementor session)
1510
throws HibernateException {
1512
if ( !isInverse && collection.isRowUpdatePossible() ) {
1514
if ( log.isDebugEnabled() ) {
1515
log.debug( "Updating rows of collection: " + role + "#" + id );
1518
//update all the modified entries
1519
int count = doUpdateRows( id, collection, session );
1521
if ( log.isDebugEnabled() ) {
1522
log.debug( "done updating rows: " + count + " updated" );
1527
protected abstract int doUpdateRows(Serializable key, PersistentCollection collection, SessionImplementor session)
1528
throws HibernateException;
1530
public CollectionMetadata getCollectionMetadata() {
1534
public SessionFactoryImplementor getFactory() {
1538
protected String filterFragment(String alias) throws MappingException {
1539
return hasWhere() ? " and " + getSQLWhereString( alias ) : "";
1542
public String filterFragment(String alias, Map enabledFilters) throws MappingException {
1544
StringBuffer sessionFilterFragment = new StringBuffer();
1545
filterHelper.render( sessionFilterFragment, alias, enabledFilters );
1547
return sessionFilterFragment.append( filterFragment( alias ) ).toString();
1550
public String oneToManyFilterFragment(String alias) throws MappingException {
1554
protected boolean isInsertCallable() {
1555
return insertCallable;
1558
protected ExecuteUpdateResultCheckStyle getInsertCheckStyle() {
1559
return insertCheckStyle;
1562
protected boolean isUpdateCallable() {
1563
return updateCallable;
1566
protected ExecuteUpdateResultCheckStyle getUpdateCheckStyle() {
1567
return updateCheckStyle;
1570
protected boolean isDeleteCallable() {
1571
return deleteCallable;
1574
protected ExecuteUpdateResultCheckStyle getDeleteCheckStyle() {
1575
return deleteCheckStyle;
1578
protected boolean isDeleteAllCallable() {
1579
return deleteAllCallable;
1582
protected ExecuteUpdateResultCheckStyle getDeleteAllCheckStyle() {
1583
return deleteAllCheckStyle;
1586
public String toString() {
1587
return StringHelper.unqualify( getClass().getName() ) + '(' + role + ')';
1590
public boolean isVersioned() {
1591
return isVersioned && getOwnerEntityPersister().isVersioned();
1594
public String getNodeName() {
1598
public String getElementNodeName() {
1599
return elementNodeName;
1602
public String getIndexNodeName() {
1603
return indexNodeName;
1606
protected SQLExceptionConverter getSQLExceptionConverter() {
1607
return sqlExceptionConverter;
1610
public CacheEntryStructure getCacheEntryStructure() {
1611
return cacheEntryStructure;
1614
public boolean isAffectedByEnabledFilters(SessionImplementor session) {
1615
return filterHelper.isAffectedBy( session.getEnabledFilters() ) ||
1616
( isManyToMany() && manyToManyFilterHelper.isAffectedBy( session.getEnabledFilters() ) );
1619
public boolean isSubselectLoadable() {
1620
return subselectLoadable;
1623
public boolean isMutable() {
1627
public String[] getCollectionPropertyColumnAliases(String propertyName, String suffix) {
1628
String rawAliases[] = (String[]) collectionPropertyColumnAliases.get(propertyName);
1630
if ( rawAliases == null ) {
1634
String result[] = new String[rawAliases.length];
1635
for ( int i=0; i<rawAliases.length; i++ ) {
1636
result[i] = new Alias(suffix).toUnquotedAliasString( rawAliases[i] );
1642
public void initCollectionPropertyMap() {
1644
initCollectionPropertyMap( "key", keyType, keyColumnAliases, keyColumnNames );
1645
initCollectionPropertyMap( "element", elementType, elementColumnAliases, elementColumnNames );
1647
initCollectionPropertyMap( "index", indexType, indexColumnAliases, indexColumnNames );
1649
if (hasIdentifier) {
1650
initCollectionPropertyMap(
1653
new String[] { identifierColumnAlias },
1654
new String[] { identifierColumnName }
1659
private void initCollectionPropertyMap(String aliasName, Type type, String[] columnAliases, String[] columnNames) {
1661
collectionPropertyColumnAliases.put(aliasName, columnAliases);
1662
collectionPropertyColumnNames.put(aliasName, columnNames);
1664
if( type.isComponentType() ) {
1665
AbstractComponentType ct = (AbstractComponentType) type;
1666
String[] propertyNames = ct.getPropertyNames();
1667
for (int i = 0; i < propertyNames.length; i++) {
1668
String name = propertyNames[i];
1669
collectionPropertyColumnAliases.put( aliasName + "." + name, columnAliases[i] );
1670
collectionPropertyColumnNames.put( aliasName + "." + name, columnNames[i] );
1676
public int getSize(Serializable key, SessionImplementor session) {
1678
PreparedStatement st = session.getBatcher().prepareSelectStatement(sqlSelectSizeString);
1680
getKeyType().nullSafeSet(st, key, 1, session);
1681
ResultSet rs = st.executeQuery();
1683
return rs.next() ? rs.getInt(1) - baseIndex : 0;
1690
session.getBatcher().closeStatement( st );
1693
catch (SQLException sqle) {
1694
throw JDBCExceptionHelper.convert(
1695
getFactory().getSQLExceptionConverter(),
1697
"could not retrieve collection size: " +
1698
MessageHelper.collectionInfoString( this, key, getFactory() ),
1704
public boolean indexExists(Serializable key, Object index, SessionImplementor session) {
1705
return exists(key, incrementIndexByBase(index), getIndexType(), sqlDetectRowByIndexString, session);
1708
public boolean elementExists(Serializable key, Object element, SessionImplementor session) {
1709
return exists(key, element, getElementType(), sqlDetectRowByElementString, session);
1712
private boolean exists(Serializable key, Object indexOrElement, Type indexOrElementType, String sql, SessionImplementor session) {
1714
PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
1716
getKeyType().nullSafeSet(st, key, 1, session);
1717
indexOrElementType.nullSafeSet( st, indexOrElement, keyColumnNames.length + 1, session );
1718
ResultSet rs = st.executeQuery();
1726
catch( TransientObjectException e ) {
1730
session.getBatcher().closeStatement( st );
1733
catch (SQLException sqle) {
1734
throw JDBCExceptionHelper.convert(
1735
getFactory().getSQLExceptionConverter(),
1737
"could not check row existence: " +
1738
MessageHelper.collectionInfoString( this, key, getFactory() ),
1744
public Object getElementByIndex(Serializable key, Object index, SessionImplementor session, Object owner) {
1746
PreparedStatement st = session.getBatcher().prepareSelectStatement(sqlSelectRowByIndexString);
1748
getKeyType().nullSafeSet(st, key, 1, session);
1749
getIndexType().nullSafeSet( st, incrementIndexByBase(index), keyColumnNames.length + 1, session );
1750
ResultSet rs = st.executeQuery();
1753
return getElementType().nullSafeGet(rs, elementColumnAliases, session, owner);
1764
session.getBatcher().closeStatement( st );
1767
catch (SQLException sqle) {
1768
throw JDBCExceptionHelper.convert(
1769
getFactory().getSQLExceptionConverter(),
1771
"could not read row: " +
1772
MessageHelper.collectionInfoString( this, key, getFactory() ),
1778
public boolean isExtraLazy() {
1782
protected Dialect getDialect() {