Fix generated values fetching for component attributes and implement identity select for Oracle

This commit is contained in:
Christian Beikov 2021-11-11 09:51:25 +01:00
parent 9a329f4991
commit 6c816932ed
8 changed files with 59 additions and 56 deletions

View File

@ -20,6 +20,7 @@ import org.hibernate.id.insert.AbstractSelectingDelegate;
import org.hibernate.id.insert.IdentifierGeneratingInsert;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.BasicType;
import org.hibernate.type.Type;
/**
@ -84,7 +85,7 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf
private final String uniqueKeyPropertyName;
private final Type uniqueKeyType;
private final Type idType;
private final BasicType<?> idType;
private final String idSelectString;
@ -94,15 +95,13 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf
String suppliedUniqueKeyPropertyName) {
super( persister );
throw new NotYetImplementedFor6Exception( getClass() );
this.persister = persister;
this.dialect = dialect;
this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, suppliedUniqueKeyPropertyName );
// this.persister = persister;
// this.dialect = dialect;
// this.uniqueKeyPropertyName = determineNameOfPropertyToUse( persister, suppliedUniqueKeyPropertyName );
//
// idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName );
// uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName );
// idType = persister.getIdentifierType();
idSelectString = persister.getSelectByUniqueKeyString( uniqueKeyPropertyName );
uniqueKeyType = persister.getPropertyType( uniqueKeyPropertyName );
idType = (BasicType<?>) persister.getIdentifierType();
}
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
@ -135,13 +134,11 @@ public class SelectGenerator extends AbstractPostInsertGenerator implements Conf
);
}
throw new NotYetImplementedFor6Exception( getClass() );
// return idType.nullSafeGet(
// rs,
// persister.getRootTableKeyColumnNames(),
// session,
// entity
// );
return idType.getJdbcValueExtractor().extract(
rs,
1,
session
);
}
}
}

View File

@ -34,6 +34,7 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InDatabaseValueGenerationStrategy;
/**
* @author Steve Ebersole
@ -58,31 +59,44 @@ public class GeneratedValuesProcessor {
// is applied before the insert/update happens.
final List<StateArrayContributorMapping> generatedValuesToSelect = new ArrayList<>();
// todo (6.0): for now, we rely on the entity metamodel as composite attributes report GenerationTiming.NEVER
// even if they have attributes that would need generation
final InDatabaseValueGenerationStrategy[] inDatabaseValueGenerationStrategies = entityDescriptor.getEntityPersister()
.getEntityMetamodel()
.getInDatabaseValueGenerationStrategies();
entityDescriptor.visitAttributeMappings( (attr) -> {
//noinspection RedundantClassCall
if ( ! StateArrayContributorMapping.class.isInstance( attr ) ) {
return;
}
if ( attr.getValueGeneration().getGenerationTiming() == GenerationTiming.NEVER ) {
final StateArrayContributorMapping mapping = (StateArrayContributorMapping) attr;
final InDatabaseValueGenerationStrategy inDatabaseValueGenerationStrategy = inDatabaseValueGenerationStrategies[mapping.getStateArrayPosition()];
if ( inDatabaseValueGenerationStrategy.getGenerationTiming() == GenerationTiming.NEVER ) {
return;
}
final GeneratedValueResolver generatedValueResolver = GeneratedValueResolver.from(
attr.getValueGeneration(),
final GeneratedValueResolver generatedValueResolver = new InDatabaseGeneratedValueResolver(
timing,
generatedValuesToSelect.size()
);
//noinspection RedundantClassCall
if ( ! InDatabaseGeneratedValueResolver.class.isInstance( generatedValueResolver ) ) {
// again, we only care about in in-db generations here
return;
}
// if ( attr.getValueGeneration().getGenerationTiming() == GenerationTiming.NEVER ) {
// return;
// }
//
// final GeneratedValueResolver generatedValueResolver = GeneratedValueResolver.from(
// attr.getValueGeneration(),
// timing,
// generatedValuesToSelect.size()
// );
//
// //noinspection RedundantClassCall
// if ( ! InDatabaseGeneratedValueResolver.class.isInstance( generatedValueResolver ) ) {
// // again, we only care about in in-db generations here
// return;
// }
// this attribute is generated for the timing we are processing...
valueDescriptors.add( new GeneratedValueDescriptor( generatedValueResolver, (StateArrayContributorMapping) attr ) );
generatedValuesToSelect.add( (StateArrayContributorMapping) attr );
valueDescriptors.add( new GeneratedValueDescriptor( generatedValueResolver, mapping ) );
generatedValuesToSelect.add( mapping );
});
if ( generatedValuesToSelect.isEmpty() ) {

View File

@ -5547,6 +5547,12 @@ public abstract class AbstractEntityPersister
creationProcess.registerInitializationCallback(
"Entity(" + getEntityName() + ") `staticFetchableList` generator",
() -> {
if ( hasInsertGeneratedProperties() ) {
insertGeneratedValuesProcessor = createGeneratedValuesProcessor( GenerationTiming.INSERT );
}
if ( hasUpdateGeneratedProperties() ) {
updateGeneratedValuesProcessor = createGeneratedValuesProcessor( GenerationTiming.ALWAYS );
}
staticFetchableList = new ArrayList<>( attributeMappings.size() );
visitSubTypeAttributeMappings( attributeMapping -> staticFetchableList.add( attributeMapping ) );
return true;
@ -5624,13 +5630,6 @@ public abstract class AbstractEntityPersister
else {
naturalIdMapping = null;
}
if ( hasInsertGeneratedProperties() ) {
insertGeneratedValuesProcessor = createGeneratedValuesProcessor( GenerationTiming.INSERT );
}
if ( hasUpdateGeneratedProperties() ) {
updateGeneratedValuesProcessor = createGeneratedValuesProcessor( GenerationTiming.ALWAYS );
}
}
private NaturalIdMapping generateNaturalIdMapping(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) {

View File

@ -9,23 +9,21 @@ package org.hibernate.orm.test.dialect.functional;
import java.sql.PreparedStatement;
import org.hibernate.Transaction;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.hibernate.testing.orm.junit.SkipForDialect;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@ -36,15 +34,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
*
* @author Jonathan Bregler
*/
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.HBM2DDL_AUTO, value = "none")
}
)
@DomainModel(
annotatedClasses = { HANASearchTest.SearchEntity.class }
)
@SessionFactory
@SessionFactory(exportSchema = false)
@RequiresDialect(HANAColumnStoreDialect.class)
@SkipForDialect(dialectClass = HANAColumnStoreDialect.class, version = 400)
public class HANASearchTest {
@ -85,6 +78,13 @@ public class HANASearchTest {
);
}
@AfterEach
protected void cleanupTestData(SessionFactoryScope scope) throws Exception {
scope.inTransaction(
session -> session.createQuery( "delete from " + ENTITY_NAME ).executeUpdate()
);
}
@Test
@TestForIssue(jiraKey = "HHH-13021")
public void testTextType(SessionFactoryScope scope) {
@ -163,7 +163,6 @@ public class HANASearchTest {
session.persist( entity );
t.commit();
session.beginTransaction();
session.beginTransaction();
Query<Object[]> legacyQuery = session.createQuery(
"select b, snippets(c), highlighted(c), score() from " + ENTITY_NAME
@ -227,7 +226,7 @@ public class HANASearchTest {
@Test
@TestForIssue(jiraKey = "HHH-13021")
public void testFuzzy(SessionFactoryScope scope) {
scope.inTransaction(
scope.inSession(
session -> {
Transaction t = session.beginTransaction();
SearchEntity entity = new SearchEntity();

View File

@ -35,9 +35,7 @@
<drop>
<![CDATA[DROP TRIGGER t_i_my_entity]]>
</drop>
<dialect-scope name="org.hibernate.dialect.Oracle9iDialect"/>
<dialect-scope name="org.hibernate.dialect.Oracle10gDialect"/>
<dialect-scope name="org.hibernate.dialect.Oracle12cDialect"/>
<dialect-scope name="org.hibernate.dialect.OracleDialect"/>
</database-object>
</hibernate-mapping>

View File

@ -37,9 +37,7 @@
<drop>
<![CDATA[DROP TRIGGER t_iu_part_gen_comp]]>
</drop>
<dialect-scope name="org.hibernate.dialect.Oracle9iDialect"/>
<dialect-scope name="org.hibernate.dialect.Oracle10gDialect"/>
<dialect-scope name="org.hibernate.dialect.Oracle12cDialect"/>
<dialect-scope name="org.hibernate.dialect.OracleDialect"/>
</database-object>
</hibernate-mapping>

View File

@ -25,7 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
* @author Steve Ebersole
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/generated/mapping/ComponentOwner.hbm.xml"
xmlMappings = "org/hibernate/orm/test/mapping/generated/ComponentOwner.hbm.xml"
)
@SessionFactory
@RequiresDialect( value = OracleDialect.class, version = 900 )

View File

@ -131,7 +131,6 @@ public class SynonymValidationTest extends BaseSessionFactoryFunctionalTest {
@Table(name = "test_entity")
private static class TestEntity {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
@ -168,7 +167,6 @@ public class SynonymValidationTest extends BaseSessionFactoryFunctionalTest {
@Table(name = "test_synonym")
private static class TestEntityWithSynonym {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)