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;
/**
* Returns the cached identifierGenerator.
*
* @return IdentifierGenerator null if
* {@link #createIdentifierGenerator(IdentifierGeneratorFactory, Dialect, String, String, RootClass)} was never
* completed.
*/
public IdentifierGenerator getIdentifierGenerator() {
return identifierGenerator;
}
@Override
public IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,

View File

@ -26,8 +26,10 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.Assigned;
import org.hibernate.loader.PropertyPath;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.access.spi.Getter;
@ -168,11 +170,13 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
}
else {
identifierMapperType = (CompositeType) mapper.getType();
KeyValue identifier = mappingInfo.getIdentifier();
mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller(
getEntityName(),
getFactory(),
(ComponentType) entityMetamodel.getIdentifierProperty().getType(),
(ComponentType) identifierMapperType
(ComponentType) identifierMapperType,
identifier
);
}
}
@ -274,7 +278,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
String entityName,
SessionFactoryImplementor sessionFactory,
ComponentType mappedIdClassComponentType,
ComponentType virtualIdComponent) {
ComponentType virtualIdComponent,
KeyValue 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
// in the entity and in the identifier value. The incoming value should
@ -302,7 +307,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
entityName,
sessionFactory,
virtualIdComponent,
mappedIdClassComponentType
mappedIdClassComponentType,
identifier
);
}
@ -341,28 +347,40 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
private final SessionFactoryImplementor sessionFactory;
private final ComponentType virtualIdComponent;
private final ComponentType mappedIdentifierType;
private final KeyValue identifier;
private IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller(
String entityName,
SessionFactoryImplementor sessionFactory,
ComponentType virtualIdComponent,
ComponentType mappedIdentifierType) {
ComponentType mappedIdentifierType,
KeyValue identifier) {
this.sessionFactory = sessionFactory;
this.entityName = entityName;
this.virtualIdComponent = virtualIdComponent;
this.mappedIdentifierType = mappedIdentifierType;
this.identifier = identifier;
}
@Override
public Object getIdentifier(Object entity, EntityMode entityMode, SharedSessionContractImplementor session) {
final Object id = mappedIdentifierType.instantiate( entityMode );
final Object[] propertyValues = virtualIdComponent.getPropertyValues( entity, entityMode );
final String[] names = virtualIdComponent.getPropertyNames();
final Type[] subTypes = virtualIdComponent.getSubtypes();
final Type[] copierSubTypes = mappedIdentifierType.getSubtypes();
final int length = subTypes.length;
for ( int i = 0; i < length; i++ ) {
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
if ( subTypes[i].isAssociationType() && !copierSubTypes[i].isAssociationType() ) {

View File

@ -45,7 +45,6 @@ import org.junit.Test;
public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalTestCase {
@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 {
doInHibernate( this::sessionFactory, session -> {
HeadS head = new HeadS();
@ -75,7 +74,6 @@ public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalT
}
@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 {
doInHibernate( this::sessionFactory, session -> {
HeadT head = new HeadT();
@ -90,7 +88,6 @@ public class CompositeIdFkGeneratedValueIdentityTest extends BaseCoreFunctionalT
}
@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 {
doInHibernate( this::sessionFactory, session -> {
HeadA head = new HeadA();