15
15
import org .hibernate .engine .spi .SessionFactoryImplementor ;
16
16
import org .hibernate .engine .spi .SessionImplementor ;
17
17
import org .hibernate .event .spi .EventSource ;
18
+ import org .hibernate .internal .CoreLogging ;
18
19
import org .hibernate .internal .CoreMessageLogger ;
19
20
import org .hibernate .persister .collection .CollectionPersister ;
20
- import org .hibernate .pretty .MessageHelper ;
21
21
import org .hibernate .type .CollectionType ;
22
22
23
- import org .jboss .logging .Logger ;
24
-
25
- import java .lang .invoke .MethodHandles ;
23
+ import static org .hibernate .pretty .MessageHelper .collectionInfoString ;
26
24
27
25
/**
28
26
* Implements book-keeping for the collection persistence by reachability algorithm
29
27
*
30
28
* @author Gavin King
31
29
*/
32
30
public final class Collections {
33
- private static final CoreMessageLogger LOG = Logger .getMessageLogger (
34
- MethodHandles .lookup (),
35
- CoreMessageLogger .class ,
36
- Collections .class .getName ()
37
- );
31
+ private static final CoreMessageLogger LOG = CoreLogging .messageLogger ( Collections .class );
38
32
39
33
/**
40
34
* record the fact that this collection was dereferenced
@@ -57,46 +51,25 @@ private static void processDereferencedCollection(PersistentCollection<?> coll,
57
51
final CollectionPersister loadedPersister = entry .getLoadedPersister ();
58
52
59
53
if ( loadedPersister != null && LOG .isDebugEnabled () ) {
60
- LOG .debugf (
61
- "Collection dereferenced: %s" ,
62
- MessageHelper .collectionInfoString ( loadedPersister ,
63
- coll , entry .getLoadedKey (), session
64
- )
65
- );
54
+ LOG .debug ("Collection dereferenced: "
55
+ + collectionInfoString ( loadedPersister , coll , entry .getLoadedKey (), session ) );
66
56
}
67
57
68
58
// do a check
69
59
final boolean hasOrphanDelete = loadedPersister != null && loadedPersister .hasOrphanDelete ();
70
60
if ( hasOrphanDelete ) {
71
- Object ownerId = loadedPersister .getOwnerEntityPersister ().getIdentifier ( coll .getOwner (), session );
72
- if ( ownerId == null ) {
73
- // the owning entity may have been deleted and its identifier unset due to
74
- // identifier-rollback; in which case, try to look up its identifier from
75
- // the persistence context
76
- if ( session .getFactory ().getSessionFactoryOptions ().isIdentifierRollbackEnabled () ) {
77
- final EntityEntry ownerEntry = persistenceContext .getEntry ( coll .getOwner () );
78
- if ( ownerEntry != null ) {
79
- ownerId = ownerEntry .getId ();
80
- }
81
- }
82
- if ( ownerId == null ) {
83
- throw new AssertionFailure ( "Unable to determine collection owner identifier for orphan-delete processing" );
84
- }
85
- }
61
+ final Object ownerId = getOwnerId ( coll , session , loadedPersister );
86
62
final EntityKey key = session .generateEntityKey ( ownerId , loadedPersister .getOwnerEntityPersister () );
87
63
final Object owner = persistenceContext .getEntity ( key );
88
64
if ( owner == null ) {
89
- throw new AssertionFailure (
90
- "collection owner not associated with session: " +
91
- loadedPersister .getRole ()
92
- );
65
+ throw new AssertionFailure ( "collection owner not associated with session: " + loadedPersister .getRole () );
93
66
}
94
67
final EntityEntry e = persistenceContext .getEntry ( owner );
95
68
//only collections belonging to deleted entities are allowed to be dereferenced in the case of orphan delete
96
69
if ( e != null && !e .getStatus ().isDeletedOrGone () ) {
97
70
throw new HibernateException (
98
- "A collection with orphan deletion was no longer referenced by the owning entity instance: " +
99
- loadedPersister .getRole ()
71
+ "A collection with orphan deletion was no longer referenced by the owning entity instance: "
72
+ + loadedPersister .getRole ()
100
73
);
101
74
}
102
75
}
@@ -108,21 +81,43 @@ private static void processDereferencedCollection(PersistentCollection<?> coll,
108
81
109
82
}
110
83
84
+ private static Object getOwnerId (
85
+ PersistentCollection <?> coll ,
86
+ SessionImplementor session ,
87
+ CollectionPersister loadedPersister ) {
88
+
89
+ Object ownerId =
90
+ loadedPersister .getOwnerEntityPersister ()
91
+ .getIdentifier ( coll .getOwner (), session );
92
+ if ( ownerId == null ) {
93
+ // the owning entity may have been deleted and its identifier unset due to
94
+ // identifier-rollback; in which case, try to look up its identifier from
95
+ // the persistence context
96
+ if ( session .getFactory ().getSessionFactoryOptions ()
97
+ .isIdentifierRollbackEnabled () ) {
98
+ final EntityEntry ownerEntry =
99
+ session .getPersistenceContextInternal ()
100
+ .getEntry ( coll .getOwner () );
101
+ if ( ownerEntry != null ) {
102
+ ownerId = ownerEntry .getId ();
103
+ }
104
+ }
105
+ if ( ownerId == null ) {
106
+ throw new AssertionFailure ( "Unable to determine collection owner identifier for orphan delete processing" );
107
+ }
108
+ }
109
+ return ownerId ;
110
+ }
111
+
111
112
private static void processNeverReferencedCollection (PersistentCollection <?> coll , SessionImplementor session )
112
113
throws HibernateException {
113
- final PersistenceContext persistenceContext = session .getPersistenceContextInternal ();
114
- final CollectionEntry entry = persistenceContext .getCollectionEntry ( coll );
114
+ final CollectionEntry entry =
115
+ session .getPersistenceContextInternal ()
116
+ .getCollectionEntry ( coll );
115
117
116
118
if ( LOG .isDebugEnabled () ) {
117
- LOG .debugf (
118
- "Found collection with unloaded owner: %s" ,
119
- MessageHelper .collectionInfoString (
120
- entry .getLoadedPersister (),
121
- coll ,
122
- entry .getLoadedKey (),
123
- session
124
- )
125
- );
119
+ LOG .debug ( "Found collection with unloaded owner: " +
120
+ collectionInfoString ( entry .getLoadedPersister (), coll , entry .getLoadedKey (), session ) );
126
121
}
127
122
128
123
entry .setCurrentPersister ( entry .getLoadedPersister () );
@@ -146,34 +141,34 @@ public static void processReachableCollection(
146
141
Object entity ,
147
142
SessionImplementor session ) {
148
143
collection .setOwner ( entity );
149
- final CollectionEntry ce = session .getPersistenceContextInternal ().getCollectionEntry ( collection );
144
+ final CollectionEntry ce =
145
+ session .getPersistenceContextInternal ()
146
+ .getCollectionEntry ( collection );
150
147
151
148
if ( ce == null ) {
152
149
// refer to comment in StatefulPersistenceContext.addCollection()
153
- throw new HibernateException (
154
- "Found two representations of same collection: " +
155
- type .getRole ()
156
- );
150
+ throw new HibernateException ( "Found two representations of same collection: " + type .getRole () );
157
151
}
158
152
159
153
final SessionFactoryImplementor factory = session .getFactory ();
160
- final CollectionPersister persister = factory . getRuntimeMetamodels ()
161
- .getMappingMetamodel ()
162
- .getCollectionDescriptor ( type .getRole () );
154
+ final CollectionPersister persister =
155
+ factory .getMappingMetamodel ()
156
+ .getCollectionDescriptor ( type .getRole () );
163
157
164
158
ce .setCurrentPersister ( persister );
165
159
//TODO: better to pass the id in as an argument?
166
160
ce .setCurrentKey ( type .getKeyOfOwner ( entity , session ) );
167
161
168
- final boolean isBytecodeEnhanced = persister .getOwnerEntityPersister ().getBytecodeEnhancementMetadata ().isEnhancedForLazyLoading ();
162
+ final boolean isBytecodeEnhanced =
163
+ persister .getOwnerEntityPersister ()
164
+ .getBytecodeEnhancementMetadata ()
165
+ .isEnhancedForLazyLoading ();
169
166
if ( isBytecodeEnhanced && !collection .wasInitialized () ) {
170
167
// the class of the collection owner is enhanced for lazy loading and we found an un-initialized PersistentCollection
171
168
// - skip it
172
169
if ( LOG .isDebugEnabled () ) {
173
- LOG .debugf (
174
- "Skipping uninitialized bytecode-lazy collection: %s" ,
175
- MessageHelper .collectionInfoString (persister , collection , ce .getCurrentKey (), session )
176
- );
170
+ LOG .debug ( "Skipping uninitialized bytecode-lazy collection: "
171
+ + collectionInfoString ( persister , collection , ce .getCurrentKey (), session ) );
177
172
}
178
173
ce .setReached ( true );
179
174
ce .setProcessed ( true );
@@ -184,9 +179,7 @@ public static void processReachableCollection(
184
179
// who set up circular or shared references between/to collections.
185
180
if ( ce .isReached () ) {
186
181
// We've been here before
187
- throw new HibernateException (
188
- "Found shared references to a collection: " + type .getRole ()
189
- );
182
+ throw new HibernateException ( "Found shared references to a collection: " + type .getRole () );
190
183
}
191
184
192
185
ce .setReached ( true );
@@ -195,13 +188,13 @@ public static void processReachableCollection(
195
188
if ( collection .wasInitialized () ) {
196
189
LOG .debugf (
197
190
"Collection found: %s, was: %s (initialized)" ,
198
- MessageHelper . collectionInfoString (
191
+ collectionInfoString (
199
192
persister ,
200
193
collection ,
201
194
ce .getCurrentKey (),
202
195
session
203
196
),
204
- MessageHelper . collectionInfoString (
197
+ collectionInfoString (
205
198
ce .getLoadedPersister (),
206
199
collection ,
207
200
ce .getLoadedKey (),
@@ -212,13 +205,13 @@ public static void processReachableCollection(
212
205
else {
213
206
LOG .debugf (
214
207
"Collection found: %s, was: %s (uninitialized)" ,
215
- MessageHelper . collectionInfoString (
208
+ collectionInfoString (
216
209
persister ,
217
210
collection ,
218
211
ce .getCurrentKey (),
219
212
session
220
213
),
221
- MessageHelper . collectionInfoString (
214
+ collectionInfoString (
222
215
ce .getLoadedPersister (),
223
216
collection ,
224
217
ce .getLoadedKey (),
@@ -250,25 +243,21 @@ private static void prepareCollectionForUpdate(
250
243
if ( loadedPersister != null || currentPersister != null ) {
251
244
// it is or was referenced _somewhere_
252
245
253
- // check if the key changed
254
- // excludes marking key changed when the loaded key is a DelayedPostInsertIdentifier.
255
- final boolean keyChanged = currentPersister != null
256
- && entry != null
257
- && !currentPersister .getKeyType ().isEqual ( entry .getLoadedKey (), entry .getCurrentKey (), factory )
258
- && !( entry .getLoadedKey () instanceof DelayedPostInsertIdentifier );
259
246
260
247
// if either its role changed, or its key changed
261
- final boolean ownerChanged = loadedPersister != currentPersister || keyChanged ;
248
+ final boolean ownerChanged =
249
+ loadedPersister != currentPersister
250
+ || wasKeyChanged ( entry , factory , currentPersister );
262
251
263
252
if ( ownerChanged ) {
264
253
// do a check
265
254
final boolean orphanDeleteAndRoleChanged =
266
255
loadedPersister != null && currentPersister != null && loadedPersister .hasOrphanDelete ();
267
256
268
- if (orphanDeleteAndRoleChanged ) {
257
+ if ( orphanDeleteAndRoleChanged ) {
269
258
throw new HibernateException (
270
- "Don't change the reference to a collection with delete- orphan enabled : "
271
- + loadedPersister .getRole ()
259
+ "Don't change the reference to a collection with delete orphan enabled: "
260
+ + loadedPersister .getRole ()
272
261
);
273
262
}
274
263
@@ -293,6 +282,17 @@ else if ( collection.isDirty() ) {
293
282
}
294
283
}
295
284
285
+ /**
286
+ * Check if the key changed.
287
+ * Excludes marking key changed when the loaded key is a {@code DelayedPostInsertIdentifier}.
288
+ */
289
+ private static boolean wasKeyChanged (
290
+ CollectionEntry entry , SessionFactoryImplementor factory , CollectionPersister currentPersister ) {
291
+ return currentPersister != null
292
+ && !currentPersister .getKeyType ().isEqual ( entry .getLoadedKey (), entry .getCurrentKey (), factory )
293
+ && !(entry .getLoadedKey () instanceof DelayedPostInsertIdentifier );
294
+ }
295
+
296
296
/**
297
297
* Determines if we can skip the explicit SQL delete statement, since
298
298
* the rows will be deleted by {@code on delete cascade}.
0 commit comments