HHH-6204 - JoinColumn on non key field fails to populate collection
This commit is contained in:
parent
e813d329bc
commit
f6fc21a133
|
@ -115,6 +115,136 @@ public class BinderHelper {
|
|||
return clone;
|
||||
}
|
||||
|
||||
// This is sooooooooo close in terms of not generating a synthetic property if we do not have to (where property ref
|
||||
// refers to a single property). The sticking point is cases where the `referencedPropertyName` come from subclasses
|
||||
// or secondary tables. Part of the problem is in PersistentClass itself during attempts to resolve the referenced
|
||||
// property; currently it only considers non-subclass and non-joined properties. Part of the problem is in terms
|
||||
// of SQL generation.
|
||||
// public static void createSyntheticPropertyReference(
|
||||
// Ejb3JoinColumn[] columns,
|
||||
// PersistentClass ownerEntity,
|
||||
// PersistentClass associatedEntity,
|
||||
// Value value,
|
||||
// boolean inverse,
|
||||
// Mappings mappings) {
|
||||
// //associated entity only used for more precise exception, yuk!
|
||||
// if ( columns[0].isImplicit() || StringHelper.isNotEmpty( columns[0].getMappedBy() ) ) return;
|
||||
// int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType( columns, ownerEntity, mappings );
|
||||
// PersistentClass associatedClass = columns[0].getPropertyHolder() != null ?
|
||||
// columns[0].getPropertyHolder().getPersistentClass() :
|
||||
// null;
|
||||
// if ( Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum ) {
|
||||
// //find properties associated to a certain column
|
||||
// Object columnOwner = findColumnOwner( ownerEntity, columns[0].getReferencedColumn(), mappings );
|
||||
// List<Property> properties = findPropertiesByColumns( columnOwner, columns, mappings );
|
||||
//
|
||||
// if ( properties == null ) {
|
||||
// //TODO use a ToOne type doing a second select
|
||||
// StringBuilder columnsList = new StringBuilder();
|
||||
// columnsList.append( "referencedColumnNames(" );
|
||||
// for (Ejb3JoinColumn column : columns) {
|
||||
// columnsList.append( column.getReferencedColumn() ).append( ", " );
|
||||
// }
|
||||
// columnsList.setLength( columnsList.length() - 2 );
|
||||
// columnsList.append( ") " );
|
||||
//
|
||||
// if ( associatedEntity != null ) {
|
||||
// //overidden destination
|
||||
// columnsList.append( "of " )
|
||||
// .append( associatedEntity.getEntityName() )
|
||||
// .append( "." )
|
||||
// .append( columns[0].getPropertyName() )
|
||||
// .append( " " );
|
||||
// }
|
||||
// else {
|
||||
// if ( columns[0].getPropertyHolder() != null ) {
|
||||
// columnsList.append( "of " )
|
||||
// .append( columns[0].getPropertyHolder().getEntityName() )
|
||||
// .append( "." )
|
||||
// .append( columns[0].getPropertyName() )
|
||||
// .append( " " );
|
||||
// }
|
||||
// }
|
||||
// columnsList.append( "referencing " )
|
||||
// .append( ownerEntity.getEntityName() )
|
||||
// .append( " not mapped to a single property" );
|
||||
// throw new AnnotationException( columnsList.toString() );
|
||||
// }
|
||||
//
|
||||
// final String referencedPropertyName;
|
||||
//
|
||||
// if ( properties.size() == 1 ) {
|
||||
// referencedPropertyName = properties.get(0).getName();
|
||||
// }
|
||||
// else {
|
||||
// // Create a synthetic (embedded composite) property to use as the referenced property which
|
||||
// // contains all the properties mapped to the referenced columns. We need to make a shallow copy
|
||||
// // of the properties to mark them as non-insertable/updatable.
|
||||
//
|
||||
// // todo : what if the columns all match with an existing component?
|
||||
//
|
||||
// StringBuilder propertyNameBuffer = new StringBuilder( "_" );
|
||||
// propertyNameBuffer.append( associatedClass.getEntityName().replace( '.', '_' ) );
|
||||
// propertyNameBuffer.append( "_" ).append( columns[0].getPropertyName() );
|
||||
// String syntheticPropertyName = propertyNameBuffer.toString();
|
||||
// //create an embeddable component
|
||||
//
|
||||
// //todo how about properties.size() == 1, this should be much simpler
|
||||
// Component embeddedComp = columnOwner instanceof PersistentClass ?
|
||||
// new Component( mappings, (PersistentClass) columnOwner ) :
|
||||
// new Component( mappings, (Join) columnOwner );
|
||||
// embeddedComp.setEmbedded( true );
|
||||
// embeddedComp.setNodeName( syntheticPropertyName );
|
||||
// embeddedComp.setComponentClassName( embeddedComp.getOwner().getClassName() );
|
||||
// for (Property property : properties) {
|
||||
// Property clone = BinderHelper.shallowCopy( property );
|
||||
// clone.setInsertable( false );
|
||||
// clone.setUpdateable( false );
|
||||
// clone.setNaturalIdentifier( false );
|
||||
// clone.setGeneration( property.getGeneration() );
|
||||
// embeddedComp.addProperty( clone );
|
||||
// }
|
||||
// SyntheticProperty synthProp = new SyntheticProperty();
|
||||
// synthProp.setName( syntheticPropertyName );
|
||||
// synthProp.setNodeName( syntheticPropertyName );
|
||||
// synthProp.setPersistentClass( ownerEntity );
|
||||
// synthProp.setUpdateable( false );
|
||||
// synthProp.setInsertable( false );
|
||||
// synthProp.setValue( embeddedComp );
|
||||
// synthProp.setPropertyAccessorName( "embedded" );
|
||||
// ownerEntity.addProperty( synthProp );
|
||||
// //make it unique
|
||||
// TableBinder.createUniqueConstraint( embeddedComp );
|
||||
//
|
||||
// referencedPropertyName = syntheticPropertyName;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * creating the property ref to the new synthetic property
|
||||
// */
|
||||
// if ( value instanceof ToOne ) {
|
||||
// ( (ToOne) value ).setReferencedPropertyName( referencedPropertyName );
|
||||
// mappings.addUniquePropertyReference( ownerEntity.getEntityName(), referencedPropertyName );
|
||||
// }
|
||||
// else if ( value instanceof Collection ) {
|
||||
// ( (Collection) value ).setReferencedPropertyName( referencedPropertyName );
|
||||
// //not unique because we could create a mtm wo association table
|
||||
// mappings.addPropertyReference( ownerEntity.getEntityName(), referencedPropertyName );
|
||||
// }
|
||||
// else {
|
||||
// throw new AssertionFailure(
|
||||
// "Do a property ref on an unexpected Value type: "
|
||||
// + value.getClass().getName()
|
||||
// );
|
||||
// }
|
||||
// mappings.addPropertyReferencedAssociation(
|
||||
// ( inverse ? "inverse__" : "" ) + associatedClass.getEntityName(),
|
||||
// columns[0].getPropertyName(),
|
||||
// referencedPropertyName
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void createSyntheticPropertyReference(
|
||||
Ejb3JoinColumn[] columns,
|
||||
PersistentClass ownerEntity,
|
||||
|
|
|
@ -1008,7 +1008,7 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
else {
|
||||
keyVal = (KeyValue) collValue.getOwner()
|
||||
.getRecursiveProperty( propRef )
|
||||
.getReferencedProperty( propRef )
|
||||
.getValue();
|
||||
}
|
||||
DependantValue key = new DependantValue( mappings, collValue.getCollectionTable(), keyVal );
|
||||
|
|
|
@ -402,7 +402,7 @@ public class TableBinder {
|
|||
"No property ref found while expected"
|
||||
);
|
||||
}
|
||||
Property synthProp = referencedEntity.getRecursiveProperty( referencedPropertyName );
|
||||
Property synthProp = referencedEntity.getReferencedProperty( referencedPropertyName );
|
||||
if ( synthProp == null ) {
|
||||
throw new AssertionFailure(
|
||||
"Cannot find synthProp: " + referencedEntity.getEntityName() + "." + referencedPropertyName
|
||||
|
|
|
@ -76,7 +76,9 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.sql.Select;
|
||||
import org.hibernate.tuple.ElementWrapper;
|
||||
import org.hibernate.type.CollectionType;
|
||||
|
||||
/**
|
||||
* A <strong>stateful</strong> implementation of the {@link PersistenceContext} contract meaning that we maintain this
|
||||
|
@ -775,6 +777,64 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
|||
*/
|
||||
@Override
|
||||
public Object getCollectionOwner(Serializable key, CollectionPersister collectionPersister) throws MappingException {
|
||||
// todo : we really just need to add a split in the notions of:
|
||||
// 1) collection key
|
||||
// 2) collection owner key
|
||||
// these 2 are not always the same. Same is true in the case of ToOne associations with property-ref...
|
||||
final EntityPersister ownerPersister = collectionPersister.getOwnerEntityPersister();
|
||||
if ( ownerPersister.getIdentifierType().getReturnedClass().isInstance( key ) ) {
|
||||
return getEntity( session.generateEntityKey( key, collectionPersister.getOwnerEntityPersister() ) );
|
||||
}
|
||||
|
||||
// we have a property-ref type mapping for the collection key. But that could show up a few ways here...
|
||||
//
|
||||
// 1) The incoming key could be the entity itself...
|
||||
if ( ownerPersister.isInstance( key ) ) {
|
||||
final Serializable owenerId = ownerPersister.getIdentifier( key, session );
|
||||
if ( owenerId == null ) {
|
||||
return null;
|
||||
}
|
||||
return getEntity( session.generateEntityKey( owenerId, ownerPersister ) );
|
||||
}
|
||||
|
||||
final CollectionType collectionType = collectionPersister.getCollectionType();
|
||||
|
||||
// 2) The incoming key is most likely the collection key which we need to resolve to the owner key
|
||||
// find the corresponding owner instance
|
||||
// a) try by EntityUniqueKey
|
||||
if ( collectionType.getLHSPropertyName() != null ) {
|
||||
Object owner = getEntity(
|
||||
new EntityUniqueKey(
|
||||
ownerPersister.getEntityName(),
|
||||
collectionType.getLHSPropertyName(),
|
||||
key,
|
||||
collectionPersister.getKeyType(),
|
||||
ownerPersister.getEntityMode(),
|
||||
session.getFactory()
|
||||
)
|
||||
);
|
||||
if ( owner != null ) {
|
||||
return owner;
|
||||
}
|
||||
|
||||
// b) try by EntityKey, which means we need to resolve owner-key -> collection-key
|
||||
// IMPL NOTE : yes if we get here this impl is very non-performant, but PersistenceContext
|
||||
// was never designed to handle this case; adding that capability for real means splitting
|
||||
// the notions of:
|
||||
// 1) collection key
|
||||
// 2) collection owner key
|
||||
// these 2 are not always the same (same is true in the case of ToOne associations with
|
||||
// property-ref). That would require changes to (at least) CollectionEntry and quite
|
||||
// probably changes to how the sql for collection initializers are generated
|
||||
//
|
||||
// We could also possibly see if the referenced property is a natural id since we already have caching
|
||||
// in place of natural id snapshots. BUt really its better to just do it the right way ^^ if we start
|
||||
// going that route
|
||||
final Serializable ownerId = ownerPersister.getIdByUniqueKey( key, collectionType.getLHSPropertyName(), session );
|
||||
return getEntity( session.generateEntityKey( ownerId, ownerPersister ) );
|
||||
}
|
||||
|
||||
// as a last resort this is what the old code did...
|
||||
return getEntity( session.generateEntityKey( key, collectionPersister.getOwnerEntityPersister() ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -182,6 +182,9 @@ public final class CollectionEntry implements Serializable {
|
|||
}
|
||||
|
||||
public void preFlush(PersistentCollection collection) throws HibernateException {
|
||||
if ( loadedKey == null && collection.getKey() != null ) {
|
||||
loadedKey = collection.getKey();
|
||||
}
|
||||
|
||||
boolean nonMutableChange = collection.isDirty() &&
|
||||
getLoadedPersister()!=null &&
|
||||
|
|
|
@ -72,7 +72,7 @@ public class JoinedSubclass extends Subclass implements TableOwner {
|
|||
public Iterator getReferenceablePropertyIterator() {
|
||||
return getPropertyIterator();
|
||||
}
|
||||
|
||||
|
||||
public Object accept(PersistentClassVisitor mv) {
|
||||
return mv.accept(this);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.PropertyAccessException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.StaleStateException;
|
||||
|
@ -1503,6 +1504,107 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdByUniqueKey(Serializable key, String uniquePropertyName, SessionImplementor session) throws HibernateException {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracef(
|
||||
"resolving unique key [%s] to identifier for entity [%s]",
|
||||
key,
|
||||
getEntityName()
|
||||
);
|
||||
}
|
||||
|
||||
int propertyIndex = getSubclassPropertyIndex( uniquePropertyName );
|
||||
if ( propertyIndex < 0 ) {
|
||||
throw new HibernateException(
|
||||
"Could not determine Type for property [" + uniquePropertyName + "] on entity [" + getEntityName() + "]"
|
||||
);
|
||||
}
|
||||
Type propertyType = getSubclassPropertyType( propertyIndex );
|
||||
|
||||
try {
|
||||
PreparedStatement ps = session.getTransactionCoordinator()
|
||||
.getJdbcCoordinator()
|
||||
.getStatementPreparer()
|
||||
.prepareStatement( generateIdByUniqueKeySelectString( uniquePropertyName ) );
|
||||
try {
|
||||
propertyType.nullSafeSet( ps, key, 1, session );
|
||||
ResultSet rs = ps.executeQuery();
|
||||
try {
|
||||
//if there is no resulting row, return null
|
||||
if ( !rs.next() ) {
|
||||
return null;
|
||||
}
|
||||
return (Serializable) getIdentifierType().nullSafeGet( rs, getIdentifierAliases(), session, null );
|
||||
}
|
||||
finally {
|
||||
rs.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw getFactory().getSQLExceptionHelper().convert(
|
||||
e,
|
||||
String.format(
|
||||
"could not resolve unique property [%s] to identifier for entity [%s]",
|
||||
uniquePropertyName,
|
||||
getEntityName()
|
||||
),
|
||||
getSQLSnapshotSelectString()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String generateIdByUniqueKeySelectString(String uniquePropertyName) {
|
||||
Select select = new Select( getFactory().getDialect() );
|
||||
|
||||
if ( getFactory().getSettings().isCommentsEnabled() ) {
|
||||
select.setComment( "resolve id by unique property [" + getEntityName() + "." + uniquePropertyName + "]" );
|
||||
}
|
||||
|
||||
final String rooAlias = getRootAlias();
|
||||
|
||||
select.setFromClause( fromTableFragment( rooAlias ) + fromJoinFragment( rooAlias, true, false ) );
|
||||
|
||||
SelectFragment selectFragment = new SelectFragment();
|
||||
selectFragment.addColumns( rooAlias, getIdentifierColumnNames(), getIdentifierAliases() );
|
||||
select.setSelectClause( selectFragment );
|
||||
|
||||
StringBuilder whereClauseBuffer = new StringBuilder();
|
||||
final int uniquePropertyIndex = getSubclassPropertyIndex( uniquePropertyName );
|
||||
final String uniquePropertyTableAlias = generateTableAlias(
|
||||
rooAlias,
|
||||
getSubclassPropertyTableNumber( uniquePropertyIndex )
|
||||
);
|
||||
String sep = "";
|
||||
for ( String columnTemplate : getSubclassPropertyColumnReaderTemplateClosure()[uniquePropertyIndex] ) {
|
||||
if ( columnTemplate == null ) {
|
||||
continue;
|
||||
}
|
||||
final String columnReference = StringHelper.replace( columnTemplate, Template.TEMPLATE, uniquePropertyTableAlias );
|
||||
whereClauseBuffer.append( sep ).append( columnReference ).append( "=?" );
|
||||
sep = " and ";
|
||||
}
|
||||
for ( String formulaTemplate : getSubclassPropertyFormulaTemplateClosure()[uniquePropertyIndex] ) {
|
||||
if ( formulaTemplate == null ) {
|
||||
continue;
|
||||
}
|
||||
final String formulaReference = StringHelper.replace( formulaTemplate, Template.TEMPLATE, uniquePropertyTableAlias );
|
||||
whereClauseBuffer.append( sep ).append( formulaReference ).append( "=?" );
|
||||
sep = " and ";
|
||||
}
|
||||
whereClauseBuffer.append( whereJoinFragment( rooAlias, true, false ) );
|
||||
|
||||
select.setWhereClause( whereClauseBuffer.toString() );
|
||||
|
||||
return select.setOuterJoins( "", "" ).toStatementString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the SQL that selects the version number by id
|
||||
*/
|
||||
|
|
|
@ -509,6 +509,8 @@ public interface EntityPersister extends OptimisticCacheSource {
|
|||
public Object[] getDatabaseSnapshot(Serializable id, SessionImplementor session)
|
||||
throws HibernateException;
|
||||
|
||||
public Serializable getIdByUniqueKey(Serializable key, String uniquePropertyName, SessionImplementor session);
|
||||
|
||||
/**
|
||||
* Get the current version of the object, or return null if there is no row for
|
||||
* the given identifier. In the case of unversioned data, return any object
|
||||
|
|
|
@ -151,6 +151,11 @@ public class Select {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Select setSelectClause(SelectFragment selectFragment) {
|
||||
setSelectClause( selectFragment.toFragmentString().substring( 2 ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the whereClause.
|
||||
* @param whereClause The whereClause to set
|
||||
|
@ -204,5 +209,4 @@ public class Select {
|
|||
LockOptions.copy(lockOptions, this.lockOptions);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -420,6 +420,11 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
|||
return new Object[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdByUniqueKey(Serializable key, String uniquePropertyName, SessionImplementor session) {
|
||||
throw new UnsupportedOperationException( "not supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCurrentVersion(Serializable id, SessionImplementor session) throws HibernateException {
|
||||
return null;
|
||||
|
|
|
@ -551,6 +551,11 @@ public class CustomPersister implements EntityPersister {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdByUniqueKey(Serializable key, String uniquePropertyName, SessionImplementor session) {
|
||||
throw new UnsupportedOperationException( "not supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getPropertyVersionability() {
|
||||
return MUTABILITY;
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.propertyref;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.annotations.IndexColumn;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "vgras007_v031")
|
||||
public class DoesNotWork implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@EmbeddedId
|
||||
private DoesNotWorkPk doesNotWorkPk;
|
||||
|
||||
@Column(name = "production_credits_tid", insertable = false, updatable = false)
|
||||
private Long globAdditInfoTid;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(
|
||||
name = "vgras029_v031",
|
||||
joinColumns = @JoinColumn(name = "text_id", referencedColumnName = "production_credits_tid")
|
||||
)
|
||||
@Column(name = "text_part", insertable = false, updatable = false)
|
||||
@IndexColumn(name = "seq_no", base = 1)
|
||||
private List<String> globalNotes = new ArrayList<String>();
|
||||
|
||||
public DoesNotWork() {
|
||||
}
|
||||
|
||||
public DoesNotWork(DoesNotWorkPk doesNotWorkPk) {
|
||||
this.doesNotWorkPk = doesNotWorkPk;
|
||||
}
|
||||
|
||||
public DoesNotWorkPk getDoesNotWorkPk() {
|
||||
return doesNotWorkPk;
|
||||
}
|
||||
|
||||
public void setDoesNotWorkPk(DoesNotWorkPk doesNotWorkPk) {
|
||||
this.doesNotWorkPk = doesNotWorkPk;
|
||||
}
|
||||
|
||||
public List<String> getGlobalNotes() {
|
||||
return globalNotes;
|
||||
}
|
||||
|
||||
public void setGlobalNotes(List<String> globalNotes) {
|
||||
this.globalNotes = globalNotes;
|
||||
}
|
||||
|
||||
public Long getGlobAdditInfoTid() {
|
||||
return globAdditInfoTid;
|
||||
}
|
||||
|
||||
public void setGlobAdditInfoTid(Long globAdditInfoTid) {
|
||||
this.globAdditInfoTid = globAdditInfoTid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((doesNotWorkPk == null) ? 0 : doesNotWorkPk.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( this == obj ) {
|
||||
return true;
|
||||
}
|
||||
if ( obj == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( !(obj instanceof DoesNotWork) ) {
|
||||
return false;
|
||||
}
|
||||
DoesNotWork other = (DoesNotWork) obj;
|
||||
if ( doesNotWorkPk == null ) {
|
||||
if ( other.doesNotWorkPk != null ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( !doesNotWorkPk.equals( other.doesNotWorkPk ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.propertyref;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Embeddable
|
||||
public class DoesNotWorkPk implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "track_no")
|
||||
private String id1;
|
||||
|
||||
@Column(name = "track_ext")
|
||||
private String id2;
|
||||
|
||||
public String getId1() {
|
||||
return id1;
|
||||
}
|
||||
|
||||
public void setId1(String id1) {
|
||||
this.id1 = id1;
|
||||
}
|
||||
|
||||
public String getId2() {
|
||||
return id2;
|
||||
}
|
||||
|
||||
public void setId2(String id2) {
|
||||
this.id2 = id2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((id1 == null) ? 0 : id1.hashCode());
|
||||
result = prime * result + ((id2 == null) ? 0 : id2.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( this == obj ) {
|
||||
return true;
|
||||
}
|
||||
if ( obj == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( !(obj instanceof DoesNotWorkPk) ) {
|
||||
return false;
|
||||
}
|
||||
DoesNotWorkPk other = (DoesNotWorkPk) obj;
|
||||
if ( id1 == null ) {
|
||||
if ( other.id1 != null ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( !id1.equals( other.id1 ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( id2 == null ) {
|
||||
if ( other.id2 != null ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( !id2.equals( other.id2 ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.propertyref;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DoesNotWorkTest extends BaseCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {DoesNotWork.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure( configuration );
|
||||
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
|
||||
configuration.setProperty( AvailableSettings.HBM2DDL_IMPORT_FILES, "/org/hibernate/test/propertyref/import.sql" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIt() {
|
||||
DoesNotWorkPk pk = new DoesNotWorkPk();
|
||||
pk.setId1( "ZZZ" );
|
||||
pk.setId2( "00" );
|
||||
|
||||
// {
|
||||
// Session session = openSession();
|
||||
// session.beginTransaction();
|
||||
// DoesNotWork entity = new DoesNotWork( pk );
|
||||
// entity.setGlobalNotes( Arrays.asList( "My first note!" ) );
|
||||
// session.save( entity );
|
||||
// session.getTransaction().commit();
|
||||
// session.close();
|
||||
// }
|
||||
|
||||
{
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
DoesNotWork entity = (DoesNotWork) session.get( DoesNotWork.class, pk );
|
||||
List<String> notes = entity.getGlobalNotes();
|
||||
if ( notes != null && notes.size() > 0 ) {
|
||||
for ( String s : notes ) {
|
||||
System.out.println( s );
|
||||
}
|
||||
}
|
||||
session.delete( entity );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.propertyref;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DoesNotWorkWithHbmTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected String[] getMappings() {
|
||||
return new String[] { "propertyref/Mapping.hbm.xml" };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure( configuration );
|
||||
configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "false" );
|
||||
configuration.setProperty( AvailableSettings.HBM2DDL_IMPORT_FILES, "/org/hibernate/test/propertyref/import.sql" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIt() {
|
||||
DoesNotWorkPk pk = new DoesNotWorkPk();
|
||||
pk.setId1( "ZZZ" );
|
||||
pk.setId2( "00" );
|
||||
|
||||
// {
|
||||
// Session session = openSession();
|
||||
// session.beginTransaction();
|
||||
// DoesNotWork entity = new DoesNotWork( pk );
|
||||
// entity.setGlobalNotes( Arrays.asList( "My first note!" ) );
|
||||
// session.save( entity );
|
||||
// session.getTransaction().commit();
|
||||
// session.close();
|
||||
// }
|
||||
|
||||
{
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
DoesNotWork entity = (DoesNotWork) session.get( DoesNotWork.class, pk );
|
||||
assertNotNull( entity );
|
||||
List<String> notes = entity.getGlobalNotes();
|
||||
assertNotNull( notes );
|
||||
assertEquals( 2, notes.size() );
|
||||
for ( String s : notes ) {
|
||||
System.out.println( s );
|
||||
}
|
||||
session.delete( entity );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.propertyref">
|
||||
<class name="DoesNotWork" table="vgras007_v031">
|
||||
<composite-id name="doesNotWorkPk" class="DoesNotWorkPk">
|
||||
<key-property name="id1" column="track_no"/>
|
||||
<key-property name="id2" column="track_ext"/>
|
||||
</composite-id>
|
||||
<property name="globAdditInfoTid" column="production_credits_tid"/>
|
||||
<list name="globalNotes" table="vgras029_v031">
|
||||
<key column="text_id" property-ref="globAdditInfoTid"/>
|
||||
<list-index column="seq_no" base="1"/>
|
||||
<element column="text_part" type="string"/>
|
||||
</list>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,3 @@
|
|||
INSERT INTO `vgras007_v031` VALUES ('ZZZ','00',1);
|
||||
|
||||
INSERT INTO `vgras029_v031` VALUES (1,'Foo Foo Foo',1), (1,'Bar Bar Bar',2);
|
|
@ -442,6 +442,11 @@ public class PersisterClassProviderTest {
|
|||
return new Object[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getIdByUniqueKey(Serializable key, String uniquePropertyName, SessionImplementor session) {
|
||||
throw new UnsupportedOperationException( "Not supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCurrentVersion(Serializable id, SessionImplementor session) throws HibernateException {
|
||||
return null;
|
||||
|
|
|
@ -192,6 +192,19 @@ public class TestClassMetadata {
|
|||
}
|
||||
|
||||
private void invokeCallback(Method callback, Object target) {
|
||||
try {
|
||||
performCallbackInvocation( callback, target );
|
||||
}
|
||||
catch (CallbackException e) {
|
||||
// this is getting eaten, at least when run from IntelliJ. The test fails to start (for start up
|
||||
// callbacks), but the exception is never shown..
|
||||
System.out.println( "Error performing callback invocation : " + e.getLocalizedMessage() );
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void performCallbackInvocation(Method callback, Object target) {
|
||||
try {
|
||||
callback.invoke( target, NO_ARGS );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue