HHH-7167 - The new natural id code introduced in 4.1.1 depends on the order the entity persisters are loaded which leads to fatal errors
This commit is contained in:
parent
c7afef512e
commit
77393f77f9
|
@ -223,8 +223,6 @@ public abstract class AbstractEntityPersister
|
||||||
private final Map loaders = new HashMap();
|
private final Map loaders = new HashMap();
|
||||||
|
|
||||||
// SQL strings
|
// SQL strings
|
||||||
private String sqlEntityIdByNaturalIdString;
|
|
||||||
|
|
||||||
private String sqlVersionSelectString;
|
private String sqlVersionSelectString;
|
||||||
private String sqlSnapshotSelectString;
|
private String sqlSnapshotSelectString;
|
||||||
private String sqlLazySelectString;
|
private String sqlLazySelectString;
|
||||||
|
@ -3377,26 +3375,37 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void logStaticSQL() {
|
protected void logStaticSQL() {
|
||||||
if (LOG.isDebugEnabled()) {
|
if ( LOG.isDebugEnabled() ) {
|
||||||
LOG.debugf("Static SQL for entity: %s", getEntityName());
|
LOG.debugf( "Static SQL for entity: %s", getEntityName() );
|
||||||
if (sqlLazySelectString != null) LOG.debugf(" Lazy select: %s", sqlLazySelectString);
|
if ( sqlLazySelectString != null ) {
|
||||||
if (sqlVersionSelectString != null) LOG.debugf(" Version select: %s", sqlVersionSelectString);
|
LOG.debugf( " Lazy select: %s", sqlLazySelectString );
|
||||||
if (sqlSnapshotSelectString != null) LOG.debugf(" Snapshot select: %s", sqlSnapshotSelectString);
|
}
|
||||||
for ( int j = 0; j < getTableSpan(); j++ ) {
|
if ( sqlVersionSelectString != null ) {
|
||||||
LOG.debugf(" Insert %s: %s", j, getSQLInsertStrings()[j]);
|
LOG.debugf( " Version select: %s", sqlVersionSelectString );
|
||||||
LOG.debugf(" Update %s: %s", j, getSQLUpdateStrings()[j]);
|
}
|
||||||
LOG.debugf(" Delete %s: %s", j, getSQLDeleteStrings()[j]);
|
if ( sqlSnapshotSelectString != null ) {
|
||||||
|
LOG.debugf( " Snapshot select: %s", sqlSnapshotSelectString );
|
||||||
|
}
|
||||||
|
for ( int j = 0; j < getTableSpan(); j++ ) {
|
||||||
|
LOG.debugf( " Insert %s: %s", j, getSQLInsertStrings()[j] );
|
||||||
|
LOG.debugf( " Update %s: %s", j, getSQLUpdateStrings()[j] );
|
||||||
|
LOG.debugf( " Delete %s: %s", j, getSQLDeleteStrings()[j] );
|
||||||
|
}
|
||||||
|
if ( sqlIdentityInsertString != null ) {
|
||||||
|
LOG.debugf( " Identity insert: %s", sqlIdentityInsertString );
|
||||||
|
}
|
||||||
|
if ( sqlUpdateByRowIdString != null ) {
|
||||||
|
LOG.debugf( " Update by row id (all fields): %s", sqlUpdateByRowIdString );
|
||||||
|
}
|
||||||
|
if ( sqlLazyUpdateByRowIdString != null ) {
|
||||||
|
LOG.debugf( " Update by row id (non-lazy fields): %s", sqlLazyUpdateByRowIdString );
|
||||||
|
}
|
||||||
|
if ( sqlInsertGeneratedValuesSelectString != null ) {
|
||||||
|
LOG.debugf( " Insert-generated property select: %s", sqlInsertGeneratedValuesSelectString );
|
||||||
|
}
|
||||||
|
if ( sqlUpdateGeneratedValuesSelectString != null ) {
|
||||||
|
LOG.debugf( " Update-generated property select: %s", sqlUpdateGeneratedValuesSelectString );
|
||||||
}
|
}
|
||||||
if (sqlIdentityInsertString != null) LOG.debugf(" Identity insert: %s", sqlIdentityInsertString);
|
|
||||||
if (sqlUpdateByRowIdString != null) LOG.debugf(" Update by row id (all fields): %s", sqlUpdateByRowIdString);
|
|
||||||
if (sqlLazyUpdateByRowIdString != null) LOG.debugf(" Update by row id (non-lazy fields): %s",
|
|
||||||
sqlLazyUpdateByRowIdString);
|
|
||||||
if (sqlInsertGeneratedValuesSelectString != null) LOG.debugf("Insert-generated property select: %s",
|
|
||||||
sqlInsertGeneratedValuesSelectString);
|
|
||||||
if (sqlUpdateGeneratedValuesSelectString != null) LOG.debugf("Update-generated property select: %s",
|
|
||||||
sqlUpdateGeneratedValuesSelectString);
|
|
||||||
if (sqlEntityIdByNaturalIdString != null) LOG.debugf("Id by Natural Id: %s",
|
|
||||||
sqlEntityIdByNaturalIdString);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3604,10 +3613,6 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postInstantiate() throws MappingException {
|
public void postInstantiate() throws MappingException {
|
||||||
if ( hasNaturalIdentifier() ) {
|
|
||||||
sqlEntityIdByNaturalIdString = generateEntityIdByNaturalIdSql();
|
|
||||||
}
|
|
||||||
|
|
||||||
createLoaders();
|
createLoaders();
|
||||||
createUniqueKeyLoaders();
|
createUniqueKeyLoaders();
|
||||||
createQueryLoader();
|
createQueryLoader();
|
||||||
|
@ -4512,7 +4517,7 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializable loadEntityIdByNaturalId(
|
public Serializable loadEntityIdByNaturalId(
|
||||||
Object[] naturalIdValues,
|
Object[] naturalIdValues,
|
||||||
|
@ -4526,6 +4531,8 @@ public abstract class AbstractEntityPersister
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String sqlEntityIdByNaturalIdString = determinePkByNaturalIdQuery();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = session.getTransactionCoordinator()
|
PreparedStatement ps = session.getTransactionCoordinator()
|
||||||
.getJdbcCoordinator()
|
.getJdbcCoordinator()
|
||||||
|
@ -4546,7 +4553,6 @@ public abstract class AbstractEntityPersister
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// entity ID has to be serializable right?
|
|
||||||
return (Serializable) getIdentifierType().hydrate( rs, getIdentifierAliases(), session, null );
|
return (Serializable) getIdentifierType().hydrate( rs, getIdentifierAliases(), session, null );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -4570,11 +4576,24 @@ public abstract class AbstractEntityPersister
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String pkByNaturalIdQuery;
|
||||||
|
|
||||||
|
private String determinePkByNaturalIdQuery() {
|
||||||
|
if ( ! hasNaturalIdentifier() ) {
|
||||||
|
throw new HibernateException( "Attempt to build natural-id -> PK resolution query for entity that does not define natural id" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pkByNaturalIdQuery == null ) {
|
||||||
|
pkByNaturalIdQuery = generateEntityIdByNaturalIdSql();
|
||||||
|
}
|
||||||
|
return pkByNaturalIdQuery;
|
||||||
|
}
|
||||||
|
|
||||||
private String generateEntityIdByNaturalIdSql() {
|
private String generateEntityIdByNaturalIdSql() {
|
||||||
EntityPersister rootPersister = getFactory().getEntityPersister( getRootEntityName() );
|
EntityPersister rootPersister = getFactory().getEntityPersister( getRootEntityName() );
|
||||||
if ( rootPersister != this ) {
|
if ( rootPersister != this ) {
|
||||||
if ( rootPersister instanceof AbstractEntityPersister ) {
|
if ( rootPersister instanceof AbstractEntityPersister ) {
|
||||||
return ( (AbstractEntityPersister) rootPersister ).sqlEntityIdByNaturalIdString;
|
return ( (AbstractEntityPersister) rootPersister ).generateEntityIdByNaturalIdSql();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ public class NaturalIdOnSingleManyToOneTest extends BaseCoreFunctionalTestCase {
|
||||||
stats.clear();
|
stats.clear();
|
||||||
assertEquals( "NaturalId cache puts should be zero", 0, stats.getNaturalIdCachePutCount() );
|
assertEquals( "NaturalId cache puts should be zero", 0, stats.getNaturalIdCachePutCount() );
|
||||||
assertEquals( "NaturalId cache hits should be zero", 0, stats.getNaturalIdCacheHitCount() );
|
assertEquals( "NaturalId cache hits should be zero", 0, stats.getNaturalIdCacheHitCount() );
|
||||||
|
assertEquals( "NaturalId Cache Puts", 0, stats.getNaturalIdCachePutCount() );
|
||||||
assertEquals( "NaturalId cache misses should be zero", 0, stats.getNaturalIdCacheMissCount() );
|
assertEquals( "NaturalId cache misses should be zero", 0, stats.getNaturalIdCacheMissCount() );
|
||||||
|
|
||||||
// first query
|
// first query
|
||||||
|
@ -124,14 +125,14 @@ public class NaturalIdOnSingleManyToOneTest extends BaseCoreFunctionalTestCase {
|
||||||
assertEquals( 1, results.size() );
|
assertEquals( 1, results.size() );
|
||||||
assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
|
assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
|
||||||
assertEquals( "NaturalId Cache Misses", 1, stats.getNaturalIdCacheMissCount() );
|
assertEquals( "NaturalId Cache Misses", 1, stats.getNaturalIdCacheMissCount() );
|
||||||
assertEquals( "NaturalId Cache Puts", 1, stats.getNaturalIdCachePutCount() );
|
assertEquals( "NaturalId Cache Puts", 2, stats.getNaturalIdCachePutCount() ); // one for Citizen, one for NaturalIdOnManyToOne
|
||||||
assertEquals( "NaturalId Cache Queries", 1, stats.getNaturalIdQueryExecutionCount() );
|
assertEquals( "NaturalId Cache Queries", 1, stats.getNaturalIdQueryExecutionCount() );
|
||||||
|
|
||||||
// query a second time - result should be in session cache
|
// query a second time - result should be in session cache
|
||||||
criteria.list();
|
criteria.list();
|
||||||
assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
|
assertEquals( "NaturalId Cache Hits", 0, stats.getNaturalIdCacheHitCount() );
|
||||||
assertEquals( "NaturalId Cache Misses", 1, stats.getNaturalIdCacheMissCount() );
|
assertEquals( "NaturalId Cache Misses", 1, stats.getNaturalIdCacheMissCount() );
|
||||||
assertEquals( "NaturalId Cache Puts", 1, stats.getNaturalIdCachePutCount() );
|
assertEquals( "NaturalId Cache Puts", 2, stats.getNaturalIdCachePutCount() );
|
||||||
assertEquals( "NaturalId Cache Queries", 1, stats.getNaturalIdQueryExecutionCount() );
|
assertEquals( "NaturalId Cache Queries", 1, stats.getNaturalIdQueryExecutionCount() );
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
|
|
Loading…
Reference in New Issue