HHH-7919 : Miscellaneous bugfixes

This commit is contained in:
Strong Liu 2013-07-18 02:12:26 +08:00
parent 21c3a17d4c
commit da40234ab7
22 changed files with 839 additions and 886 deletions

View File

@ -45,6 +45,7 @@ public interface Mapping {
*
* @deprecated temporary solution
*/
@Deprecated
public IdentifierGeneratorFactory getIdentifierGeneratorFactory();
public Type getIdentifierType(String className) throws MappingException;
public String getIdentifierPropertyName(String className) throws MappingException;

View File

@ -95,7 +95,7 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
@Override
public IdentifierSource getIdentifierSource() {
if ( entityElement().getId() == null && entityElement().getCompositeId() == null ) {
throw new AssertionFailure(
throw makeMappingException(
String.format( "Entity [%s] did not define an identifier", getEntityName() )
);
}

View File

@ -675,6 +675,7 @@ public interface EntityPersister extends OptimisticCacheSource, EntityDefinition
* @deprecated Use {@link #getIdentifier(Object,SessionImplementor)} instead
*/
@SuppressWarnings( {"JavaDoc"})
@Deprecated
public Serializable getIdentifier(Object object) throws HibernateException;
/**

View File

@ -57,9 +57,7 @@ public class ComponentMetamodel implements Serializable {
private final int propertySpan;
private final Map<String,Integer> propertyIndexes = new HashMap<String,Integer>();
// public ComponentMetamodel(Component component, SessionFactoryImplementor sessionFactory) {
public ComponentMetamodel(Component component) {
// this.sessionFactory = sessionFactory;
this.isKey = component.isKey();
propertySpan = component.getPropertySpan();
properties = new StandardProperty[propertySpan];

View File

@ -402,14 +402,14 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
this.virtualIdComponent = virtualIdComponent;
this.mappedIdentifierType = mappedIdentifierType;
}
@Override
public Object getIdentifier(Object entity, EntityMode entityMode, SessionImplementor session) {
Object id = mappedIdentifierType.instantiate( entityMode );
final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity, entityMode );
mappedIdentifierType.setPropertyValues( id, propertyValues, entityMode );
return id;
}
@Override
public void setIdentifier(Object entity, Serializable id, EntityMode entityMode, SessionImplementor session) {
virtualIdComponent.setPropertyValues(
entity,
@ -427,7 +427,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
this.virtualIdComponent = virtualIdComponent;
this.mappedIdentifierType = mappedIdentifierType;
}
@Override
public Object getIdentifier(Object entity, EntityMode entityMode, SessionImplementor session) {
final Object id = mappedIdentifierType.instantiate( entityMode );
final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity, entityMode );
@ -478,7 +478,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
mappedIdentifierType.setPropertyValues( id, propertyValues, entityMode );
return id;
}
@Override
public void setIdentifier(Object entity, Serializable id, EntityMode entityMode, SessionImplementor session) {
final Object[] extractedValues = mappedIdentifierType.getPropertyValues( id, entityMode );
final Object[] injectionValues = new Object[ extractedValues.length ];
@ -521,9 +521,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
.getEventListenerGroup( EventType.PERSIST )
.listeners();
}
/**
* {@inheritDoc}
*/
@Override
public void resetIdentifier(
Object entity,
Serializable currentId,
@ -548,7 +546,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
}
}
@Override
public Object getVersion(Object entity) throws HibernateException {
if ( !entityMetamodel.isVersioned() ) return null;
return getters[ entityMetamodel.getVersionPropertyIndex() ].get( entity );
@ -557,7 +555,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
protected boolean shouldGetAllProperties(Object entity) {
return !hasUninitializedLazyProperties( entity );
}
@Override
public Object[] getPropertyValues(Object entity) throws HibernateException {
boolean getAll = shouldGetAllProperties( entity );
final int span = entityMetamodel.getPropertySpan();
@ -574,7 +572,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
return result;
}
@Override
public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap, SessionImplementor session)
throws HibernateException {
final int span = entityMetamodel.getPropertySpan();
@ -585,11 +583,11 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
return result;
}
@Override
public Object getPropertyValue(Object entity, int i) throws HibernateException {
return getters[i].get( entity );
}
@Override
public Object getPropertyValue(Object entity, String propertyPath) throws HibernateException {
int loc = propertyPath.indexOf('.');
String basePropertyName = loc > 0
@ -670,7 +668,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
throw new MappingException( "component property not found: " + subPropertyName );
}
@Override
public void setPropertyValues(Object entity, Object[] values) throws HibernateException {
boolean setAll = !entityMetamodel.hasLazyProperties();
@ -680,15 +678,15 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
}
}
@Override
public void setPropertyValue(Object entity, int i, Object value) throws HibernateException {
setters[i].set( entity, value, getFactory() );
}
@Override
public void setPropertyValue(Object entity, String propertyName, Object value) throws HibernateException {
setters[ entityMetamodel.getPropertyIndex( propertyName ) ].set( entity, value, getFactory() );
}
@Override
public final Object instantiate(Serializable id, SessionImplementor session) {
Object result = getInstantiator().instantiate( id );
if ( id != null ) {
@ -696,31 +694,31 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
return result;
}
@Override
public final Object instantiate() throws HibernateException {
return instantiate( null, null );
}
@Override
public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched, SessionImplementor session) {}
@Override
public boolean hasUninitializedLazyProperties(Object entity) {
// the default is to simply not lazy fetch properties for now...
return false;
}
@Override
public final boolean isInstance(Object object) {
return getInstantiator().isInstance( object );
}
@Override
public boolean hasProxy() {
return entityMetamodel.isLazy();
}
@Override
public final Object createProxy(Serializable id, SessionImplementor session)
throws HibernateException {
return getProxyFactory().getProxy( id, session );
}
@Override
public boolean isLifecycleImplementor() {
return false;
}
@ -745,18 +743,18 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
public String toString() {
return getClass().getName() + '(' + getEntityMetamodel().getName() + ')';
}
@Override
public Getter getIdentifierGetter() {
return idGetter;
}
@Override
public Getter getVersionGetter() {
if ( getEntityMetamodel().isVersioned() ) {
return getGetter( getEntityMetamodel().getVersionPropertyIndex() );
}
return null;
}
@Override
public Getter getGetter(int i) {
return getters[i];
}

View File

@ -64,9 +64,7 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
super(entityMetamodel, mappedEntity);
}
/**
* {@inheritDoc}
*/
@Override
public EntityMode getEntityMode() {
return EntityMode.MAP;
}
@ -87,33 +85,21 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
}
}
/**
* {@inheritDoc}
*/
@Override
protected Getter buildPropertyGetter(Property mappedProperty, PersistentClass mappedEntity) {
return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getName() );
}
/**
* {@inheritDoc}
*/
@Override
protected Setter buildPropertySetter(Property mappedProperty, PersistentClass mappedEntity) {
return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getName() );
}
/**
* {@inheritDoc}
*/
@Override
protected Instantiator buildInstantiator(PersistentClass mappingInfo) {
return new DynamicMapInstantiator( mappingInfo );
}
/**
* {@inheritDoc}
*/
@Override
protected ProxyFactory buildProxyFactory(PersistentClass mappingInfo, Getter idGetter, Setter idSetter) {
@ -136,33 +122,21 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
return pf;
}
/**
* {@inheritDoc}
*/
@Override
protected Getter buildPropertyGetter(AttributeBinding mappedProperty) {
return buildPropertyAccessor(mappedProperty).getGetter( null, mappedProperty.getAttribute().getName() );
}
/**
* {@inheritDoc}
*/
@Override
protected Setter buildPropertySetter(AttributeBinding mappedProperty) {
return buildPropertyAccessor(mappedProperty).getSetter( null, mappedProperty.getAttribute().getName() );
}
/**
* {@inheritDoc}
*/
@Override
protected Instantiator buildInstantiator(EntityBinding mappingInfo) {
return new DynamicMapInstantiator( mappingInfo );
}
/**
* {@inheritDoc}
*/
@Override
protected ProxyFactory buildProxyFactory(EntityBinding mappingInfo, Getter idGetter, Setter idSetter) {
@ -185,37 +159,27 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
return pf;
}
/**
* {@inheritDoc}
*/
@Override
public Class getMappedClass() {
return Map.class;
}
/**
* {@inheritDoc}
*/
@Override
public Class getConcreteProxyClass() {
return Map.class;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isInstrumented() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public EntityNameResolver[] getEntityNameResolvers() {
return new EntityNameResolver[] { BasicEntityNameResolver.INSTANCE };
}
/**
* {@inheritDoc}
*/
@Override
public String determineConcreteSubclassEntityName(Object entityInstance, SessionFactoryImplementor factory) {
return extractEmbeddedEntityName( ( Map ) entityInstance );
}
@ -227,9 +191,7 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
public static class BasicEntityNameResolver implements EntityNameResolver {
public static final BasicEntityNameResolver INSTANCE = new BasicEntityNameResolver();
/**
* {@inheritDoc}
*/
@Override
public String resolveEntityName(Object entity) {
if ( ! Map.class.isInstance( entity ) ) {
return null;
@ -241,17 +203,11 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer {
return entityName;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
return getClass().equals( obj.getClass() );
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return getClass().hashCode();

View File

@ -51,6 +51,7 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
* @author Steve Ebersole
* @author Brett Meyer
*/
@SuppressWarnings("unchecked")
public abstract class AbstractStandardBasicType<T>
implements BasicType, StringRepresentableType<T>, ProcedureParameterExtractionAware<T> {
@ -70,11 +71,11 @@ public abstract class AbstractStandardBasicType<T>
public T fromString(String string) {
return javaTypeDescriptor.fromString( string );
}
@Override
public String toString(T value) {
return javaTypeDescriptor.toString( value );
}
@Override
public T fromStringValue(String xml) throws HibernateException {
return fromString( xml );
}
@ -94,11 +95,11 @@ public abstract class AbstractStandardBasicType<T>
return deepCopy( original );
}
}
@Override
public boolean[] toColumnNullness(Object value, Mapping mapping) {
return value == null ? ArrayHelper.FALSE : ArrayHelper.TRUE;
}
@Override
public String[] getRegistrationKeys() {
return registerUnderJavaType()
? new String[] { getName(), javaTypeDescriptor.getJavaTypeClass().getName() }
@ -134,15 +135,15 @@ public abstract class AbstractStandardBasicType<T>
public final void setSqlTypeDescriptor( SqlTypeDescriptor sqlTypeDescriptor ) {
this.sqlTypeDescriptor = sqlTypeDescriptor;
}
@Override
public final Class getReturnedClass() {
return javaTypeDescriptor.getJavaTypeClass();
}
@Override
public final int getColumnSpan(Mapping mapping) throws MappingException {
return sqlTypes( mapping ).length;
}
@Override
public final int[] sqlTypes(Mapping mapping) throws MappingException {
return new int[] { sqlTypeDescriptor.getSqlType() };
}
@ -156,60 +157,60 @@ public abstract class AbstractStandardBasicType<T>
public Size[] defaultSizes(Mapping mapping) throws MappingException {
return new Size[] { getDefaultSize() };
}
@Override
public final boolean isAssociationType() {
return false;
}
@Override
public final boolean isCollectionType() {
return false;
}
@Override
public final boolean isComponentType() {
return false;
}
@Override
public final boolean isEntityType() {
return false;
}
@Override
public final boolean isAnyType() {
return false;
}
@SuppressWarnings({ "unchecked" })
@Override
public final boolean isSame(Object x, Object y) {
return isEqual( x, y );
}
@SuppressWarnings({ "unchecked" })
@Override
public final boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) {
return isEqual( x, y );
}
@SuppressWarnings({ "unchecked" })
@Override
public final boolean isEqual(Object one, Object another) {
return javaTypeDescriptor.areEqual( (T) one, (T) another );
}
@SuppressWarnings({ "unchecked" })
@Override
public final int getHashCode(Object x) {
return javaTypeDescriptor.extractHashCode( (T) x );
}
@Override
public final int getHashCode(Object x, SessionFactoryImplementor factory) {
return getHashCode( x );
}
@SuppressWarnings({ "unchecked" })
@Override
public final int compare(Object x, Object y) {
return javaTypeDescriptor.getComparator().compare( (T) x, (T) y );
}
@Override
public final boolean isDirty(Object old, Object current, SessionImplementor session) {
return isDirty( old, current );
}
@Override
public final boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session) {
return checkable[0] && isDirty( old, current );
}
@ -217,7 +218,7 @@ public abstract class AbstractStandardBasicType<T>
protected final boolean isDirty(Object old, Object current) {
return !isSame( old, current );
}
@Override
public final boolean isModified(
Object oldHydratedState,
Object currentState,
@ -225,7 +226,7 @@ public abstract class AbstractStandardBasicType<T>
SessionImplementor session) {
return isDirty( oldHydratedState, currentState );
}
@Override
public final Object nullSafeGet(
ResultSet rs,
String[] names,
@ -233,7 +234,7 @@ public abstract class AbstractStandardBasicType<T>
Object owner) throws SQLException {
return nullSafeGet( rs, names[0], session );
}
@Override
public final Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
throws SQLException {
return nullSafeGet( rs, name, session );
@ -252,7 +253,7 @@ public abstract class AbstractStandardBasicType<T>
return nullSafeGet( rs, name, session );
}
@SuppressWarnings({ "unchecked" })
@Override
public final void nullSafeSet(
PreparedStatement st,
Object value,
@ -262,7 +263,6 @@ public abstract class AbstractStandardBasicType<T>
nullSafeSet( st, value, index, options );
}
@SuppressWarnings({ "unchecked" })
protected final void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
remapSqlTypeDescriptor( options ).getBinder( javaTypeDescriptor ).bind( st, (T) value, index, options );
}
@ -275,16 +275,16 @@ public abstract class AbstractStandardBasicType<T>
nullSafeSet( st, value, index, session );
}
@SuppressWarnings({ "unchecked" })
@Override
public final String toLoggableString(Object value, SessionFactoryImplementor factory) {
return javaTypeDescriptor.extractLoggableRepresentation( (T) value );
}
@Override
public final boolean isMutable() {
return getMutabilityPlan().isMutable();
}
@SuppressWarnings({ "unchecked" })
@Override
public final Object deepCopy(Object value, SessionFactoryImplementor factory) {
return deepCopy( (T) value );
}
@ -293,41 +293,41 @@ public abstract class AbstractStandardBasicType<T>
return getMutabilityPlan().deepCopy( value );
}
@SuppressWarnings({ "unchecked" })
@Override
public final Serializable disassemble(Object value, SessionImplementor session, Object owner) throws HibernateException {
return getMutabilityPlan().disassemble( (T) value );
}
@Override
public final Object assemble(Serializable cached, SessionImplementor session, Object owner) throws HibernateException {
return getMutabilityPlan().assemble( cached );
}
@Override
public final void beforeAssemble(Serializable cached, SessionImplementor session) {
}
@Override
public final Object hydrate(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return nullSafeGet( rs, names, session, owner );
}
@Override
public final Object resolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
return value;
}
@Override
public final Object semiResolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
return value;
}
@Override
public final Type getSemiResolvedType(SessionFactoryImplementor factory) {
return this;
}
@SuppressWarnings({ "unchecked" })
@Override
public final Object replace(Object original, Object target, SessionImplementor session, Object owner, Map copyCache) {
return getReplacement( (T) original, (T) target, session );
}
@SuppressWarnings({ "unchecked" })
@Override
public Object replace(
Object original,
Object target,
@ -364,15 +364,16 @@ public abstract class AbstractStandardBasicType<T>
// TODO : have SessionImplementor extend WrapperOptions
private WrapperOptions getOptions(final SessionImplementor session) {
return new WrapperOptions() {
@Override
public boolean useStreamForLobBinding() {
return Environment.useStreamsForBinary()
|| session.getFactory().getDialect().useInputStreamToInsertBlob();
}
@Override
public LobCreator getLobCreator() {
return Hibernate.getLobCreator( session );
}
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
final SqlTypeDescriptor remapped = sqlTypeDescriptor.canBeRemapped()
? session.getFactory().getDialect().remapSqlTypeDescriptor( sqlTypeDescriptor )

View File

@ -61,43 +61,43 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
this.identifierType = identifierType;
this.metaType = metaType;
}
@Override
public Object deepCopy(Object value, SessionFactoryImplementor factory)
throws HibernateException {
return value;
}
@Override
public boolean isMethodOf(Method method) {
return false;
}
@Override
public boolean isSame(Object x, Object y) throws HibernateException {
return x==y;
}
@Override
public int compare(Object x, Object y) {
return 0; //TODO: entities CAN be compared, by PK and entity name, fix this!
}
@Override
public int getColumnSpan(Mapping session)
throws MappingException {
return 2;
}
@Override
public String getName() {
return "object";
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
throw new UnsupportedOperationException("object is a multicolumn type");
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return resolveAny(
@ -106,20 +106,20 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
session
);
}
@Override
public Object hydrate(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
String entityName = (String) metaType.nullSafeGet(rs, names[0], session, owner);
Serializable id = (Serializable) identifierType.nullSafeGet(rs, names[1], session, owner);
return new ObjectTypeCacheEntry(entityName, id);
}
@Override
public Object resolve(Object value, SessionImplementor session, Object owner)
throws HibernateException {
ObjectTypeCacheEntry holder = (ObjectTypeCacheEntry) value;
return resolveAny(holder.entityName, holder.id, session);
}
@Override
public Object semiResolve(Object value, SessionImplementor session, Object owner)
throws HibernateException {
throw new UnsupportedOperationException("any mappings may not form part of a property-ref");
@ -130,12 +130,12 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
return entityName==null || id==null ?
null : session.internalLoad( entityName, id, false, false );
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
nullSafeSet(st, value, index, null, session);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SessionImplementor session)
throws HibernateException, SQLException {
@ -163,11 +163,11 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
identifierType.nullSafeSet(st, id, index+1, idsettable, session);
}
}
@Override
public Class getReturnedClass() {
return Object.class;
}
@Override
public int[] sqlTypes(Mapping mapping) throws MappingException {
return ArrayHelper.join(
metaType.sqlTypes( mapping ),
@ -190,7 +190,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
identifierType.defaultSizes( mapping )
);
}
@Override
public String toLoggableString(Object value, SessionFactoryImplementor factory)
throws HibernateException {
//TODO: terrible implementation!
@ -209,7 +209,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
this.id = id;
}
}
@Override
public Object assemble(
Serializable cached,
SessionImplementor session,
@ -219,7 +219,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
ObjectTypeCacheEntry e = (ObjectTypeCacheEntry) cached;
return e==null ? null : session.internalLoad(e.entityName, e.id, false, false);
}
@Override
public Serializable disassemble(Object value, SessionImplementor session, Object owner)
throws HibernateException {
return value==null ?
@ -231,11 +231,11 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
)
);
}
@Override
public boolean isAnyType() {
return true;
}
@Override
public Object replace(
Object original,
Object target,
@ -261,20 +261,21 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
);
}
}
@Override
public CascadeStyle getCascadeStyle(int i) {
return CascadeStyles.NONE;
}
@Override
public FetchMode getFetchMode(int i) {
return FetchMode.SELECT;
}
private static final String[] PROPERTY_NAMES = new String[] { "class", "id" };
private static final String[] PROPERTY_NAMES = { "class", "id" };
@Override
public String[] getPropertyNames() {
return PROPERTY_NAMES;
}
@Override
public Object getPropertyValue(Object component, int i, SessionImplementor session)
throws HibernateException {
@ -282,7 +283,7 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
session.bestGuessEntityName(component) :
getIdentifier(component, session);
}
@Override
public Object[] getPropertyValues(Object component, SessionImplementor session)
throws HibernateException {
@ -297,43 +298,43 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
return null;
}
}
@Override
public Type[] getSubtypes() {
return new Type[] { metaType, identifierType };
}
@Override
public void setPropertyValues(Object component, Object[] values, EntityMode entityMode)
throws HibernateException {
throw new UnsupportedOperationException();
}
@Override
public Object[] getPropertyValues(Object component, EntityMode entityMode) {
throw new UnsupportedOperationException();
}
@Override
public boolean isComponentType() {
return true;
}
@Override
public ForeignKeyDirection getForeignKeyDirection() {
//return AssociationType.TO_PARENT; //this is better but causes a transient object exception...
return ForeignKeyDirection.FROM_PARENT;
}
@Override
public boolean isAssociationType() {
return true;
}
@Override
public boolean useLHSPrimaryKey() {
return false;
}
@Override
public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) {
throw new UnsupportedOperationException("any types do not have a unique referenced persister");
}
@Override
public boolean isModified(Object old, Object current, boolean[] checkable, SessionImplementor session)
throws HibernateException {
if (current==null) return old!=null;
@ -344,49 +345,46 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
return ( checkable[0] && !holder.entityName.equals( session.bestGuessEntityName(current) ) ) ||
identifierType.isModified(holder.id, getIdentifier(current, session), idcheckable, session);
}
@Override
public String getAssociatedEntityName(SessionFactoryImplementor factory)
throws MappingException {
throw new UnsupportedOperationException("any types do not have a unique referenced persister");
}
@Override
public boolean[] getPropertyNullability() {
return null;
}
@Override
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map<String, Filter> enabledFilters)
throws MappingException {
throw new UnsupportedOperationException();
}
public boolean isReferenceToPrimaryKey() {
return true;
}
@Override
public String getRHSUniqueKeyPropertyName() {
return null;
}
@Override
public String getLHSPropertyName() {
return null;
}
@Override
public boolean isAlwaysDirtyChecked() {
return false;
}
@Override
public boolean[] toColumnNullness(Object value, Mapping mapping) {
boolean[] result = new boolean[ getColumnSpan(mapping) ];
if (value!=null) Arrays.fill(result, true);
return result;
}
@Override
public boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session)
throws HibernateException {
//TODO!!!
return isDirty(old, current, session);
}
@Override
public boolean isEmbedded() {
return false;
}

View File

@ -55,7 +55,6 @@ import org.hibernate.tuple.component.ComponentTuplizer;
*/
public class ComponentType extends AbstractType implements CompositeType, ProcedureParameterExtractionAware {
private final TypeFactory.TypeScope typeScope;
private final String[] propertyNames;
private final Type[] propertyTypes;
private final boolean[] propertyNullability;
@ -68,7 +67,6 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
protected final ComponentTuplizer componentTuplizer;
public ComponentType(TypeFactory.TypeScope typeScope, ComponentMetamodel metamodel) {
this.typeScope = typeScope;
// for now, just "re-flatten" the metamodel since this is temporary stuff anyway (HHH-1907)
this.isKey = metamodel.isKey();
this.propertySpan = metamodel.getPropertySpan();
@ -102,23 +100,34 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
public ComponentTuplizer getComponentTuplizer() {
return componentTuplizer;
}
private transient int columnSpan = Integer.MIN_VALUE;
@Override
public int getColumnSpan(Mapping mapping) throws MappingException {
int span = 0;
for ( int i = 0; i < propertySpan; i++ ) {
span += propertyTypes[i].getColumnSpan( mapping );
if ( columnSpan == Integer.MIN_VALUE ) {
int span = 0;
for ( int i = 0; i < propertySpan; i++ ) {
span += propertyTypes[i].getColumnSpan( mapping );
}
columnSpan = span;
}
return span;
return columnSpan;
}
private transient int[] sqlTypes;
@Override
public int[] sqlTypes(Mapping mapping) throws MappingException {
//Not called at runtime so doesn't matter if its slow :)
int[] sqlTypes = new int[getColumnSpan( mapping )];
int n = 0;
for ( int i = 0; i < propertySpan; i++ ) {
int[] subtypes = propertyTypes[i].sqlTypes( mapping );
for ( int subtype : subtypes ) {
sqlTypes[n++] = subtype;
if ( sqlTypes == null ) {
//Not called at runtime so doesn't matter if its slow :)
sqlTypes = new int[getColumnSpan( mapping )];
int n = 0;
for ( int i = 0; i < propertySpan; i++ ) {
int[] subtypes = propertyTypes[i].sqlTypes( mapping );
for ( int subtype : subtypes ) {
sqlTypes[n++] = subtype;
}
}
}
return sqlTypes;
@ -282,7 +291,7 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
}
return false;
}
@Override
public boolean isDirty(Object x, Object y, boolean[] checkable, SessionImplementor session)
throws HibernateException {
if ( x == y ) {

View File

@ -36,15 +36,15 @@ public class EmbeddedComponentType extends ComponentType {
public EmbeddedComponentType(TypeFactory.TypeScope typeScope, ComponentMetamodel metamodel) {
super( typeScope, metamodel );
}
@Override
public boolean isEmbedded() {
return true;
}
@Override
public boolean isMethodOf(Method method) {
return componentTuplizer.isMethodOf( method );
}
@Override
public Object instantiate(Object parent, SessionImplementor session) throws HibernateException {
final boolean useParent = parent!=null &&
//TODO: Yuck! This is not quite good enough, it's a quick

View File

@ -139,6 +139,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
*
* @return True.
*/
@Override
public boolean isAssociationType() {
return true;
}
@ -148,13 +149,12 @@ public abstract class EntityType extends AbstractType implements AssociationType
*
* @return True.
*/
@Override
public final boolean isEntityType() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isMutable() {
return false;
}
@ -164,6 +164,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
*
* @return string rep
*/
@Override
public String toString() {
return getClass().getName() + '(' + getAssociatedEntityName() + ')';
}
@ -171,6 +172,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
/**
* For entity types, the name correlates to the associated entity name.
*/
@Override
public String getName() {
return associatedEntityName;
}
@ -184,13 +186,13 @@ public abstract class EntityType extends AbstractType implements AssociationType
public boolean isReferenceToPrimaryKey() {
return referenceToPrimaryKey;
}
@Override
public String getRHSUniqueKeyPropertyName() {
// Return null if this type references a PK. This is important for
// associations' use of mappedBy referring to a derived ID.
return referenceToPrimaryKey ? null : uniqueKeyPropertyName;
}
@Override
public String getLHSPropertyName() {
return null;
}
@ -214,6 +216,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @param factory The session factory, for resolution.
* @return The associated entity name.
*/
@Override
public String getAssociatedEntityName(SessionFactoryImplementor factory) {
return getAssociatedEntityName();
}
@ -225,6 +228,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @return The associated joinable
* @throws MappingException Generally indicates an invalid entity name.
*/
@Override
public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException {
return ( Joinable ) factory.getEntityPersister( associatedEntityName );
}
@ -237,8 +241,9 @@ public abstract class EntityType extends AbstractType implements AssociationType
* entity persister (nor to the session factory, to look it up) which is really
* needed to "do the right thing" here...
*
* @return The entiyt class.
* @return The entity class.
*/
@Override
public final Class getReturnedClass() {
if ( returnedClass == null ) {
returnedClass = determineAssociatedEntityClass();
@ -257,17 +262,13 @@ public abstract class EntityType extends AbstractType implements AssociationType
}
}
/**
* {@inheritDoc}
*/
@Override
public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return nullSafeGet( rs, new String[] {name}, session, owner );
}
/**
* {@inheritDoc}
*/
@Override
public final Object nullSafeGet(
ResultSet rs,
String[] names,
@ -284,27 +285,22 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @param y Another entity instance
* @return True if x == y; false otherwise.
*/
@Override
public final boolean isSame(Object x, Object y) {
return x == y;
}
/**
* {@inheritDoc}
*/
@Override
public int compare(Object x, Object y) {
return 0; //TODO: entities CAN be compared, by PK, fix this! -> only if/when we can extract the id values....
}
/**
* {@inheritDoc}
*/
@Override
public Object deepCopy(Object value, SessionFactoryImplementor factory) {
return value; //special case ... this is the leaf of the containment graph, even though not immutable
}
/**
* {@inheritDoc}
*/
@Override
public Object replace(
Object original,
Object target,
@ -342,9 +338,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
}
}
/**
* {@inheritDoc}
*/
@Override
public int getHashCode(Object x, SessionFactoryImplementor factory) {
EntityPersister persister = factory.getEntityPersister(associatedEntityName);
if ( !persister.canExtractIdOutOfEntity() ) {
@ -413,7 +407,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
return persister.getIdentifierType()
.isEqual(xid, yid, factory);
}
@Override
public String getOnCondition(String alias, SessionFactoryImplementor factory, Map<String, Filter> enabledFilters)
throws MappingException {
if ( isReferenceToPrimaryKey() ) { //TODO: this is a bit arbitrary, expose a switch to the user?
@ -427,6 +421,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
/**
* Resolve an identifier or unique key value
*/
@Override
public Object resolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
if ( value == null ) {
return null;
@ -445,7 +440,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
return null;
}
@Override
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
return factory.getEntityPersister( associatedEntityName ).getIdentifierType();
}
@ -480,6 +475,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @return The loggable string.
* @throws HibernateException Generally some form of resolution problem.
*/
@Override
public String toLoggableString(Object value, SessionFactoryImplementor factory) {
if ( value == null ) {
return "null";
@ -524,6 +520,9 @@ public abstract class EntityType extends AbstractType implements AssociationType
return isOneToOne();
}
private transient Type identifierType;
private transient Type identifierOrUniqueType;
/**
* Convenience method to locate the identifier type of the associated entity.
*
@ -531,7 +530,10 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @return The identifier type
*/
Type getIdentifierType(Mapping factory) {
return factory.getIdentifierType( getAssociatedEntityName() );
if ( identifierType == null ) {
identifierType = factory.getIdentifierType( getAssociatedEntityName() );
}
return identifierType;
}
/**
@ -555,18 +557,21 @@ public abstract class EntityType extends AbstractType implements AssociationType
* or unique key property name.
*/
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
return getIdentifierType(factory);
}
else {
Type type = factory.getReferencedPropertyType( getAssociatedEntityName(), uniqueKeyPropertyName );
if ( type.isEntityType() ) {
type = ( ( EntityType ) type).getIdentifierOrUniqueKeyType( factory );
if ( identifierOrUniqueType == null ) {
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
identifierOrUniqueType = getIdentifierType( factory );
}
else {
Type type = factory.getReferencedPropertyType( getAssociatedEntityName(), uniqueKeyPropertyName );
if ( type.isEntityType() ) {
type = ( (EntityType) type ).getIdentifierOrUniqueKeyType( factory );
}
identifierOrUniqueType = type;
}
return type;
}
return identifierOrUniqueType;
}
private transient String identifierOrUniquePropertyName;
/**
* The name of the property on the associated entity to which our FK
* refers
@ -575,16 +580,18 @@ public abstract class EntityType extends AbstractType implements AssociationType
* @return The appropriate property name.
* @throws MappingException Generally, if unable to resolve the associated entity name
*/
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
throws MappingException {
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
return factory.getIdentifierPropertyName( getAssociatedEntityName() );
}
else {
return uniqueKeyPropertyName;
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory) throws MappingException {
if ( identifierOrUniquePropertyName == null ) {
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
identifierOrUniquePropertyName = factory.getIdentifierPropertyName( getAssociatedEntityName() );
}
else {
identifierOrUniquePropertyName = uniqueKeyPropertyName;
}
}
return identifierOrUniquePropertyName;
}
protected abstract boolean isNullable();
/**

View File

@ -46,7 +46,7 @@ import org.hibernate.persister.entity.EntityPersister;
*/
public class ManyToOneType extends EntityType {
private final boolean ignoreNotFound;
private boolean isLogicalOneToOne;
private final boolean isLogicalOneToOne;
/**
* Creates a many-to-one association type with the given referenced entity.
@ -113,11 +113,11 @@ public class ManyToOneType extends EntityType {
this.ignoreNotFound = ignoreNotFound;
this.isLogicalOneToOne = isLogicalOneToOne;
}
@Override
protected boolean isNullable() {
return ignoreNotFound;
}
@Override
public boolean isAlwaysDirtyChecked() {
// always need to dirty-check, even when non-updateable;
// this ensures that when the association is updated,
@ -125,20 +125,20 @@ public class ManyToOneType extends EntityType {
// in the cache
return true;
}
@Override
public boolean isOneToOne() {
return false;
}
@Override
public boolean isLogicalOneToOne() {
return isLogicalOneToOne;
}
@Override
public int getColumnSpan(Mapping mapping) throws MappingException {
// our column span is the number of columns in the PK
return getIdentifierOrUniqueKeyType( mapping ).getColumnSpan( mapping );
}
@Override
public int[] sqlTypes(Mapping mapping) throws MappingException {
return getIdentifierOrUniqueKeyType( mapping ).sqlTypes( mapping );
}
@ -152,7 +152,7 @@ public class ManyToOneType extends EntityType {
public Size[] defaultSizes(Mapping mapping) throws MappingException {
return getIdentifierOrUniqueKeyType( mapping ).defaultSizes( mapping );
}
@Override
public void nullSafeSet(
PreparedStatement st,
Object value,
@ -162,7 +162,7 @@ public class ManyToOneType extends EntityType {
getIdentifierOrUniqueKeyType( session.getFactory() )
.nullSafeSet( st, getIdentifier( value, session ), index, settable, session );
}
@Override
public void nullSafeSet(
PreparedStatement st,
Object value,
@ -171,11 +171,11 @@ public class ManyToOneType extends EntityType {
getIdentifierOrUniqueKeyType( session.getFactory() )
.nullSafeSet( st, getIdentifier( value, session ), index, session );
}
@Override
public ForeignKeyDirection getForeignKeyDirection() {
return ForeignKeyDirection.FROM_PARENT;
}
@Override
public Object hydrate(
ResultSet rs,
String[] names,
@ -204,11 +204,11 @@ public class ManyToOneType extends EntityType {
}
}
}
@Override
public boolean useLHSPrimaryKey() {
return false;
}
@Override
public boolean isModified(
Object old,
Object current,
@ -225,7 +225,7 @@ public class ManyToOneType extends EntityType {
return getIdentifierOrUniqueKeyType( session.getFactory() )
.isDirty( old, getIdentifier( current, session ), session );
}
@Override
public Serializable disassemble(
Object value,
SessionImplementor session,
@ -251,7 +251,7 @@ public class ManyToOneType extends EntityType {
return getIdentifierType( session ).disassemble( id, session, owner );
}
}
@Override
public Object assemble(
Serializable oid,
SessionImplementor session,
@ -274,11 +274,11 @@ public class ManyToOneType extends EntityType {
//the owner of the association is not the owner of the id
return ( Serializable ) getIdentifierType( session ).assemble( oid, session, null );
}
@Override
public void beforeAssemble(Serializable oid, SessionImplementor session) {
scheduleBatchLoadIfNeeded( assembleId( oid, session ), session );
}
@Override
public boolean[] toColumnNullness(Object value, Mapping mapping) {
boolean[] result = new boolean[ getColumnSpan( mapping ) ];
if ( value != null ) {
@ -286,7 +286,7 @@ public class ManyToOneType extends EntityType {
}
return result;
}
@Override
public boolean isDirty(
Object old,
Object current,
@ -298,7 +298,7 @@ public class ManyToOneType extends EntityType {
Object newid = getIdentifier( current, session );
return getIdentifierType( session ).isDirty( oldid, newid, session );
}
@Override
public boolean isDirty(
Object old,
Object current,

View File

@ -36,11 +36,11 @@ public class ObjectType extends AnyType implements BasicType {
public ObjectType() {
super( StringType.INSTANCE, SerializableType.INSTANCE );
}
@Override
public String getName() {
return "object";
}
@Override
public String[] getRegistrationKeys() {
return new String[] { getName(), Object.class.getName() };
}

View File

@ -98,11 +98,11 @@ public class OneToOneType extends EntityType {
this.entityName = entityName;
}
@Override
public String getPropertyName() {
return propertyName;
}
@Override
public boolean isNull(Object owner, SessionImplementor session) {
if ( propertyName != null ) {
final EntityPersister ownerPersister = session.getFactory().getEntityPersister( entityName );
@ -114,11 +114,11 @@ public class OneToOneType extends EntityType {
return false;
}
}
@Override
public int getColumnSpan(Mapping session) throws MappingException {
return 0;
}
@Override
public int[] sqlTypes(Mapping session) throws MappingException {
return ArrayHelper.EMPTY_INT_ARRAY;
}
@ -134,39 +134,39 @@ public class OneToOneType extends EntityType {
public Size[] defaultSizes(Mapping mapping) throws MappingException {
return SIZES;
}
@Override
public boolean[] toColumnNullness(Object value, Mapping mapping) {
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SessionImplementor session) {
//nothing to do
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) {
//nothing to do
}
@Override
public boolean isOneToOne() {
return true;
}
@Override
public boolean isDirty(Object old, Object current, SessionImplementor session) {
return false;
}
@Override
public boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session) {
return false;
}
@Override
public boolean isModified(Object old, Object current, boolean[] checkable, SessionImplementor session) {
return false;
}
@Override
public ForeignKeyDirection getForeignKeyDirection() {
return foreignKeyType;
}
@Override
public Object hydrate(
ResultSet rs,
String[] names,
@ -176,20 +176,20 @@ public class OneToOneType extends EntityType {
return session.getContextEntityIdentifier(owner);
}
@Override
protected boolean isNullable() {
return foreignKeyType==ForeignKeyDirection.TO_PARENT;
}
@Override
public boolean useLHSPrimaryKey() {
return true;
}
@Override
public Serializable disassemble(Object value, SessionImplementor session, Object owner)
throws HibernateException {
return null;
}
@Override
public Object assemble(Serializable oid, SessionImplementor session, Object owner)
throws HibernateException {
//this should be a call to resolve(), not resolveIdentifier(),
@ -203,6 +203,7 @@ public class OneToOneType extends EntityType {
* assemble/disassemble is implemented and because a one-to-one
* association is never dirty
*/
@Override
public boolean isAlwaysDirtyChecked() {
//TODO: this is kinda inconsistent with CollectionType
return false;

View File

@ -107,11 +107,11 @@ public class SpecialOneToOneType extends OneToOneType {
);
}
@Override
public int getColumnSpan(Mapping mapping) throws MappingException {
return super.getIdentifierOrUniqueKeyType( mapping ).getColumnSpan( mapping );
}
@Override
public int[] sqlTypes(Mapping mapping) throws MappingException {
return super.getIdentifierOrUniqueKeyType( mapping ).sqlTypes( mapping );
}
@ -125,11 +125,11 @@ public class SpecialOneToOneType extends OneToOneType {
public Size[] defaultSizes(Mapping mapping) throws MappingException {
return super.getIdentifierOrUniqueKeyType( mapping ).defaultSizes( mapping );
}
@Override
public boolean useLHSPrimaryKey() {
return false;
}
@Override
public Object hydrate(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return super.getIdentifierOrUniqueKeyType( session.getFactory() )
@ -137,7 +137,7 @@ public class SpecialOneToOneType extends OneToOneType {
}
// TODO: copy/paste from ManyToOneType
@Override
public Serializable disassemble(Object value, SessionImplementor session, Object owner)
throws HibernateException {
if (value==null) {
@ -156,7 +156,7 @@ public class SpecialOneToOneType extends OneToOneType {
return getIdentifierType(session).disassemble(id, session, owner);
}
}
@Override
public Object assemble(Serializable oid, SessionImplementor session, Object owner)
throws HibernateException {
//TODO: currently broken for unique-key references (does not detect

View File

@ -72,7 +72,7 @@ public final class TypeFactory implements Serializable {
}
this.factory = factory;
}
@Override
public SessionFactoryImplementor resolveFactory() {
if ( factory == null ) {
throw new HibernateException( "SessionFactory for type scoping not yet known" );

View File

@ -74,15 +74,6 @@ public class JdbcTypeNameMapper {
*
* @return {@code true} to indicate the type code is a standard type code; {@code false} otherwise.
*/
public static boolean isStandardTypeCode(int typeCode) {
return isStandardTypeCode( Integer.valueOf( typeCode ) );
}
/**
* Same as call to {@link #isStandardTypeCode(int)}
*
* @see #isStandardTypeCode(int)
*/
public static boolean isStandardTypeCode(Integer typeCode) {
return JDBC_TYPE_MAP.containsKey( typeCode );
}

View File

@ -58,7 +58,7 @@ public class JdbcTypeFamilyInformation {
}
}
private ConcurrentHashMap<Integer,Family> typeCodeToFamilyMap = new ConcurrentHashMap<Integer, Family>();
private final ConcurrentHashMap<Integer,Family> typeCodeToFamilyMap = new ConcurrentHashMap<Integer, Family>();
/**
* Will return {@code null} if no match is found.
@ -68,6 +68,6 @@ public class JdbcTypeFamilyInformation {
* @return The family of datatypes the type code belongs to, or {@code null} if it belongs to no known families.
*/
public Family locateJdbcTypeFamilyByTypeCode(int typeCode) {
return typeCodeToFamilyMap.get( Integer.valueOf( typeCode ) );
return typeCodeToFamilyMap.get( typeCode );
}
}

View File

@ -48,7 +48,7 @@ public class SqlTypeDescriptorRegistry {
private static final Logger log = Logger.getLogger( SqlTypeDescriptorRegistry.class );
private ConcurrentHashMap<Integer,SqlTypeDescriptor> descriptorMap = new ConcurrentHashMap<Integer, SqlTypeDescriptor>();
private final ConcurrentHashMap<Integer,SqlTypeDescriptor> descriptorMap = new ConcurrentHashMap<Integer, SqlTypeDescriptor>();
public void addDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
descriptorMap.put( sqlTypeDescriptor.getSqlType(), sqlTypeDescriptor );
@ -72,7 +72,7 @@ public class SqlTypeDescriptorRegistry {
if ( family != null ) {
for ( int potentialAlternateTypeCode : family.getTypeCodes() ) {
if ( potentialAlternateTypeCode != jdbcTypeCode ) {
final SqlTypeDescriptor potentialAlternateDescriptor = descriptorMap.get( Integer.valueOf( potentialAlternateTypeCode ) );
final SqlTypeDescriptor potentialAlternateDescriptor = descriptorMap.get( potentialAlternateTypeCode );
if ( potentialAlternateDescriptor != null ) {
// todo : add a SqlTypeDescriptor.canBeAssignedFrom method...
return potentialAlternateDescriptor;

View File

@ -66,7 +66,7 @@ import static org.junit.Assert.fail;
* @author Hardy Ferentschik
*/
@SuppressWarnings("unchecked")
//@FailureExpectedWithNewMetamodel
@FailureExpectedWithNewMetamodel
public class OneToManyTest extends BaseCoreFunctionalTestCase {
@Test
public void testColumnDefinitionPropagation() throws Exception {

View File

@ -56,7 +56,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* see {@link SingularIdentifierAttributeSourceImpl} basically, the {@link Details} class doesn't have an 'id' attribute
* it is a virtual attribute, but we need some api to define this, maybe add a method to the {@link org.hibernate.metamodel.spi.source.AttributeSource}
* say "isSynthetic()"
*/
@FailureExpectedWithNewMetamodel
public class MasterDetailTest extends LegacyTestCase {
@Override