HHH-14950 - Support mapping of embeddables with no setters (assuming a custom instantiator or repo-strategy is used)
Tests; Remove `ComponentTuplizer` and friends; Remove `ComponentMetadata`
This commit is contained in:
parent
09cc6d7b00
commit
fa4b76702c
|
@ -1688,12 +1688,8 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
props,
|
||||
false
|
||||
);
|
||||
|
||||
if ( isEmptyCompositesEnabled ) {
|
||||
// It would be nice to do this logging in ComponentMetamodel, where
|
||||
// AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED is actually used.
|
||||
// Unfortunately that would end up logging a message several times for
|
||||
// each embeddable/composite. Doing it here will log the message only
|
||||
// once.
|
||||
LOG.emptyCompositesEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.mapping;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -16,8 +15,8 @@ import java.util.Objects;
|
|||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
|
||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
import org.hibernate.boot.model.source.internal.hbm.MappingDocument;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
|
@ -28,10 +27,8 @@ import org.hibernate.id.IdentifierGenerator;
|
|||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.collections.JoinedIterator;
|
||||
import org.hibernate.metamodel.RepresentationMode;
|
||||
import org.hibernate.metamodel.EmbeddableInstantiator;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
import org.hibernate.tuple.component.ComponentMetamodel;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.EmbeddedComponentType;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -56,7 +53,6 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
private String roleName;
|
||||
|
||||
private Class<? extends EmbeddableInstantiator> customInstantiator;
|
||||
private Map<RepresentationMode,String> tuplizerImpls;
|
||||
|
||||
// cache the status of the type
|
||||
private volatile Type type;
|
||||
|
@ -205,14 +201,9 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
// Other components should be sorted already
|
||||
sortProperties( true );
|
||||
|
||||
// TODO : temporary initial step towards HHH-1907
|
||||
final ComponentMetamodel metamodel = new ComponentMetamodel(
|
||||
this,
|
||||
getMetadata().getMetadataBuildingOptions()
|
||||
);
|
||||
localType = isEmbedded()
|
||||
? new EmbeddedComponentType( getBuildingContext().getBootstrapContext().getTypeConfiguration(), metamodel, originalPropertyOrder )
|
||||
: new ComponentType( getBuildingContext().getBootstrapContext().getTypeConfiguration(), metamodel, originalPropertyOrder );
|
||||
? new EmbeddedComponentType( this, originalPropertyOrder, getBuildingContext() )
|
||||
: new ComponentType( this, originalPropertyOrder, getBuildingContext() );
|
||||
|
||||
this.type = localType;
|
||||
}
|
||||
|
@ -329,29 +320,6 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
return componentClassName!=null;
|
||||
}
|
||||
|
||||
public void addTuplizer(RepresentationMode representationMode, String implClassName) {
|
||||
if ( tuplizerImpls == null ) {
|
||||
tuplizerImpls = new HashMap<>();
|
||||
}
|
||||
tuplizerImpls.put( representationMode, implClassName );
|
||||
}
|
||||
|
||||
public String getTuplizerImplClassName(RepresentationMode mode) {
|
||||
// todo : remove this once ComponentMetamodel is complete and merged
|
||||
if ( tuplizerImpls == null ) {
|
||||
return null;
|
||||
}
|
||||
return tuplizerImpls.get( mode );
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Map getTuplizerMap() {
|
||||
if ( tuplizerImpls == null ) {
|
||||
return null;
|
||||
}
|
||||
return java.util.Collections.unmodifiableMap( tuplizerImpls );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Property} at the specified position in this {@link Component}.
|
||||
*
|
||||
|
|
|
@ -30,9 +30,6 @@ import org.hibernate.property.access.spi.Getter;
|
|||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @see org.hibernate.tuple.entity.EntityTuplizer
|
||||
* @see org.hibernate.tuple.component.ComponentTuplizer
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated See {@link ManagedTypeRepresentationStrategy}
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.tuple.component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
|
||||
/**
|
||||
* Support for tuplizers relating to components.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractComponentTuplizer implements ComponentTuplizer {
|
||||
protected final Getter[] getters;
|
||||
protected final Setter[] setters;
|
||||
protected final int propertySpan;
|
||||
protected final boolean hasCustomAccessors;
|
||||
|
||||
protected abstract Getter buildGetter(Component component, Property prop);
|
||||
protected abstract Setter buildSetter(Component component, Property prop);
|
||||
|
||||
protected AbstractComponentTuplizer(Component component) {
|
||||
setComponentClass( component );
|
||||
propertySpan = component.getPropertySpan();
|
||||
getters = new Getter[propertySpan];
|
||||
setters = new Setter[propertySpan];
|
||||
|
||||
Iterator iter = component.getPropertyIterator();
|
||||
boolean foundCustomAccessor=false;
|
||||
int i = 0;
|
||||
while ( iter.hasNext() ) {
|
||||
Property prop = ( Property ) iter.next();
|
||||
getters[i] = buildGetter( component, prop );
|
||||
setters[i] = buildSetter( component, prop );
|
||||
if ( !prop.isBasicPropertyAccessor() ) {
|
||||
foundCustomAccessor = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
hasCustomAccessors = foundCustomAccessor;
|
||||
}
|
||||
|
||||
public Object getPropertyValue(Object component, int i) throws HibernateException {
|
||||
return getters[i].get( component );
|
||||
}
|
||||
|
||||
public Object[] getPropertyValues(Object component) throws HibernateException {
|
||||
Object[] values = new Object[propertySpan];
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
values[i] = getPropertyValue( component, i );
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setPropertyValues(Object component, Object[] values) throws HibernateException {
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
setters[i].set( component, values[i] );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMethodOf(Method method) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Getter getGetter(int i) {
|
||||
return getters[i];
|
||||
}
|
||||
|
||||
// It should be an abstract method but not sure if this can break any customer extension
|
||||
protected void setComponentClass(Component component){
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.tuple.component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.RepresentationMode;
|
||||
import org.hibernate.tuple.PropertyFactory;
|
||||
import org.hibernate.tuple.StandardProperty;
|
||||
|
||||
/**
|
||||
* Centralizes metamodel information about a component.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ComponentMetamodel implements Serializable {
|
||||
|
||||
// TODO : will need reference to session factory to fully complete HHH-1907
|
||||
|
||||
private final String role;
|
||||
private final boolean isKey;
|
||||
private final StandardProperty[] properties;
|
||||
|
||||
private final RepresentationMode representationMode;
|
||||
private final ComponentTuplizer componentTuplizer;
|
||||
|
||||
// cached for efficiency...
|
||||
private final int propertySpan;
|
||||
private final Map propertyIndexes = new HashMap();
|
||||
private final boolean createEmptyCompositesEnabled;
|
||||
|
||||
@Deprecated
|
||||
public ComponentMetamodel(Component component, MetadataBuildingOptions metadataBuildingOptions) {
|
||||
this( component, new ComponentTuplizerFactory( metadataBuildingOptions ) );
|
||||
}
|
||||
|
||||
private ComponentMetamodel(Component component, ComponentTuplizerFactory componentTuplizerFactory){
|
||||
this.role = component.getRoleName();
|
||||
this.isKey = component.isKey();
|
||||
propertySpan = component.getPropertySpan();
|
||||
properties = new StandardProperty[propertySpan];
|
||||
Iterator itr = component.getPropertyIterator();
|
||||
int i = 0;
|
||||
while ( itr.hasNext() ) {
|
||||
Property property = ( Property ) itr.next();
|
||||
properties[i] = PropertyFactory.buildStandardProperty( property, false );
|
||||
propertyIndexes.put( property.getName(), i );
|
||||
i++;
|
||||
}
|
||||
|
||||
representationMode = component.hasPojoRepresentation() ? RepresentationMode.POJO : RepresentationMode.MAP;
|
||||
|
||||
// todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel
|
||||
final String tuplizerClassName = component.getTuplizerImplClassName( representationMode );
|
||||
this.componentTuplizer = tuplizerClassName == null ? componentTuplizerFactory.constructDefaultTuplizer(
|
||||
representationMode,
|
||||
component
|
||||
) : componentTuplizerFactory.constructTuplizer( tuplizerClassName, component );
|
||||
|
||||
final ConfigurationService cs = component.getMetadata().getMetadataBuildingOptions().getServiceRegistry()
|
||||
.getService(ConfigurationService.class);
|
||||
|
||||
this.createEmptyCompositesEnabled = ConfigurationHelper.getBoolean(
|
||||
Environment.CREATE_EMPTY_COMPOSITES_ENABLED,
|
||||
cs.getSettings(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isKey() {
|
||||
return isKey;
|
||||
}
|
||||
|
||||
public int getPropertySpan() {
|
||||
return propertySpan;
|
||||
}
|
||||
|
||||
public StandardProperty[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public StandardProperty getProperty(int index) {
|
||||
if ( index < 0 || index >= propertySpan ) {
|
||||
throw new IllegalArgumentException( "illegal index value for component property access [request=" + index + ", span=" + propertySpan + "]" );
|
||||
}
|
||||
return properties[index];
|
||||
}
|
||||
|
||||
public int getPropertyIndex(String propertyName) {
|
||||
Integer index = ( Integer ) propertyIndexes.get( propertyName );
|
||||
if ( index == null ) {
|
||||
throw new HibernateException( "component does not contain such a property [" + propertyName + "]" );
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
public StandardProperty getProperty(String propertyName) {
|
||||
return getProperty( getPropertyIndex( propertyName ) );
|
||||
}
|
||||
|
||||
public RepresentationMode getRepresentationMode() {
|
||||
return representationMode;
|
||||
}
|
||||
|
||||
public ComponentTuplizer getComponentTuplizer() {
|
||||
return componentTuplizer;
|
||||
}
|
||||
|
||||
public boolean isCreateEmptyCompositesEnabled() {
|
||||
return createEmptyCompositesEnabled;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.tuple.component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.tuple.Tuplizer;
|
||||
|
||||
/**
|
||||
* Defines further responsibilities regarding tuplization based on
|
||||
* a mapped components.
|
||||
* </p>
|
||||
* ComponentTuplizer implementations should have the following constructor signature:
|
||||
* (org.hibernate.mapping.Component)
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated for removal in 6.0. See instead `ManagedTypeRepresentationStrategy`
|
||||
* and `RepresentationMode` in 6.0
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ComponentTuplizer extends Tuplizer, Serializable {
|
||||
|
||||
/**
|
||||
* Is the given method available via the managed component as a property getter?
|
||||
*
|
||||
* @param method The method which to check against the managed component.
|
||||
* @return True if the managed component is available from the managed component; else false.
|
||||
*/
|
||||
public boolean isMethodOf(Method method);
|
||||
|
||||
/**
|
||||
* Extract the current values contained on the given entity.
|
||||
*
|
||||
* @param entity The entity from which to extract values.
|
||||
* @return The current property values.
|
||||
*/
|
||||
public Object[] getPropertyValues(Object entity);
|
||||
|
||||
/**
|
||||
* Inject the given values into the given entity.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @param values The values to be injected.
|
||||
*/
|
||||
public void setPropertyValues(Object entity, Object[] values);
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.tuple.component;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.ClassLoaderAccess;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.metamodel.RepresentationMode;
|
||||
|
||||
/**
|
||||
* A registry allowing users to define the default {@link ComponentTuplizer} class to use per {@link RepresentationMode}.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ComponentTuplizerFactory implements Serializable {
|
||||
private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class };
|
||||
|
||||
private final Map<RepresentationMode,Class<? extends ComponentTuplizer>> defaultImplClassByMode = buildBaseMapping();
|
||||
|
||||
private final ClassLoaderAccess classLoaderAccess;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link ComponentTuplizerFactory#ComponentTuplizerFactory(BootstrapContext)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ComponentTuplizerFactory(MetadataBuildingOptions metadataBuildingOptions) {
|
||||
classLoaderAccess = new ClassLoaderAccessImpl(
|
||||
metadataBuildingOptions.getTempClassLoader(),
|
||||
metadataBuildingOptions.getServiceRegistry().getService( ClassLoaderService.class )
|
||||
);
|
||||
}
|
||||
|
||||
public ComponentTuplizerFactory(BootstrapContext bootstrapContext) {
|
||||
classLoaderAccess = bootstrapContext.getClassLoaderAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method allowing registration of the tuplizer class to use as default for a particular entity-mode.
|
||||
*
|
||||
* @param representationMode The entity-mode for which to register the tuplizer class
|
||||
* @param tuplizerClass The class to use as the default tuplizer for the given entity-mode.
|
||||
*/
|
||||
@SuppressWarnings({ "UnusedDeclaration" })
|
||||
public void registerDefaultTuplizerClass(RepresentationMode representationMode, Class<? extends ComponentTuplizer> tuplizerClass) {
|
||||
assert isComponentTuplizerImplementor( tuplizerClass )
|
||||
: "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + ComponentTuplizer.class.getName();
|
||||
assert hasProperConstructor( tuplizerClass )
|
||||
: "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable";
|
||||
|
||||
defaultImplClassByMode.put( representationMode, tuplizerClass );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the given tuplizer class.
|
||||
*
|
||||
* @param tuplizerClassName The name of the tuplizer class to instantiate
|
||||
* @param metadata The metadata for the component.
|
||||
*
|
||||
* @return The instantiated tuplizer
|
||||
*
|
||||
* @throws HibernateException If class name cannot be resolved to a class reference, or if the
|
||||
* {@link Constructor#newInstance} call fails.
|
||||
*/
|
||||
public ComponentTuplizer constructTuplizer(String tuplizerClassName, Component metadata) {
|
||||
try {
|
||||
Class<? extends ComponentTuplizer> tuplizerClass = classLoaderAccess.classForName( tuplizerClassName );
|
||||
return constructTuplizer( tuplizerClass, metadata );
|
||||
}
|
||||
catch ( ClassLoadingException e ) {
|
||||
throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the given tuplizer class.
|
||||
*
|
||||
* @param tuplizerClass The tuplizer class to instantiate
|
||||
* @param metadata The metadata for the component.
|
||||
*
|
||||
* @return The instantiated tuplizer
|
||||
*
|
||||
* @throws HibernateException if the {@link Constructor#newInstance} call fails.
|
||||
*/
|
||||
public ComponentTuplizer constructTuplizer(Class<? extends ComponentTuplizer> tuplizerClass, Component metadata) {
|
||||
Constructor<? extends ComponentTuplizer> constructor = getProperConstructor( tuplizerClass );
|
||||
assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]";
|
||||
try {
|
||||
return constructor.newInstance( metadata );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Unable to instantiate tuplizer [%s] for component: `%s` (%s)",
|
||||
tuplizerClass.getName(),
|
||||
metadata.getComponentClassName(),
|
||||
metadata.getRoleName()
|
||||
),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct am instance of the default tuplizer for the given entity-mode.
|
||||
*
|
||||
* @param representationMode The entity mode for which to build a default tuplizer.
|
||||
* @param metadata The metadata for the component.
|
||||
*
|
||||
* @return The instantiated tuplizer
|
||||
*
|
||||
* @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from
|
||||
* {@link #constructTuplizer} too.
|
||||
*/
|
||||
public ComponentTuplizer constructDefaultTuplizer(RepresentationMode representationMode, Component metadata) {
|
||||
Class<? extends ComponentTuplizer> tuplizerClass = defaultImplClassByMode.get( representationMode );
|
||||
if ( tuplizerClass == null ) {
|
||||
throw new HibernateException( "could not determine default tuplizer class to use [" + representationMode + "]" );
|
||||
}
|
||||
|
||||
return constructTuplizer( tuplizerClass, metadata );
|
||||
}
|
||||
|
||||
private boolean isComponentTuplizerImplementor(Class tuplizerClass) {
|
||||
return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class );
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private boolean hasProperConstructor(Class tuplizerClass) {
|
||||
return getProperConstructor( tuplizerClass ) != null;
|
||||
}
|
||||
|
||||
private Constructor<? extends ComponentTuplizer> getProperConstructor(Class<? extends ComponentTuplizer> clazz) {
|
||||
Constructor<? extends ComponentTuplizer> constructor = null;
|
||||
try {
|
||||
constructor = clazz.getDeclaredConstructor( COMPONENT_TUP_CTOR_SIG );
|
||||
try {
|
||||
ReflectHelper.ensureAccessibility( constructor );
|
||||
}
|
||||
catch ( SecurityException e ) {
|
||||
constructor = null;
|
||||
}
|
||||
}
|
||||
catch ( NoSuchMethodException ignore ) {
|
||||
}
|
||||
|
||||
return constructor;
|
||||
}
|
||||
|
||||
private static Map<RepresentationMode,Class<? extends ComponentTuplizer>> buildBaseMapping() {
|
||||
Map<RepresentationMode,Class<? extends ComponentTuplizer>> map = new ConcurrentHashMap<>();
|
||||
map.put( RepresentationMode.POJO, PojoComponentTuplizer.class );
|
||||
map.put( RepresentationMode.MAP, DynamicMapComponentTuplizer.class );
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.tuple.component;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyMapImpl;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
|
||||
/**
|
||||
* A {@link ComponentTuplizer} specific to the dynamic-map entity mode.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DynamicMapComponentTuplizer extends AbstractComponentTuplizer {
|
||||
|
||||
public Class getMappedClass() {
|
||||
return Map.class;
|
||||
}
|
||||
|
||||
public DynamicMapComponentTuplizer(Component component) {
|
||||
super(component);
|
||||
}
|
||||
|
||||
protected Getter buildGetter(Component component, Property prop) {
|
||||
return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( null, prop.getName() ).getGetter();
|
||||
}
|
||||
|
||||
protected Setter buildSetter(Component component, Property prop) {
|
||||
return PropertyAccessStrategyMapImpl.INSTANCE.buildPropertyAccess( null, prop.getName() ).getSetter();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.tuple.component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.bytecode.spi.BasicProxyFactory;
|
||||
import org.hibernate.bytecode.spi.BytecodeProvider;
|
||||
import org.hibernate.bytecode.spi.ProxyFactoryFactory;
|
||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBasicImpl;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.property.access.spi.Setter;
|
||||
import org.hibernate.tuple.Instantiator;
|
||||
|
||||
/**
|
||||
* A {@link ComponentTuplizer} specific to the pojo entity mode.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PojoComponentTuplizer extends AbstractComponentTuplizer {
|
||||
private Class componentClass;
|
||||
private ReflectionOptimizer optimizer;
|
||||
private final Getter parentGetter;
|
||||
private final Setter parentSetter;
|
||||
|
||||
public PojoComponentTuplizer(Component component) {
|
||||
super( component );
|
||||
|
||||
String[] getterNames = new String[propertySpan];
|
||||
String[] setterNames = new String[propertySpan];
|
||||
Class[] propTypes = new Class[propertySpan];
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
getterNames[i] = getters[i].getMethodName();
|
||||
setterNames[i] = setters[i].getMethodName();
|
||||
propTypes[i] = getters[i].getReturnTypeClass();
|
||||
}
|
||||
|
||||
final String parentPropertyName = component.getParentProperty();
|
||||
if ( parentPropertyName == null ) {
|
||||
parentSetter = null;
|
||||
parentGetter = null;
|
||||
}
|
||||
else {
|
||||
final PropertyAccess propertyAccess = PropertyAccessStrategyBasicImpl.INSTANCE.buildPropertyAccess(
|
||||
componentClass,
|
||||
parentPropertyName
|
||||
);
|
||||
parentSetter = propertyAccess.getSetter();
|
||||
parentGetter = propertyAccess.getGetter();
|
||||
}
|
||||
|
||||
if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) {
|
||||
optimizer = null;
|
||||
}
|
||||
else {
|
||||
final BytecodeProvider bytecodeProvider = component.getServiceRegistry().getService( BytecodeProvider.class );
|
||||
optimizer = bytecodeProvider.getReflectionOptimizer(
|
||||
componentClass, getterNames, setterNames, propTypes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Class getMappedClass() {
|
||||
return componentClass;
|
||||
}
|
||||
|
||||
public Object[] getPropertyValues(Object component) throws HibernateException {
|
||||
if ( component == PropertyAccessStrategyBackRefImpl.UNKNOWN ) {
|
||||
return new Object[propertySpan];
|
||||
}
|
||||
else if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
|
||||
return optimizer.getAccessOptimizer().getPropertyValues( component );
|
||||
}
|
||||
else {
|
||||
return super.getPropertyValues( component );
|
||||
}
|
||||
}
|
||||
|
||||
public void setPropertyValues(Object component, Object[] values) throws HibernateException {
|
||||
if ( optimizer != null && optimizer.getAccessOptimizer() != null ) {
|
||||
optimizer.getAccessOptimizer().setPropertyValues( component, values );
|
||||
}
|
||||
else {
|
||||
super.setPropertyValues( component, values );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMethodOf(Method method) {
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
final Method getterMethod = getters[i].getMethod();
|
||||
if ( getterMethod != null && getterMethod.equals( method ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Getter buildGetter(Component component, Property prop) {
|
||||
return prop.getGetter( this.componentClass );
|
||||
}
|
||||
|
||||
protected Setter buildSetter(Component component, Property prop) {
|
||||
return prop.getSetter( this.componentClass );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setComponentClass(Component component) {
|
||||
this.componentClass = component.getComponentClass();
|
||||
}
|
||||
|
||||
private static class ProxiedInstantiator implements Instantiator {
|
||||
private final Class proxiedClass;
|
||||
private final BasicProxyFactory factory;
|
||||
|
||||
public ProxiedInstantiator(Class componentClass, ProxyFactoryFactory proxyFactoryFactory) {
|
||||
proxiedClass = componentClass;
|
||||
factory = proxyFactoryFactory
|
||||
.buildBasicProxyFactory( proxiedClass );
|
||||
}
|
||||
|
||||
public Object instantiate(Object id) {
|
||||
throw new AssertionFailure( "ProxiedInstantiator can only be used to instantiate component" );
|
||||
}
|
||||
|
||||
public Object instantiate() {
|
||||
return factory.getProxy();
|
||||
}
|
||||
|
||||
public boolean isInstance(Object object) {
|
||||
return proxiedClass.isInstance( object );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import java.sql.CallableStatement;
|
|||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.FetchMode;
|
||||
|
@ -19,7 +20,10 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.PropertyNotFoundException;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -27,18 +31,19 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.EmbeddableInstantiator;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||
import org.hibernate.metamodel.EmbeddableInstantiator;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.tuple.PropertyFactory;
|
||||
import org.hibernate.tuple.StandardProperty;
|
||||
import org.hibernate.tuple.ValueGeneration;
|
||||
import org.hibernate.tuple.component.ComponentMetamodel;
|
||||
import org.hibernate.tuple.component.ComponentTuplizer;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.spi.CompositeTypeImplementor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Handles "component" mappings
|
||||
|
@ -46,8 +51,8 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class ComponentType extends AbstractType implements CompositeTypeImplementor, ProcedureParameterExtractionAware {
|
||||
private final Class<?> componentClass;
|
||||
|
||||
private final TypeConfiguration typeConfiguration;
|
||||
private final String[] propertyNames;
|
||||
private final Type[] propertyTypes;
|
||||
private final ValueGeneration[] propertyValueGenerationStrategies;
|
||||
|
@ -56,18 +61,20 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
|
|||
protected final int propertySpan;
|
||||
private final CascadeStyle[] cascade;
|
||||
private final FetchMode[] joinedFetch;
|
||||
|
||||
private final boolean isKey;
|
||||
private boolean hasNotNullProperty;
|
||||
private final boolean createEmptyCompositesEnabled;
|
||||
|
||||
protected final ComponentTuplizer componentTuplizer;
|
||||
private EmbeddableValuedModelPart mappingModelPart;
|
||||
|
||||
public ComponentType(TypeConfiguration typeConfiguration, ComponentMetamodel metamodel, int[] originalPropertyOrder) {
|
||||
this.typeConfiguration = typeConfiguration;
|
||||
// for now, just "re-flatten" the metamodel since this is temporary stuff anyway (HHH-1907)
|
||||
this.isKey = metamodel.isKey();
|
||||
this.propertySpan = metamodel.getPropertySpan();
|
||||
public ComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext buildingContext) {
|
||||
this.componentClass = component.isDynamic()
|
||||
? Map.class
|
||||
: component.getComponentClass();
|
||||
|
||||
this.isKey = component.isKey();
|
||||
this.propertySpan = component.getPropertySpan();
|
||||
this.originalPropertyOrder = originalPropertyOrder;
|
||||
this.propertyNames = new String[propertySpan];
|
||||
this.propertyTypes = new Type[propertySpan];
|
||||
|
@ -76,8 +83,12 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
|
|||
this.cascade = new CascadeStyle[propertySpan];
|
||||
this.joinedFetch = new FetchMode[propertySpan];
|
||||
|
||||
for ( int i = 0; i < propertySpan; i++ ) {
|
||||
StandardProperty prop = metamodel.getProperty( i );
|
||||
final Iterator<Property> itr = component.getPropertyIterator();
|
||||
int i = 0;
|
||||
while ( itr.hasNext() ) {
|
||||
final Property property = itr.next();
|
||||
// todo (6.0) : see if we really need to create these
|
||||
final StandardProperty prop = PropertyFactory.buildStandardProperty( property, false );
|
||||
this.propertyNames[i] = prop.getName();
|
||||
this.propertyTypes[i] = prop.getType();
|
||||
this.propertyNullability[i] = prop.isNullable();
|
||||
|
@ -87,10 +98,14 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
|
|||
hasNotNullProperty = true;
|
||||
}
|
||||
this.propertyValueGenerationStrategies[i] = prop.getValueGenerationStrategy();
|
||||
i++;
|
||||
}
|
||||
|
||||
this.componentTuplizer = metamodel.getComponentTuplizer();
|
||||
this.createEmptyCompositesEnabled = metamodel.isCreateEmptyCompositesEnabled();
|
||||
this.createEmptyCompositesEnabled = ConfigurationHelper.getBoolean(
|
||||
Environment.CREATE_EMPTY_COMPOSITES_ENABLED,
|
||||
buildingContext.getBootstrapContext().getServiceRegistry().getService( ConfigurationService.class ).getSettings(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isKey() {
|
||||
|
@ -152,8 +167,8 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
|
|||
return true;
|
||||
}
|
||||
|
||||
public Class getReturnedClass() {
|
||||
return componentTuplizer.getMappedClass();
|
||||
public Class<?> getReturnedClass() {
|
||||
return componentClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,22 +8,41 @@ package org.hibernate.type;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.hibernate.tuple.component.ComponentMetamodel;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.property.access.spi.Getter;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class EmbeddedComponentType extends ComponentType {
|
||||
public EmbeddedComponentType(TypeConfiguration typeScope, ComponentMetamodel metamodel, int[] propertyReordering) {
|
||||
super( typeScope, metamodel, propertyReordering );
|
||||
public EmbeddedComponentType(Component component, int[] originalPropertyOrder, MetadataBuildingContext buildingContext) {
|
||||
super( component, originalPropertyOrder, buildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmbedded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMethodOf(Method method) {
|
||||
return componentTuplizer.isMethodOf( method );
|
||||
if ( mappingModelPart() == null ) {
|
||||
throw new IllegalStateException( "EmbeddableValuedModelPart not known yet" );
|
||||
}
|
||||
|
||||
final EmbeddableMappingType embeddable = mappingModelPart().getEmbeddableTypeDescriptor();
|
||||
for ( int i = 0; i < embeddable.getAttributeMappings().size(); i++ ) {
|
||||
final AttributeMapping attributeMapping = embeddable.getAttributeMapping( i );
|
||||
final Getter getter = attributeMapping.getPropertyAccess().getGetter();
|
||||
final Method getterMethod = getter.getMethod();
|
||||
if ( getterMethod != null && getterMethod.equals( method ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ public class BasicCriteriaUsageTest extends BaseEntityManagerFunctionalTestCase
|
|||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-8283")
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public void testDateCompositeCustomType() {
|
||||
Payment payment = new Payment();
|
||||
|
|
|
@ -17,7 +17,7 @@ import jakarta.persistence.Entity;
|
|||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Table(name = "persons")
|
||||
@Table(name = "people")
|
||||
//tag::embeddable-instantiator-class[]
|
||||
@Entity
|
||||
public class Person {
|
||||
|
|
|
@ -20,7 +20,7 @@ import jakarta.persistence.Id;
|
|||
import jakarta.persistence.Table;
|
||||
|
||||
|
||||
@Table(name = "persons")
|
||||
@Table(name = "people")
|
||||
//tag::embeddable-instantiator-property[]
|
||||
@Entity
|
||||
public class Person {
|
||||
|
|
|
@ -28,15 +28,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
@DomainModel( annotatedClasses = { Person.class, NameImpl.class } )
|
||||
@SessionFactory
|
||||
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" )
|
||||
@JiraKey( "HHH-14950" )
|
||||
public class InstantiationTests {
|
||||
|
||||
// these tests fail the build even though they are marked @FailureExpected because the
|
||||
// failure happens while creating the test "fixtures" (here the boot model) which JUnit
|
||||
// does not like
|
||||
|
||||
// @Test
|
||||
@Test
|
||||
public void modelTest(DomainModelScope scope) {
|
||||
scope.withHierarchy( Person.class, (personMapping) -> {
|
||||
final Property name = personMapping.getProperty( "name" );
|
||||
|
@ -49,7 +43,8 @@ public class InstantiationTests {
|
|||
});
|
||||
}
|
||||
|
||||
// @Test
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" )
|
||||
public void basicTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
final Person mick = new Person( 1, new NameImpl( "Mick", "Jagger" ) );
|
||||
|
|
|
@ -20,9 +20,8 @@ import jakarta.persistence.Id;
|
|||
import jakarta.persistence.Table;
|
||||
|
||||
|
||||
@Table(name = "persons")
|
||||
//tag::embeddable-instantiator-property[]
|
||||
@Entity
|
||||
@Table(name = "people")
|
||||
public class Person {
|
||||
@Id
|
||||
public Integer id;
|
||||
|
@ -38,8 +37,6 @@ public class Person {
|
|||
@Access( AccessType.PROPERTY )
|
||||
public Set<Name> aliases;
|
||||
|
||||
//end::embeddable-instantiator-property[]
|
||||
|
||||
private Person() {
|
||||
// for Hibernate use
|
||||
}
|
||||
|
@ -80,6 +77,4 @@ public class Person {
|
|||
aliases.add( alias );
|
||||
}
|
||||
|
||||
//tag::embeddable-instantiator-property[]
|
||||
}
|
||||
//end::embeddable-instantiator-property[]
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Creating a new version of {@link InstantiationTests} that won't fail the build,
|
||||
* but still allows us to test the behavior.
|
||||
*
|
||||
* JUnit does not like when build fixtures (here, the SF) fails
|
||||
*/
|
||||
@ServiceRegistry
|
||||
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" )
|
||||
@JiraKey( "HHH-14950" )
|
||||
public class TempInstantiationTests {
|
||||
@Test
|
||||
public void basicTest(ServiceRegistryScope registerScope) {
|
||||
final MetadataSources metadataSources = new MetadataSources( registerScope.getRegistry() )
|
||||
.addAnnotatedClass( Person.class )
|
||||
.addAnnotatedClass( Name.class )
|
||||
.addAnnotatedClass( NameImpl.class );
|
||||
|
||||
final Metadata metadata = metadataSources.buildMetadata();
|
||||
|
||||
final PersistentClass personMapping = metadata.getEntityBinding( Person.class.getName() );
|
||||
|
||||
final Property name = personMapping.getProperty( "name" );
|
||||
final Component nameMapping = (Component) name.getValue();
|
||||
assertThat( nameMapping.getPropertySpan() ).isEqualTo( 2 );
|
||||
|
||||
final Property aliases = personMapping.getProperty( "aliases" );
|
||||
final Component aliasMapping = (Component) ( (Collection) aliases.getValue() ).getElement();
|
||||
assertThat( aliasMapping.getPropertySpan() ).isEqualTo( 2 );
|
||||
}
|
||||
}
|
|
@ -14,8 +14,8 @@ import org.hibernate.testing.orm.junit.DomainModel;
|
|||
import org.hibernate.testing.orm.junit.DomainModelScope;
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.NotImplementedYet;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -23,7 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
/**
|
||||
* A "baseline" test for {@link org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf.InstantiationTests}.
|
||||
*
|
||||
* There we have try to map an interface as an embeddable.
|
||||
* There, we try to map an interface as an embeddable.
|
||||
*
|
||||
* Here we try to map a class that only defines getters to mimic a typical interface.
|
||||
*
|
||||
|
@ -31,15 +31,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
@DomainModel( annotatedClasses = { Person.class, Name.class } )
|
||||
@SessionFactory
|
||||
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" )
|
||||
@JiraKey( "HHH-14950" )
|
||||
public class InstantiationTests {
|
||||
|
||||
// these tests fail the build even though they are marked @FailureExpected because the
|
||||
// failure happens while creating the test "fixtures" (here the boot model) which JUnit
|
||||
// does not like
|
||||
|
||||
// @Test
|
||||
@Test
|
||||
public void modelTest(DomainModelScope scope) {
|
||||
scope.withHierarchy( Person.class, (personMapping) -> {
|
||||
final Property name = personMapping.getProperty( "name" );
|
||||
|
@ -52,4 +46,28 @@ public class InstantiationTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" )
|
||||
public void basicTest(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
final Person mick = new Person( 1, Name.make( "Mick", "Jagger" ) );
|
||||
session.persist( mick );
|
||||
|
||||
final Person john = new Person( 2, Name.make( "John", "Doe" ) );
|
||||
john.addAlias( Name.make( "Jon", "Doe" ) );
|
||||
session.persist( john );
|
||||
} );
|
||||
scope.inTransaction( (session) -> {
|
||||
final Person mick = session.createQuery( "from Person where id = 1", Person.class ).uniqueResult();
|
||||
assertThat( mick.getName().getFirstName() ).isEqualTo( "Mick" );
|
||||
} );
|
||||
scope.inTransaction( (session) -> {
|
||||
final Person john = session.createQuery( "from Person p join fetch p.aliases where p.id = 2", Person.class ).uniqueResult();
|
||||
assertThat( john.getName().getFirstName() ).isEqualTo( "John" );
|
||||
assertThat( john.getAliases() ).hasSize( 1 );
|
||||
final Name alias = john.getAliases().iterator().next();
|
||||
assertThat( alias.getFirstName() ).isEqualTo( "Jon" );
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,18 @@ package org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf2;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Name {
|
||||
private final String first;
|
||||
private final String last;
|
||||
|
||||
public static Name make(String first, String last) {
|
||||
return new Name( first, last );
|
||||
}
|
||||
|
||||
private Name(String first, String last) {
|
||||
this.first = first;
|
||||
this.last = last;
|
||||
}
|
||||
|
||||
String getFirstName() {
|
||||
return "John";
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ import org.hibernate.metamodel.EmbeddableInstantiator;
|
|||
public class NameInstantiator implements EmbeddableInstantiator {
|
||||
@Override
|
||||
public Object instantiate(Supplier<Object[]> valuesAccess, SessionFactoryImplementor sessionFactory) {
|
||||
return new Name();
|
||||
final Object[] values = valuesAccess.get();
|
||||
return Name.make( (String) values[0], (String) values[1] );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,9 +20,8 @@ import jakarta.persistence.Id;
|
|||
import jakarta.persistence.Table;
|
||||
|
||||
|
||||
@Table(name = "persons")
|
||||
//tag::embeddable-instantiator-property[]
|
||||
@Entity
|
||||
@Table(name = "people")
|
||||
public class Person {
|
||||
@Id
|
||||
public Integer id;
|
||||
|
@ -38,8 +37,6 @@ public class Person {
|
|||
@Access( AccessType.PROPERTY )
|
||||
public Set<Name> aliases;
|
||||
|
||||
//end::embeddable-instantiator-property[]
|
||||
|
||||
private Person() {
|
||||
// for Hibernate use
|
||||
}
|
||||
|
@ -80,6 +77,5 @@ public class Person {
|
|||
aliases.add( alias );
|
||||
}
|
||||
|
||||
//tag::embeddable-instantiator-property[]
|
||||
}
|
||||
//end::embeddable-instantiator-property[]
|
||||
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf2;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
|
||||
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Creating a new version of {@link InstantiationTests} that won't fail the build,
|
||||
* but still allows us to test the behavior.
|
||||
*
|
||||
* JUnit does not like when build fixtures (here, the SF) fails
|
||||
*/
|
||||
@ServiceRegistry
|
||||
@FailureExpected( jiraKey = "HHH-14950", reason = "Model has no setters, which is not supported" )
|
||||
@JiraKey( "HHH-14950" )
|
||||
public class TempInstantiationTests {
|
||||
@Test
|
||||
public void basicTest(ServiceRegistryScope registerScope) {
|
||||
final MetadataSources metadataSources = new MetadataSources( registerScope.getRegistry() )
|
||||
.addAnnotatedClass( org.hibernate.orm.test.mapping.embeddable.strategy.instantiator.intf.Person.class )
|
||||
.addAnnotatedClass( Name.class );
|
||||
|
||||
final Metadata metadata = metadataSources.buildMetadata();
|
||||
|
||||
final PersistentClass personMapping = metadata.getEntityBinding( Person.class.getName() );
|
||||
|
||||
final Property name = personMapping.getProperty( "name" );
|
||||
final Component nameMapping = (Component) name.getValue();
|
||||
assertThat( nameMapping.getPropertySpan() ).isEqualTo( 2 );
|
||||
|
||||
final Property aliases = personMapping.getProperty( "aliases" );
|
||||
final Component aliasMapping = (Component) ( (Collection) aliases.getValue() ).getElement();
|
||||
assertThat( aliasMapping.getPropertySpan() ).isEqualTo( 2 );
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ import org.junit.Ignore;
|
|||
* @author Max Rydahl Andersen
|
||||
*/
|
||||
@RequiresDialect( DB2Dialect.class )
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public class DB2CustomSQLTest extends CustomStoredProcTestSupport {
|
||||
public String[] getMappings() {
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.junit.Ignore;
|
|||
* @author Andrea Boriero
|
||||
*/
|
||||
@RequiresDialect(DerbyDialect.class)
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public class DerbyCustomSQLTest extends CustomStoredProcTestSupport {
|
||||
public String[] getMappings() {
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.junit.Ignore;
|
|||
* @author Gavin King
|
||||
*/
|
||||
@RequiresDialect( MySQLDialect.class )
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public class MySQLCustomSQLTest extends CustomStoredProcTestSupport {
|
||||
public String[] getMappings() {
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.junit.Ignore;
|
|||
* @author Gavin King
|
||||
*/
|
||||
@RequiresDialect( OracleDialect.class )
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public class OracleCustomSQLTest extends CustomStoredProcTestSupport {
|
||||
public String[] getMappings() {
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.junit.Ignore;
|
|||
* @author Gail Badner
|
||||
*/
|
||||
@RequiresDialect( SQLServerDialect.class )
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public class SQLServerCustomSQLTest extends CustomStoredProcTestSupport {
|
||||
public String[] getMappings() {
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.junit.Ignore;
|
|||
* @author Gavin King
|
||||
*/
|
||||
@RequiresDialect( { SybaseDialect.class })
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
@Ignore( "Missing support for composite user types" )
|
||||
public class SybaseCustomSQLTest extends CustomStoredProcTestSupport {
|
||||
public String[] getMappings() {
|
||||
|
|
|
@ -75,7 +75,7 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||
xmlMappings = {"org/hibernate/orm/test/sql/hand/query/NativeSQLQueries.hbm.xml"}
|
||||
)
|
||||
@SessionFactory
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom ComponentTuplizer/Instantiator
|
||||
// todo (6.0): needs a composite user type mechanism e.g. by providing a custom embeddable strategy or istantiator
|
||||
public class NativeSQLQueriesTest {
|
||||
|
||||
protected String getOrganizationFetchJoinEmploymentSQL() {
|
||||
|
|
|
@ -22,8 +22,6 @@ final class StaticClassLists {
|
|||
//The CoreMessageLogger is sometimes looked up without it necessarily being a field, so we're
|
||||
//not processing it the same way as other Logger lookups.
|
||||
org.hibernate.internal.CoreMessageLogger_$logger.class,
|
||||
org.hibernate.tuple.component.PojoComponentTuplizer.class,
|
||||
org.hibernate.tuple.component.DynamicMapComponentTuplizer.class,
|
||||
org.hibernate.tuple.entity.DynamicMapEntityTuplizer.class,
|
||||
org.hibernate.persister.collection.OneToManyPersister.class,
|
||||
org.hibernate.persister.collection.BasicCollectionPersister.class,
|
||||
|
|
Loading…
Reference in New Issue