HHH-6204 - JoinColumn on non key field fails to populate collection

This commit is contained in:
Steve Ebersole 2012-07-24 14:59:27 -05:00 committed by Strong Liu
parent e813d329bc
commit f6fc21a133
19 changed files with 753 additions and 4 deletions

View File

@ -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,

View File

@ -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 );

View File

@ -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

View File

@ -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() ) );
}

View File

@ -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 &&

View File

@ -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);
}

View File

@ -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
*/

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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 );
}