HHH-10956 fixed failed insertion with IdClass with partial identifier generation

* regression introduced by HHH-4848
* AbstractEntityTuplizer lines 179 and 311 formatting issues, preserved
* bug HHH-9662 blocks testing of Identity insertion
This commit is contained in:
Jason Pyeron 2020-04-22 18:15:11 -04:00 committed by Andrea Boriero
parent 77d60e5d6e
commit 87cfe33b5c
3 changed files with 34 additions and 8 deletions

View File

@ -264,6 +264,17 @@ public class SimpleValue implements KeyValue {
private IdentifierGenerator identifierGenerator; private IdentifierGenerator identifierGenerator;
/**
* Returns the cached identifierGenerator.
*
* @return IdentifierGenerator null if
* {@link #createIdentifierGenerator(IdentifierGeneratorFactory, Dialect, String, String, RootClass)} was never
* completed.
*/
public IdentifierGenerator getIdentifierGenerator() {
return identifierGenerator;
}
@Override @Override
public IdentifierGenerator createIdentifierGenerator( public IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory, IdentifierGeneratorFactory identifierGeneratorFactory,

View File

@ -26,8 +26,10 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.Assigned; import org.hibernate.id.Assigned;
import org.hibernate.loader.PropertyPath; import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.metamodel.spi.MetamodelImplementor; import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Getter;
@ -168,11 +170,13 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
} }
else { else {
identifierMapperType = (CompositeType) mapper.getType(); identifierMapperType = (CompositeType) mapper.getType();
KeyValue identifier = mappingInfo.getIdentifier();
mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller( mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller(
getEntityName(), getEntityName(),
getFactory(), getFactory(),
(ComponentType) entityMetamodel.getIdentifierProperty().getType(), (ComponentType) entityMetamodel.getIdentifierProperty().getType(),
(ComponentType) identifierMapperType (ComponentType) identifierMapperType,
identifier
); );
} }
} }
@ -274,7 +278,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
String entityName, String entityName,
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
ComponentType mappedIdClassComponentType, ComponentType mappedIdClassComponentType,
ComponentType virtualIdComponent) { ComponentType virtualIdComponent,
KeyValue identifier) {
// so basically at this point we know we have a "mapped" composite identifier // so basically at this point we know we have a "mapped" composite identifier
// which is an awful way to say that the identifier is represented differently // which is an awful way to say that the identifier is represented differently
// in the entity and in the identifier value. The incoming value should // in the entity and in the identifier value. The incoming value should
@ -302,7 +307,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
entityName, entityName,
sessionFactory, sessionFactory,
virtualIdComponent, virtualIdComponent,
mappedIdClassComponentType mappedIdClassComponentType,
identifier
); );
} }
@ -341,28 +347,40 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
private final SessionFactoryImplementor sessionFactory; private final SessionFactoryImplementor sessionFactory;
private final ComponentType virtualIdComponent; private final ComponentType virtualIdComponent;
private final ComponentType mappedIdentifierType; private final ComponentType mappedIdentifierType;
private final KeyValue identifier;
private IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller( private IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller(
String entityName, String entityName,
SessionFactoryImplementor sessionFactory, SessionFactoryImplementor sessionFactory,
ComponentType virtualIdComponent, ComponentType virtualIdComponent,
ComponentType mappedIdentifierType) { ComponentType mappedIdentifierType,
KeyValue identifier) {
this.sessionFactory = sessionFactory; this.sessionFactory = sessionFactory;
this.entityName = entityName; this.entityName = entityName;
this.virtualIdComponent = virtualIdComponent; this.virtualIdComponent = virtualIdComponent;
this.mappedIdentifierType = mappedIdentifierType; this.mappedIdentifierType = mappedIdentifierType;
this.identifier = identifier;
} }
@Override @Override
public Object getIdentifier(Object entity, EntityMode entityMode, SharedSessionContractImplementor session) { public Object getIdentifier(Object entity, EntityMode entityMode, SharedSessionContractImplementor session) {
final Object id = mappedIdentifierType.instantiate( entityMode ); final Object id = mappedIdentifierType.instantiate( entityMode );
final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity, entityMode ); final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity, entityMode );
final String[] names = virtualIdComponent.getPropertyNames();
final Type[] subTypes = virtualIdComponent.getSubtypes(); final Type[] subTypes = virtualIdComponent.getSubtypes();
final Type[] copierSubTypes = mappedIdentifierType.getSubtypes(); final Type[] copierSubTypes = mappedIdentifierType.getSubtypes();
final int length = subTypes.length; final int length = subTypes.length;
for ( int i = 0; i < length; i++ ) { for ( int i = 0; i < length; i++ ) {
if ( propertyValues[i] == null ) { if ( propertyValues[i] == null ) {
throw new HibernateException( "No part of a composite identifier may be null" ); try {
final String name = names[i];
final Property p = ((Component) identifier).getProperty(name);
final SimpleValue v = (SimpleValue) p.getValue();
if ( v.getIdentifierGenerator() == null ) throw new NullPointerException("No IdentifierGenerator found for property "+name);
}
catch (Throwable t) {
throw new HibernateException( "No part of a composite identifier may be null", t );
}
} }
//JPA 2 @MapsId + @IdClass points to the pk of the entity //JPA 2 @MapsId + @IdClass points to the pk of the entity
if ( subTypes[i].isAssociationType() && !copierSubTypes[i].isAssociationType() ) { if ( subTypes[i].isAssociationType() && !copierSubTypes[i].isAssociationType() ) {

View File

@ -45,7 +45,6 @@ import org.junit.Test;
public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalTestCase { public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalTestCase {
@Test @Test
@FailureExpected(jiraKey = "HHH-10956", message = "javax.persistence.PersistenceException: org.hibernate.HibernateException: No part of a composite identifier may be null")
public void testCompositePkWithIdentityAndFKBySequence() throws Exception { public void testCompositePkWithIdentityAndFKBySequence() throws Exception {
doInHibernate( this::sessionFactory, session -> { doInHibernate( this::sessionFactory, session -> {
HeadS head = new HeadS(); HeadS head = new HeadS();
@ -75,7 +74,6 @@ public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalT
} }
@Test @Test
@FailureExpected(jiraKey = "HHH-10956", message = "javax.persistence.PersistenceException: org.hibernate.HibernateException: No part of a composite identifier may be null")
public void testCompositePkWithIdentityAndFKByTable() throws Exception { public void testCompositePkWithIdentityAndFKByTable() throws Exception {
doInHibernate( this::sessionFactory, session -> { doInHibernate( this::sessionFactory, session -> {
HeadT head = new HeadT(); HeadT head = new HeadT();
@ -90,7 +88,6 @@ public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalT
} }
@Test @Test
@FailureExpected(jiraKey = "HHH-10956", message = "javax.persistence.PersistenceException: org.hibernate.HibernateException: No part of a composite identifier may be null")
public void testCompositePkWithIdentityAndFKByAuto() throws Exception { public void testCompositePkWithIdentityAndFKByAuto() throws Exception {
doInHibernate( this::sessionFactory, session -> { doInHibernate( this::sessionFactory, session -> {
HeadA head = new HeadA(); HeadA head = new HeadA();