Skip to content

Commit 3ee8433

Browse files
committed
HHH-19393 Fix envers mappers for immutable components
1 parent ae56c71 commit 3ee8433

File tree

3 files changed

+60
-32
lines changed

3 files changed

+60
-32
lines changed

hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/AbstractCompositeIdMapper.java

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
import org.hibernate.envers.exception.AuditException;
1010
import org.hibernate.envers.internal.entities.PropertyData;
1111
import org.hibernate.envers.internal.tools.Tools;
12-
import org.hibernate.internal.util.ReflectHelper;
12+
import org.hibernate.mapping.Component;
1313
import org.hibernate.service.ServiceRegistry;
14+
import org.hibernate.type.spi.CompositeTypeImplementor;
15+
1416

1517
/**
1618
* An abstract identifier mapper implementation specific for composite identifiers.
@@ -20,13 +22,16 @@
2022
* @author Chris Cranford
2123
*/
2224
public abstract class AbstractCompositeIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
23-
protected final Class<?> compositeIdClass;
24-
25+
protected final CompositeTypeImplementor compositeType;
2526
protected Map<PropertyData, AbstractIdMapper> ids;
2627

27-
protected AbstractCompositeIdMapper(Class<?> compositeIdClass, ServiceRegistry serviceRegistry) {
28+
protected AbstractCompositeIdMapper(Component component) {
29+
this( component.getServiceRegistry(), (CompositeTypeImplementor) component.getType() );
30+
}
31+
32+
protected AbstractCompositeIdMapper(ServiceRegistry serviceRegistry, CompositeTypeImplementor compositeType) {
2833
super( serviceRegistry );
29-
this.compositeIdClass = compositeIdClass;
34+
this.compositeType = compositeType;
3035
ids = Tools.newLinkedHashMap();
3136
}
3237

@@ -46,24 +51,44 @@ public Object mapToIdFromMap(Map data) {
4651
return null;
4752
}
4853

49-
final Object compositeId = instantiateCompositeId();
50-
for ( AbstractIdMapper mapper : ids.values() ) {
51-
if ( !mapper.mapToEntityFromMap( compositeId, data ) ) {
52-
return null;
54+
if ( !compositeType.isMutable() ) {
55+
return mapToImmutableIdFromMap( data );
56+
}
57+
58+
final Object compositeId = instantiateCompositeId( null );
59+
60+
if ( compositeType.isMutable() ) {
61+
for ( AbstractIdMapper mapper : ids.values() ) {
62+
if ( !mapper.mapToEntityFromMap( compositeId, data ) ) {
63+
return null;
64+
}
5365
}
5466
}
5567

5668
return compositeId;
5769
}
5870

71+
protected Object mapToImmutableIdFromMap(Map data) {
72+
final var propertyNames = compositeType.getPropertyNames();
73+
final var values = new Object[propertyNames.length];
74+
for ( int i = 0; i < propertyNames.length; i++ ) {
75+
values[i] = data.get( propertyNames[i] );
76+
}
77+
return instantiateCompositeId( values );
78+
}
79+
5980
@Override
6081
public void mapToEntityFromEntity(Object objectTo, Object objectFrom) {
6182
// no-op; does nothing
6283
}
6384

64-
protected Object instantiateCompositeId() {
85+
protected Object instantiateCompositeId(Object[] values) {
6586
try {
66-
return ReflectHelper.getDefaultConstructor( compositeIdClass ).newInstance();
87+
return compositeType.getMappingModelPart()
88+
.getEmbeddableTypeDescriptor()
89+
.getRepresentationStrategy()
90+
.getInstantiator()
91+
.instantiate( () -> values );
6792
}
6893
catch ( Exception e ) {
6994
throw new AuditException( e );

hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/EmbeddedIdMapper.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hibernate.mapping.Component;
1616
import org.hibernate.property.access.spi.Setter;
1717
import org.hibernate.service.ServiceRegistry;
18+
import org.hibernate.type.spi.CompositeTypeImplementor;
1819

1920
/**
2021
* An identifier mapper implementation for {@link jakarta.persistence.EmbeddedId} mappings.
@@ -26,12 +27,12 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
2627
private PropertyData idPropertyData;
2728

2829
public EmbeddedIdMapper(PropertyData propertyData, Component component) {
29-
super( component.getComponentClass(), component.getServiceRegistry() );
30+
super( component );
3031
this.idPropertyData = propertyData;
3132
}
3233

33-
private EmbeddedIdMapper(PropertyData idPropertyData, Class<?> compositeIdClass, ServiceRegistry serviceRegistry) {
34-
super( compositeIdClass, serviceRegistry );
34+
private EmbeddedIdMapper(PropertyData idPropertyData, CompositeTypeImplementor compositeType, ServiceRegistry serviceRegistry) {
35+
super( serviceRegistry, compositeType );
3536
this.idPropertyData = idPropertyData;
3637
}
3738

@@ -58,11 +59,17 @@ public boolean mapToEntityFromMap(final Object obj, final Map data) {
5859

5960
final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() );
6061
try {
61-
final Object subObj = instantiateCompositeId();
62-
62+
final Object subObj;
6363
boolean ret = true;
64-
for ( IdMapper idMapper : ids.values() ) {
65-
ret &= idMapper.mapToEntityFromMap( subObj, data );
64+
if ( compositeType.isMutable() ) {
65+
subObj = instantiateCompositeId( null );
66+
for ( IdMapper idMapper : ids.values() ) {
67+
ret &= idMapper.mapToEntityFromMap( subObj, data );
68+
}
69+
}
70+
else {
71+
subObj = mapToImmutableIdFromMap( data );
72+
ret = subObj != null;
6673
}
6774

6875
if ( ret ) {
@@ -78,7 +85,7 @@ public boolean mapToEntityFromMap(final Object obj, final Map data) {
7885

7986
@Override
8087
public IdMapper prefixMappedProperties(String prefix) {
81-
final EmbeddedIdMapper ret = new EmbeddedIdMapper( idPropertyData, compositeIdClass, getServiceRegistry() );
88+
final EmbeddedIdMapper ret = new EmbeddedIdMapper( idPropertyData, compositeType, getServiceRegistry() );
8289

8390
for ( PropertyData propertyData : ids.keySet() ) {
8491
final String propertyName = propertyData.getName();

hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/id/MultipleIdMapper.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hibernate.proxy.HibernateProxy;
1616
import org.hibernate.proxy.LazyInitializer;
1717
import org.hibernate.service.ServiceRegistry;
18+
import org.hibernate.type.spi.CompositeTypeImplementor;
1819

1920
/**
2021
* An implementation of an identifier mapper for {@link jakarta.persistence.IdClass} or multiple
@@ -24,17 +25,12 @@
2425
* @author Chris Cranford
2526
*/
2627
public class MultipleIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
27-
28-
private final boolean embedded;
29-
3028
public MultipleIdMapper(Component component) {
31-
super( component.getComponentClass(), component.getServiceRegistry() );
32-
this.embedded = component.isEmbedded();
29+
super( component );
3330
}
3431

35-
private MultipleIdMapper(boolean embedded, Class<?> compositeIdClass, ServiceRegistry serviceRegistry) {
36-
super( compositeIdClass, serviceRegistry );
37-
this.embedded = embedded;
32+
private MultipleIdMapper(CompositeTypeImplementor compositeType, ServiceRegistry serviceRegistry) {
33+
super( serviceRegistry, compositeType );
3834
}
3935

4036
@Override
@@ -44,8 +40,8 @@ public void add(PropertyData propertyData) {
4440

4541
@Override
4642
public void mapToMapFromId(Session session, Map<String, Object> data, Object obj) {
47-
if ( compositeIdClass.isInstance( obj ) ) {
48-
if ( embedded ) {
43+
if ( compositeType.getReturnedClass().isInstance( obj ) ) {
44+
if ( compositeType.isEmbedded() ) {
4945
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( obj );
5046
if ( lazyInitializer != null ) {
5147
obj = lazyInitializer.getInternalIdentifier();
@@ -77,7 +73,7 @@ public void mapToMapFromId(Map<String, Object> data, Object obj) {
7773

7874
@Override
7975
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
80-
if ( embedded ) {
76+
if ( compositeType.isEmbedded() ) {
8177
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( obj );
8278
if ( lazyInitializer != null ) {
8379
obj = lazyInitializer.getInternalIdentifier();
@@ -100,7 +96,7 @@ public boolean mapToEntityFromMap(Object obj, Map data) {
10096

10197
@Override
10298
public IdMapper prefixMappedProperties(String prefix) {
103-
final MultipleIdMapper ret = new MultipleIdMapper( embedded, compositeIdClass, getServiceRegistry() );
99+
final MultipleIdMapper ret = new MultipleIdMapper( compositeType, getServiceRegistry() );
104100

105101
for ( PropertyData propertyData : ids.keySet() ) {
106102
final String propertyName = propertyData.getName();
@@ -116,7 +112,7 @@ public Object mapToIdFromEntity(Object data) {
116112
return null;
117113
}
118114

119-
final Object compositeId = instantiateCompositeId();
115+
final Object compositeId = instantiateCompositeId( null );
120116
for ( AbstractIdMapper mapper : ids.values() ) {
121117
mapper.mapToEntityFromEntity( compositeId, data );
122118
}

0 commit comments

Comments
 (0)