HHH-4552 - Support generated value within composite keys
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18640 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
091c2d2269
commit
3b536fa6f6
|
@ -60,7 +60,6 @@ public class IdClassGeneratedValueTest extends TestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
@FailureExpected(message = "Not yet implemented", jiraKey = "HHH-4552")
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void testSingleGeneratedValue() {
|
||||
Session s = openSession();
|
||||
|
@ -77,7 +76,7 @@ public class IdClassGeneratedValueTest extends TestCase {
|
|||
s.beginTransaction();
|
||||
List<Simple2> simpleList = s.createQuery( "select s from Simple2 s" ).list();
|
||||
assertEquals( simpleList.size(), 2 );
|
||||
s1 = ( Simple2 ) s.load( Simple2.class, new SimplePK( s1Id1, 2L ) );
|
||||
s1 = ( Simple2 ) s.load( Simple2.class, new SimplePK( s1Id1, 200L ) );
|
||||
assertEquals( s1.getQuantity(), 10 );
|
||||
s.clear();
|
||||
s.createQuery( "delete Simple2" ).executeUpdate();
|
||||
|
@ -85,7 +84,6 @@ public class IdClassGeneratedValueTest extends TestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
@FailureExpected(message = "Not yet implemented", jiraKey = "HHH-4552")
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void testMultipleGeneratedValue() {
|
||||
Session s = openSession();
|
||||
|
@ -103,7 +101,7 @@ public class IdClassGeneratedValueTest extends TestCase {
|
|||
s.beginTransaction();
|
||||
List<Multiple> simpleList = s.createQuery( "select m from Multiple m" ).list();
|
||||
assertEquals( simpleList.size(), 2 );
|
||||
m1 = ( Multiple ) s.load( Multiple.class, new MultiplePK( m1Id1, m1Id2, 2L ) );
|
||||
m1 = ( Multiple ) s.load( Multiple.class, new MultiplePK( m1Id1, m1Id2, 1000L ) );
|
||||
assertEquals( m1.getQuantity(), 10 );
|
||||
s.clear();
|
||||
s.createQuery( "delete Multiple" ).executeUpdate();
|
||||
|
|
|
@ -33,26 +33,15 @@ import java.io.Serializable;
|
|||
public class SimplePK implements Serializable {
|
||||
private final Long id1;
|
||||
private final Long id2;
|
||||
// AnnotationBinder (incorrectly) requires this to be transient; see HHH-4819 and HHH-4820
|
||||
private final transient int cachedHashCode;
|
||||
|
||||
private SimplePK() {
|
||||
// required by Hibernate, though never used; see HHH-4818
|
||||
id1 = null;
|
||||
id2 = null;
|
||||
cachedHashCode = super.hashCode();
|
||||
}
|
||||
|
||||
public SimplePK(Long id1, Long id2) {
|
||||
this.id1 = id1;
|
||||
this.id2 = id2;
|
||||
this.cachedHashCode = calculateHashCode();
|
||||
}
|
||||
|
||||
private int calculateHashCode() {
|
||||
int result = id1.hashCode();
|
||||
result = 31 * result + id2.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Long getId1() {
|
||||
|
@ -80,6 +69,8 @@ public class SimplePK implements Serializable {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return cachedHashCode;
|
||||
int result = id1.hashCode();
|
||||
result = 31 * result + id2.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,12 +62,35 @@ import org.hibernate.engine.SessionImplementor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositeNestedGeneratedValueGenerator implements IdentifierGenerator, Serializable {
|
||||
/**
|
||||
* Contract for declaring how to locate the context for sub-value injection.
|
||||
*/
|
||||
public static interface GenerationContextLocator {
|
||||
/**
|
||||
* Given the incoming object, determine the context for injecting back its generated
|
||||
* id sub-values.
|
||||
*
|
||||
* @param session The current session
|
||||
* @param incomingObject The entity for which we are generating id
|
||||
*
|
||||
* @return The injection context
|
||||
*/
|
||||
public Serializable locateGenerationContext(SessionImplementor session, Object incomingObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract for performing the actual sub-value generation, usually injecting it into the
|
||||
* determined {@link GenerationContextLocator#locateGenerationContext context}
|
||||
*/
|
||||
public static interface GenerationPlan {
|
||||
public void execute(SessionImplementor session, Object incomingObject, Object objectId);
|
||||
/**
|
||||
* Execute the value generation.
|
||||
*
|
||||
* @param session The current session
|
||||
* @param incomingObject The entity for which we are generating id
|
||||
* @param injectionContext The context into which the generated value can be injected
|
||||
*/
|
||||
public void execute(SessionImplementor session, Object incomingObject, Object injectionContext);
|
||||
}
|
||||
|
||||
private final GenerationContextLocator generationContextLocator;
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.EntityMode;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.EntityEntry;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
|
@ -348,17 +349,17 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
|
||||
// IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the
|
||||
// various scenarios for which we need to account here
|
||||
if ( isEmbedded() ) {
|
||||
// we have the "straight up" embedded (again the hibernate term) component identifier
|
||||
attributeDeclarer = entityClass;
|
||||
if ( rootClass.getIdentifierMapper() != null ) {
|
||||
// we have the @IdClass / <composite-id mapped="true"/> case
|
||||
attributeDeclarer = resolveComponentClass();
|
||||
}
|
||||
else if ( rootClass.getIdentifierProperty() != null ) {
|
||||
// we have the "@EmbeddedId" / <composite-id name="idName"/> case
|
||||
attributeDeclarer = resolveComponentClass();
|
||||
}
|
||||
else {
|
||||
// we have the @IdClass / <composite-id mapped="true"/> case
|
||||
attributeDeclarer = resolveComponentClass();
|
||||
// we have the "straight up" embedded (again the hibernate term) component identifier
|
||||
attributeDeclarer = entityClass;
|
||||
}
|
||||
|
||||
locator = new StandardGenerationContextLocator( rootClass.getEntityName() );
|
||||
|
@ -383,13 +384,11 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
defaultSchema,
|
||||
rootClass
|
||||
);
|
||||
final Setter injector = property.getPropertyAccessor( attributeDeclarer )
|
||||
.getSetter( attributeDeclarer, property.getName() );
|
||||
generator.addGeneratedValuePlan(
|
||||
new ValueGenerationPlan(
|
||||
property.getName(),
|
||||
valueGenerator,
|
||||
injector
|
||||
injector( property, attributeDeclarer )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -397,6 +396,11 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
return generator;
|
||||
}
|
||||
|
||||
private Setter injector(Property property, Class attributeDeclarer) {
|
||||
return property.getPropertyAccessor( attributeDeclarer )
|
||||
.getSetter( attributeDeclarer, property.getName() );
|
||||
}
|
||||
|
||||
private Class resolveComponentClass() {
|
||||
try {
|
||||
return getComponentClass();
|
||||
|
@ -434,9 +438,12 @@ public class Component extends SimpleValue implements MetaAttributable {
|
|||
this.injector = injector;
|
||||
}
|
||||
|
||||
public void execute(SessionImplementor session, Object incomingObject, Object idObject) {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void execute(SessionImplementor session, Object incomingObject, Object injectionContext) {
|
||||
final Object generatedValue = subGenerator.generate( session, incomingObject );
|
||||
injector.set( idObject, generatedValue, session.getFactory() );
|
||||
injector.set( injectionContext, generatedValue, session.getFactory() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -226,6 +226,11 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
|
|||
else if ( idSetter != null ) {
|
||||
idSetter.set( entity, id, getFactory() );
|
||||
}
|
||||
else if ( identifierMapperType != null ) {
|
||||
ComponentType extractor = (ComponentType) entityMetamodel.getIdentifierProperty().getType();
|
||||
ComponentType copier = (ComponentType) identifierMapperType;
|
||||
copier.setPropertyValues( entity, extractor.getPropertyValues( id, getEntityMode() ), getEntityMode() );
|
||||
}
|
||||
}
|
||||
|
||||
public void resetIdentifier(Object entity, Serializable currentId, Object currentVersion) {
|
||||
|
|
Loading…
Reference in New Issue