Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.tools.Tools;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.Component;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.spi.CompositeTypeImplementor;


/**
* An abstract identifier mapper implementation specific for composite identifiers.
Expand All @@ -20,13 +22,16 @@
* @author Chris Cranford
*/
public abstract class AbstractCompositeIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
protected final Class<?> compositeIdClass;

protected final CompositeTypeImplementor compositeType;
protected Map<PropertyData, AbstractIdMapper> ids;

protected AbstractCompositeIdMapper(Class<?> compositeIdClass, ServiceRegistry serviceRegistry) {
protected AbstractCompositeIdMapper(Component component) {
this( component.getServiceRegistry(), (CompositeTypeImplementor) component.getType() );
}

protected AbstractCompositeIdMapper(ServiceRegistry serviceRegistry, CompositeTypeImplementor compositeType) {
super( serviceRegistry );
this.compositeIdClass = compositeIdClass;
this.compositeType = compositeType;
ids = Tools.newLinkedHashMap();
}

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

final Object compositeId = instantiateCompositeId();
for ( AbstractIdMapper mapper : ids.values() ) {
if ( !mapper.mapToEntityFromMap( compositeId, data ) ) {
return null;
if ( !compositeType.isMutable() ) {
return mapToImmutableIdFromMap( data );
}

final Object compositeId = instantiateCompositeId( null );

if ( compositeType.isMutable() ) {
for ( AbstractIdMapper mapper : ids.values() ) {
if ( !mapper.mapToEntityFromMap( compositeId, data ) ) {
return null;
}
}
}

return compositeId;
}

protected Object mapToImmutableIdFromMap(Map data) {
final var propertyNames = compositeType.getPropertyNames();
final var values = new Object[propertyNames.length];
for ( int i = 0; i < propertyNames.length; i++ ) {
values[i] = data.get( propertyNames[i] );
}
return instantiateCompositeId( values );
}

@Override
public void mapToEntityFromEntity(Object objectTo, Object objectFrom) {
// no-op; does nothing
}

protected Object instantiateCompositeId() {
protected Object instantiateCompositeId(Object[] values) {
try {
return ReflectHelper.getDefaultConstructor( compositeIdClass ).newInstance();
return compositeType.getMappingModelPart()
.getEmbeddableTypeDescriptor()
.getRepresentationStrategy()
.getInstantiator()
.instantiate( () -> values );
}
catch ( Exception e ) {
throw new AuditException( e );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.hibernate.mapping.Component;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.spi.CompositeTypeImplementor;

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

public EmbeddedIdMapper(PropertyData propertyData, Component component) {
super( component.getComponentClass(), component.getServiceRegistry() );
super( component );
this.idPropertyData = propertyData;
}

private EmbeddedIdMapper(PropertyData idPropertyData, Class<?> compositeIdClass, ServiceRegistry serviceRegistry) {
super( compositeIdClass, serviceRegistry );
private EmbeddedIdMapper(PropertyData idPropertyData, CompositeTypeImplementor compositeType, ServiceRegistry serviceRegistry) {
super( serviceRegistry, compositeType );
this.idPropertyData = idPropertyData;
}

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

final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() );
try {
final Object subObj = instantiateCompositeId();

final Object subObj;
boolean ret = true;
for ( IdMapper idMapper : ids.values() ) {
ret &= idMapper.mapToEntityFromMap( subObj, data );
if ( compositeType.isMutable() ) {
subObj = instantiateCompositeId( null );
for ( IdMapper idMapper : ids.values() ) {
ret &= idMapper.mapToEntityFromMap( subObj, data );
}
}
else {
subObj = mapToImmutableIdFromMap( data );
ret = subObj != null;
}

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

@Override
public IdMapper prefixMappedProperties(String prefix) {
final EmbeddedIdMapper ret = new EmbeddedIdMapper( idPropertyData, compositeIdClass, getServiceRegistry() );
final EmbeddedIdMapper ret = new EmbeddedIdMapper( idPropertyData, compositeType, getServiceRegistry() );

for ( PropertyData propertyData : ids.keySet() ) {
final String propertyName = propertyData.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.spi.CompositeTypeImplementor;

import java.util.ArrayList;
import java.util.LinkedHashMap;
Expand All @@ -24,17 +25,12 @@
* @author Chris Cranford
*/
public class MultipleIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {

private final boolean embedded;

public MultipleIdMapper(Component component) {
super( component.getComponentClass(), component.getServiceRegistry() );
this.embedded = component.isEmbedded();
super( component );
}

private MultipleIdMapper(boolean embedded, Class<?> compositeIdClass, ServiceRegistry serviceRegistry) {
super( compositeIdClass, serviceRegistry );
this.embedded = embedded;
private MultipleIdMapper(CompositeTypeImplementor compositeType, ServiceRegistry serviceRegistry) {
super( serviceRegistry, compositeType );
}

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

@Override
public void mapToMapFromId(SharedSessionContractImplementor session, Map<String, Object> data, Object obj) {
if ( compositeIdClass.isInstance( obj ) ) {
if ( embedded ) {
if ( compositeType.getReturnedClass().isInstance( obj ) ) {
if ( compositeType.isEmbedded() ) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( obj );
if ( lazyInitializer != null ) {
obj = lazyInitializer.getInternalIdentifier();
Expand Down Expand Up @@ -77,7 +73,7 @@ public void mapToMapFromId(Map<String, Object> data, Object obj) {

@Override
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
if ( embedded ) {
if ( compositeType.isEmbedded() ) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( obj );
if ( lazyInitializer != null ) {
obj = lazyInitializer.getInternalIdentifier();
Expand All @@ -100,7 +96,7 @@ public boolean mapToEntityFromMap(Object obj, Map data) {

@Override
public IdMapper prefixMappedProperties(String prefix) {
final MultipleIdMapper ret = new MultipleIdMapper( embedded, compositeIdClass, getServiceRegistry() );
final MultipleIdMapper ret = new MultipleIdMapper( compositeType, getServiceRegistry() );

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

final Object compositeId = instantiateCompositeId();
final Object compositeId = instantiateCompositeId( null );
for ( AbstractIdMapper mapper : ids.values() ) {
mapper.mapToEntityFromEntity( compositeId, data );
}
Expand Down
Loading