Skip to content

Commit 80bbea4

Browse files
committed
HHH-18131 Composite identifiers with associations stopped working with @IdClass
1 parent 3aae473 commit 80bbea4

15 files changed

+105
-24
lines changed

hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
164164
final Object originalId;
165165
if ( entry == null ) {
166166
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
167-
originalId = persister.getIdentifier( entity, source );
167+
originalId = persister.getIdentifier( entity, copiedAlready );
168168
if ( originalId != null ) {
169169
final EntityKey entityKey;
170170
if ( persister.getIdentifierType() instanceof ComponentType ) {

hibernate-core/src/main/java/org/hibernate/event/spi/MergeContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,8 @@ private String printEntity(Object entity) {
366366
// Entity was not found in current persistence context. Use Object#toString() method.
367367
return "[" + entity + "]";
368368
}
369+
370+
public EventSource getEventSource() {
371+
return session;
372+
}
369373
}

hibernate-core/src/main/java/org/hibernate/internal/util/EntityPrinter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hibernate.engine.spi.EntityHolder;
1616
import org.hibernate.engine.spi.EntityKey;
1717
import org.hibernate.engine.spi.SessionFactoryImplementor;
18+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1819
import org.hibernate.engine.spi.TypedValue;
1920
import org.hibernate.internal.CoreLogging;
2021
import org.hibernate.internal.CoreMessageLogger;
@@ -53,7 +54,7 @@ public String toString(String entityName, Object entity) throws HibernateExcepti
5354
result.put(
5455
entityPersister.getIdentifierPropertyName(),
5556
entityPersister.getIdentifierType().toLoggableString(
56-
entityPersister.getIdentifier( entity, null ),
57+
entityPersister.getIdentifier( entity, (SharedSessionContractImplementor) null ),
5758
factory
5859
)
5960
);

hibernate-core/src/main/java/org/hibernate/jpa/internal/PersistenceUnitUtilImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.hibernate.MappingException;
1414
import org.hibernate.engine.spi.EntityEntry;
1515
import org.hibernate.engine.spi.SessionFactoryImplementor;
16+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1617
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
1718
import org.hibernate.persister.entity.EntityPersister;
1819
import org.hibernate.proxy.LazyInitializer;
@@ -106,7 +107,7 @@ private Object getIdentifierFromPersister(Object entity) {
106107
catch (MappingException ex) {
107108
throw new IllegalArgumentException( entityClass.getName() + " is not an entity", ex );
108109
}
109-
return persister.getIdentifier( entity, null );
110+
return persister.getIdentifier( entity, (SharedSessionContractImplementor) null );
110111
}
111112

112113
}

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityIdentifierMapping.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.hibernate.engine.internal.ForeignKeys;
1111
import org.hibernate.engine.spi.IdentifierValue;
1212
import org.hibernate.engine.spi.SharedSessionContractImplementor;
13+
import org.hibernate.event.spi.MergeContext;
1314

1415
import jakarta.persistence.EmbeddedId;
1516
import jakarta.persistence.Id;
@@ -68,6 +69,15 @@ default String getPartName() {
6869
*/
6970
Object getIdentifier(Object entity);
7071

72+
/**
73+
* Extract the identifier from an instance of the entity
74+
*
75+
* It's supposed to be use during the merging process
76+
*/
77+
default Object getIdentifier(Object entity, MergeContext mergeContext){
78+
return getIdentifier( entity );
79+
}
80+
7181
/**
7282
* Return the identifier of the persistent or transient object, or throw
7383
* an exception if the instance is "unsaved"

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/InverseNonAggregatedIdentifierMapping.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.hibernate.engine.spi.EntityKey;
1515
import org.hibernate.engine.spi.PersistenceContext;
1616
import org.hibernate.engine.spi.SharedSessionContractImplementor;
17+
import org.hibernate.event.spi.MergeContext;
1718
import org.hibernate.internal.util.collections.CollectionHelper;
1819
import org.hibernate.metamodel.mapping.AttributeMapping;
1920
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
@@ -196,6 +197,11 @@ public SqlTuple toSqlExpression(
196197

197198
@Override
198199
public Object getIdentifier(Object entity) {
200+
return getIdentifier( entity, null );
201+
}
202+
203+
@Override
204+
public Object getIdentifier(Object entity, MergeContext mergeContext) {
199205
if ( hasContainingClass() ) {
200206
final Object id = identifierValueMapper.getRepresentationStrategy().getInstantiator().instantiate(
201207
null,
@@ -218,16 +224,17 @@ public Object getIdentifier(Object entity) {
218224
//JPA 2 @MapsId + @IdClass points to the pk of the entity
219225
else if ( attributeMapping instanceof ToOneAttributeMapping
220226
&& !( identifierValueMapper.getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
227+
final Object toOne = getIfMerged( o, mergeContext );
221228
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
222229
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
223230
toOneAttributeMapping.getSideNature().inverse()
224231
);
225232
if ( targetPart.isEntityIdentifierMapping() ) {
226-
propertyValues[i] = ( (EntityIdentifierMapping) targetPart ).getIdentifier( o );
233+
propertyValues[i] = ( (EntityIdentifierMapping) targetPart )
234+
.getIdentifier( toOne, mergeContext );
227235
}
228236
else {
229-
propertyValues[i] = o;
230-
assert false;
237+
propertyValues[i] = toOne;
231238
}
232239
}
233240
else {
@@ -242,6 +249,16 @@ else if ( attributeMapping instanceof ToOneAttributeMapping
242249
}
243250
}
244251

252+
private static Object getIfMerged(Object o, MergeContext mergeContext) {
253+
if ( mergeContext != null ) {
254+
final Object merged = mergeContext.get( o );
255+
if ( merged != null ) {
256+
return merged;
257+
}
258+
}
259+
return o;
260+
}
261+
245262
@Override
246263
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
247264
final Object[] propertyValues = new Object[identifierValueMapper.getNumberOfAttributeMappings()];

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hibernate.engine.spi.EntityKey;
1616
import org.hibernate.engine.spi.PersistenceContext;
1717
import org.hibernate.engine.spi.SharedSessionContractImplementor;
18+
import org.hibernate.event.spi.MergeContext;
1819
import org.hibernate.internal.util.collections.CollectionHelper;
1920
import org.hibernate.mapping.Component;
2021
import org.hibernate.mapping.RootClass;
@@ -237,6 +238,11 @@ public String getAttributeName() {
237238

238239
@Override
239240
public Object getIdentifier(Object entity) {
241+
return getIdentifier( entity, null );
242+
}
243+
244+
@Override
245+
public Object getIdentifier(Object entity, MergeContext mergeContext) {
240246
if ( hasContainingClass() ) {
241247
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
242248
if ( lazyInitializer != null ) {
@@ -259,16 +265,16 @@ public Object getIdentifier(Object entity) {
259265
//JPA 2 @MapsId + @IdClass points to the pk of the entity
260266
else if ( attributeMapping instanceof ToOneAttributeMapping
261267
&& !( identifierValueMapper.getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
268+
final Object toOne = getIfMerged( o, mergeContext );
262269
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
263270
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
264271
toOneAttributeMapping.getSideNature().inverse()
265272
);
266273
if ( targetPart.isEntityIdentifierMapping() ) {
267-
propertyValues[i] = ( (EntityIdentifierMapping) targetPart ).getIdentifier( o );
274+
propertyValues[i] = ( (EntityIdentifierMapping) targetPart ).getIdentifier( toOne, mergeContext );
268275
}
269276
else {
270-
propertyValues[i] = o;
271-
assert false;
277+
propertyValues[i] = toOne;
272278
}
273279
}
274280
else {
@@ -285,6 +291,16 @@ else if ( attributeMapping instanceof ToOneAttributeMapping
285291
}
286292
}
287293

294+
private static Object getIfMerged(Object o, MergeContext mergeContext) {
295+
if ( mergeContext != null ) {
296+
final Object merged = mergeContext.get( o );
297+
if ( merged != null ) {
298+
return merged;
299+
}
300+
}
301+
return o;
302+
}
303+
288304
@Override
289305
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
290306
final Object[] propertyValues = new Object[identifierValueMapper.getNumberOfAttributeMappings()];

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
import org.hibernate.engine.spi.SharedSessionContractImplementor;
101101
import org.hibernate.event.spi.EventSource;
102102
import org.hibernate.event.spi.LoadEvent;
103+
import org.hibernate.event.spi.MergeContext;
103104
import org.hibernate.generator.BeforeExecutionGenerator;
104105
import org.hibernate.generator.EventType;
105106
import org.hibernate.generator.Generator;
@@ -4724,6 +4725,11 @@ public Object getIdentifier(Object entity, SharedSessionContractImplementor sess
47244725
return identifierMapping.getIdentifier( entity );
47254726
}
47264727

4728+
@Override
4729+
public Object getIdentifier(Object entity, MergeContext mergeContext) {
4730+
return identifierMapping.getIdentifier( entity, mergeContext );
4731+
}
4732+
47274733
@Override
47284734
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
47294735
identifierMapping.setIdentifier( entity, id, session );

hibernate-core/src/main/java/org/hibernate/persister/entity/EntityPersister.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.hibernate.engine.spi.SessionImplementor;
3131
import org.hibernate.engine.spi.SharedSessionContractImplementor;
3232
import org.hibernate.event.spi.EventSource;
33+
import org.hibernate.event.spi.MergeContext;
3334
import org.hibernate.generator.BeforeExecutionGenerator;
3435
import org.hibernate.generator.EventType;
3536
import org.hibernate.generator.Generator;
@@ -1130,8 +1131,18 @@ default Object getValue(Object object, int i) {
11301131
*/
11311132
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
11321133

1133-
/**
1134-
* Inject the identifier value into the given entity.
1134+
/**
1135+
* Get the identifier of an instance from the object's identifier property.
1136+
* Throw an exception if it has no identifier property.
1137+
*
1138+
* It's supposed to be use during the merging process
1139+
*/
1140+
default Object getIdentifier(Object entity, MergeContext mergeContext) {
1141+
return getIdentifier( entity, mergeContext.getEventSource() );
1142+
}
1143+
1144+
/**
1145+
* Inject the identifier value into the given entity.
11351146
*/
11361147
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
11371148

hibernate-core/src/main/java/org/hibernate/query/derived/AnonymousTupleBasicEntityIdentifierMapping.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.hibernate.Incubating;
1010
import org.hibernate.engine.spi.IdentifierValue;
1111
import org.hibernate.engine.spi.SharedSessionContractImplementor;
12+
import org.hibernate.event.spi.MergeContext;
1213
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
1314
import org.hibernate.metamodel.mapping.JdbcMapping;
1415
import org.hibernate.metamodel.mapping.ManagedMappingType;
@@ -51,6 +52,11 @@ public Object getIdentifier(Object entity) {
5152
return delegate.getIdentifier( entity );
5253
}
5354

55+
@Override
56+
public Object getIdentifier(Object entity, MergeContext mergeContext) {
57+
return delegate.getIdentifier( entity, mergeContext );
58+
}
59+
5460
@Override
5561
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
5662
delegate.setIdentifier( entity, id, session );

0 commit comments

Comments
 (0)