diff --git a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveIdentityGenerator.java b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveIdentityGenerator.java index f29bffeac..cd9603ca3 100644 --- a/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveIdentityGenerator.java +++ b/hibernate-reactive-core/src/main/java/org/hibernate/reactive/persister/entity/impl/ReactiveIdentityGenerator.java @@ -5,188 +5,38 @@ */ package org.hibernate.reactive.persister.entity.impl; -import java.util.Iterator; -import org.hibernate.MappingException; -import org.hibernate.boot.model.relational.SqlStringGenerationContext; -import org.hibernate.dialect.CockroachDialect; -import org.hibernate.dialect.DB2Dialect; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.PostgreSQLDialect; -import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.identity.CockroachDBIdentityColumnSupport; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.id.IdentityGenerator; import org.hibernate.id.PostInsertIdentityPersister; -import org.hibernate.id.insert.IdentifierGeneratingInsert; import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate; -import org.hibernate.id.insert.InsertReturningDelegate; -import org.hibernate.reactive.id.insert.ReactiveBasicSelectingDelegate; -import org.hibernate.reactive.id.insert.ReactiveInsertReturningDelegate; -import org.hibernate.sql.Insert; +import org.hibernate.reactive.logging.impl.Log; -import static org.hibernate.reactive.dialect.ReactiveDialectWrapper.instanceOf; +import static java.lang.invoke.MethodHandles.lookup; +import static org.hibernate.reactive.logging.impl.LoggerFactory.make; /** * Fix the insert and select id queries generated by Hibernate ORM */ public class ReactiveIdentityGenerator extends IdentityGenerator { + private static final Log LOG = make( Log.class, lookup() ); + /** * @see CockroachDBIdentityColumnSupport#supportsIdentityColumns() for some limitations related to CockraochDB */ @Override public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(PostInsertIdentityPersister persister) { Dialect dialect = persister.getFactory().getJdbcServices().getDialect(); - if ( persister.getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled() ) { - return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate( persister, dialect ); - } - if ( dialect.getIdentityColumnSupport().supportsInsertSelectIdentity() - // Basically, this is the only approach that works for Cockroach at the moment. - // That said, there are some limitations about identity generation with Cockroach. - // Check CockroachDBIdentityColumnSupport#supportsIdentityColumns for more details - || instanceOf( dialect, CockroachDialect.class ) ) { - return new ReactiveInsertReturningDelegate( persister, dialect ); - } - return new ReactiveBasicSelectingDelegate( persister, dialect ); - } - - public static class ReactiveInsertAndSelectDelegate extends InsertReturningDelegate { - - private final PostInsertIdentityPersister persister; - private final Dialect dialect; - private final SessionFactoryImplementor factory; - - public ReactiveInsertAndSelectDelegate(PostInsertIdentityPersister persister, Dialect dialect) { - super( persister, dialect ); - this.persister = persister; - this.dialect = dialect; - this.factory = persister.getFactory(); - } - - @Override - public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert(SqlStringGenerationContext context) { - IdentifierGeneratingInsert insert = createInsert( context ); - insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[0] ); - return insert; - } - - private IdentifierGeneratingInsert createInsert(SqlStringGenerationContext context) { - if ( dialect instanceof PostgreSQLDialect || dialect instanceof CockroachDialect ) { - return new PostgresIdentifierGeneratingInsert( factory ); - } - if ( dialect instanceof SQLServerDialect ) { - return new SqlServerIdentifierGeneratingInsert( factory ); - } - if ( dialect instanceof DB2Dialect ) { - return new Db2IdentifierGeneratingInsert( factory ); - } - return super.prepareIdentifierGeneratingInsert( context ); - } + boolean generatedKeysEnabled = persister.getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled(); + if ( !generatedKeysEnabled ) { + LOG.debugf( "Ignoring property `%s`", AvailableSettings.USE_GET_GENERATED_KEYS ); + } + // With JDBC, it's possible to select different type of queries for the retrieval of the id after + // an insert. But, we don't need this in Hibernate Reactive, and it's easier to just run the most efficient query + // for the selected database. + return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate( persister, dialect ); } - - public static class Db2IdentifierGeneratingInsert extends IdentifierGeneratingInsert { - - private String identityColumnName; - - public Db2IdentifierGeneratingInsert(SessionFactoryImplementor sessionFactory) { - super( sessionFactory ); - } - - @Override - public Insert addIdentityColumn(String columnName) { - this.identityColumnName = columnName; - return super.addIdentityColumn( columnName ); - } - - /** - * @see Insert#toStatementString() - */ - @Override - public String toStatementString() { - return "select " + identityColumnName + " from new table (" + super.toStatementString() + ")"; - } - } - - public static class PostgresIdentifierGeneratingInsert extends IdentifierGeneratingInsert { - - private String identityColumnName; - - public PostgresIdentifierGeneratingInsert(SessionFactoryImplementor sessionFactory) { - super( sessionFactory ); - } - - @Override - public Insert addIdentityColumn(String columnName) { - this.identityColumnName = columnName; - return super.addIdentityColumn( columnName ); - } - - @Override - public String toStatementString() { - return super.toStatementString() + " returning " + identityColumnName; - } - } - - public static class SqlServerIdentifierGeneratingInsert extends IdentifierGeneratingInsert { - private String identityColumnName; - - public SqlServerIdentifierGeneratingInsert(SessionFactoryImplementor sessionFactory) { - super( sessionFactory ); - } - - @Override - public Insert addIdentityColumn(String columnName) { - this.identityColumnName = columnName; - return super.addIdentityColumn( columnName ); - } - - /** - * @see Insert#toStatementString() - */ - public String toStatementString() { - StringBuilder buf = new StringBuilder( columns.size() * 15 + tableName.length() + 10 ); - if ( comment != null ) { - buf.append( "/* " ).append( Dialect.escapeComment( comment ) ).append( " */ " ); - } - buf.append( "insert into " ).append( tableName ); - if ( columns.size() == 0 ) { - if ( getDialect().supportsNoColumnsInsert() ) { - // This line is missing in ORM - buf.append( " output inserted." ).append( identityColumnName ); - buf.append( ' ' ).append( getDialect().getNoColumnsInsertString() ); - } - else { - throw new MappingException( String.format( - "The INSERT statement for table [%s] contains no column, and this is not supported by [%s]", - tableName, - getDialect() ) ); - } - } - else { - buf.append( " (" ); - Iterator iter = columns.keySet().iterator(); - while ( iter.hasNext() ) { - buf.append( iter.next() ); - if ( iter.hasNext() ) { - buf.append( ", " ); - } - } - buf.append( ')'); - // This line is missing in ORM - buf.append( " output inserted." ).append( identityColumnName ); - buf.append( " values (" ); - iter = columns.values().iterator(); - while ( iter.hasNext() ) { - buf.append( iter.next() ); - if ( iter.hasNext() ) { - buf.append( ", " ); - } - } - buf.append( ')' ); - } - return buf.toString(); - } - } - }