allow use of SelectGenerator from annotations
- generalize @GenericGenerator to any Generator - add tests for @GenericGenerator(type=SelectGenerator) - move some logic for choosing the right InsertGeneratedIdentifierDelegate to the generators themselves
This commit is contained in:
parent
6536fe0d72
commit
e8c2824976
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import org.hibernate.generator.InMemoryGenerator;
|
||||
import org.hibernate.generator.Generator;
|
||||
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
|
@ -19,11 +19,10 @@ import static java.lang.annotation.ElementType.TYPE;
|
|||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Defines a named identifier generator, an instance of the interface
|
||||
* {@link org.hibernate.id.IdentifierGenerator}. This allows the use of
|
||||
* custom identifier generation strategies beyond those provided by the
|
||||
* four basic JPA-defined {@linkplain jakarta.persistence.GenerationType
|
||||
* generation types}.
|
||||
* Defines a named identifier generator, usually an instance of the interface
|
||||
* {@link org.hibernate.id.IdentifierGenerator}. This allows the use of custom
|
||||
* identifier generation strategies beyond those provided by the four basic
|
||||
* JPA-defined {@linkplain jakarta.persistence.GenerationType generation types}.
|
||||
* <p>
|
||||
* A named generator may be associated with an entity class by:
|
||||
* <ul>
|
||||
|
@ -74,17 +73,17 @@ public @interface GenericGenerator {
|
|||
*/
|
||||
String name();
|
||||
/**
|
||||
* The type of identifier generator, a class implementing {@link InMemoryGenerator}
|
||||
* The type of identifier generator, a class implementing {@link Generator}
|
||||
* or, more commonly, {@link org.hibernate.id.IdentifierGenerator}.
|
||||
*
|
||||
* @since 6.2
|
||||
*/
|
||||
Class<? extends InMemoryGenerator> type() default InMemoryGenerator.class;
|
||||
Class<? extends Generator> type() default Generator.class;
|
||||
/**
|
||||
* The type of identifier generator, the name of either:
|
||||
* <ul>
|
||||
* <li>a built-in Hibernate id generator, or
|
||||
* <li>a custom class implementing {@link InMemoryGenerator}, or, more commonly,
|
||||
* <li>a custom class implementing {@link Generator}, or, more commonly,
|
||||
* {@link org.hibernate.id.IdentifierGenerator}.
|
||||
* </ul>
|
||||
*
|
||||
|
|
|
@ -81,6 +81,7 @@ import org.hibernate.cfg.annotations.QueryBinder;
|
|||
import org.hibernate.dialect.TimeZoneSupport;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.generator.Generator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.GenericsHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
@ -98,7 +99,6 @@ import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
|
|||
import org.hibernate.property.access.spi.PropertyAccessStrategy;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.generator.InMemoryGenerator;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaType;
|
||||
|
@ -489,7 +489,7 @@ public final class AnnotationBinder {
|
|||
else if ( generatorAnnotation instanceof GenericGenerator ) {
|
||||
final GenericGenerator genericGenerator = (GenericGenerator) generatorAnnotation;
|
||||
definitionBuilder.setName( genericGenerator.name() );
|
||||
final String strategy = genericGenerator.type().equals(InMemoryGenerator.class)
|
||||
final String strategy = genericGenerator.type().equals(Generator.class)
|
||||
? genericGenerator.strategy()
|
||||
: genericGenerator.type().getName();
|
||||
definitionBuilder.setStrategy( strategy );
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
package org.hibernate.generator;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.id.PostInsertIdentityPersister;
|
||||
import org.hibernate.id.insert.BasicSelectingDelegate;
|
||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||
|
||||
/**
|
||||
* A value generated by the database might be generated implicitly, by a trigger, or using
|
||||
|
@ -69,18 +71,15 @@ public interface InDatabaseGenerator extends Generator {
|
|||
String[] getReferencedColumnValues(Dialect dialect);
|
||||
|
||||
/**
|
||||
* The name of a property of the entity which may be used to locate the just-{@code insert}ed
|
||||
* row containing the generated value. Of course, the columns mapped by this property should
|
||||
* form a unique key of the entity.
|
||||
* The {@link InsertGeneratedIdentifierDelegate} used to retrieve the generates value if this
|
||||
* object is an identifier generator.
|
||||
* <p>
|
||||
* This is ignored by {@link org.hibernate.metamodel.mapping.internal.GeneratedValuesProcessor},
|
||||
* which handles multiple generators at once. This method arguably breaks the separation of
|
||||
* concerns between the generator and the coordinating code.
|
||||
*
|
||||
* @see org.hibernate.id.SelectGenerator
|
||||
*/
|
||||
default String getUniqueKeyPropertyName(EntityPersister persister) {
|
||||
return null;
|
||||
default InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(PostInsertIdentityPersister persister) {
|
||||
return new BasicSelectingDelegate( persister, persister.getFactory().getJdbcServices().getDialect() );
|
||||
}
|
||||
|
||||
default boolean generatedByDatabase() {
|
||||
|
|
|
@ -9,6 +9,9 @@ package org.hibernate.id;
|
|||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.id.factory.spi.StandardGenerator;
|
||||
import org.hibernate.generator.InDatabaseGenerator;
|
||||
import org.hibernate.id.insert.BasicSelectingDelegate;
|
||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||
import org.hibernate.id.insert.InsertReturningDelegate;
|
||||
|
||||
/**
|
||||
* An {@link InDatabaseGenerator} that handles {@code IDENTITY}/"autoincrement" columns
|
||||
|
@ -16,11 +19,23 @@ import org.hibernate.generator.InDatabaseGenerator;
|
|||
* <p>
|
||||
* Delegates to the {@link org.hibernate.dialect.identity.IdentityColumnSupport} provided
|
||||
* by the {@linkplain Dialect#getIdentityColumnSupport() dialect}.
|
||||
* <p>
|
||||
* The actual work involved in retrieving the primary key value is the job of a
|
||||
* {@link org.hibernate.id.insert.InsertGeneratedIdentifierDelegate}, either:
|
||||
* <ul>
|
||||
* <li>a {@link org.hibernate.id.insert.GetGeneratedKeysDelegate},
|
||||
* <li>an {@link org.hibernate.id.insert.InsertReturningDelegate}, or a
|
||||
* <li>a {@link org.hibernate.id.insert.BasicSelectingDelegate}.
|
||||
* </ul>
|
||||
*
|
||||
* @see org.hibernate.dialect.identity.IdentityColumnSupport
|
||||
* @see org.hibernate.id.insert.InsertGeneratedIdentifierDelegate
|
||||
*
|
||||
* @author Christoph Sturm
|
||||
*/
|
||||
public class IdentityGenerator
|
||||
implements PostInsertIdentifierGenerator, BulkInsertionCapableIdentifierGenerator, StandardGenerator {
|
||||
|
||||
@Override
|
||||
public boolean referenceColumnsInSql(Dialect dialect) {
|
||||
return dialect.getIdentityColumnSupport().hasIdentityInsertKeyword();
|
||||
|
@ -30,4 +45,18 @@ public class IdentityGenerator
|
|||
public String[] getReferencedColumnValues(Dialect dialect) {
|
||||
return new String[] { dialect.getIdentityColumnSupport().getIdentityInsertString() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(PostInsertIdentityPersister persister) {
|
||||
Dialect dialect = persister.getFactory().getJdbcServices().getDialect();
|
||||
if ( persister.getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled() ) {
|
||||
return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate( persister, dialect );
|
||||
}
|
||||
else if ( dialect.getIdentityColumnSupport().supportsInsertSelectIdentity() ) {
|
||||
return new InsertReturningDelegate( persister, dialect );
|
||||
}
|
||||
else {
|
||||
return new BasicSelectingDelegate( persister, dialect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import java.util.Properties;
|
|||
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
|
||||
|
||||
/**
|
||||
* The counterpart of {@link IdentifierGenerator} for values generated by the database.
|
||||
* The counterpart to {@link IdentifierGenerator} for values generated by the database.
|
||||
* This interface is no longer the only way to handle database-generate identifiers.
|
||||
* Any {@link InDatabaseGenerator} with timing {@link EventTypeSets#INSERT_ONLY} may now
|
||||
* be used.
|
||||
|
|
|
@ -11,14 +11,16 @@ import java.util.Properties;
|
|||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.generator.InDatabaseGenerator;
|
||||
import org.hibernate.id.factory.spi.StandardGenerator;
|
||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||
import org.hibernate.id.insert.UniqueKeySelectingDelegate;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* A generator that {@code select}s the just-{@code insert}ed row to determine the
|
||||
* column value assigned by the database. The correct row is located
|
||||
* using a unique key of the entity, either:
|
||||
* column value assigned by the database. The correct row is located using a unique
|
||||
* key of the entity, either:
|
||||
* <ul>
|
||||
* <li>the mapped {@linkplain org.hibernate.annotations.NaturalId} of the entity, or
|
||||
* <li>a property specified using the parameter named {@code "key"}.
|
||||
|
@ -26,11 +28,32 @@ import org.hibernate.type.Type;
|
|||
* The second approach is provided for backward compatibility with older versions of
|
||||
* Hibernate.
|
||||
* <p>
|
||||
* This generator is intended for use with primary keys assigned by a database trigger
|
||||
* or something similar, for example:
|
||||
* <pre>{@code
|
||||
* @Entity @Table(name="TableWithPKAssignedByTrigger")
|
||||
* @GenericGenerator(name = "triggered", type = SelectGenerator.class)
|
||||
* public class TriggeredEntity {
|
||||
* @Id @GeneratedValue(generator = "triggered")
|
||||
* private Long id;
|
||||
*
|
||||
* @NaturalId
|
||||
* private String name;
|
||||
*
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
* For tables with identity/autoincrement columns, use {@link IdentityGenerator}.
|
||||
* <p>
|
||||
* The actual work involved in retrieving the primary key value is the job of
|
||||
* {@link org.hibernate.id.insert.UniqueKeySelectingDelegate}.
|
||||
* <p>
|
||||
* Arguably, this class breaks the natural separation of responsibility between the
|
||||
* {@linkplain InDatabaseGenerator generator} and the coordinating
|
||||
* code, since it's role is to specify how the generated value is <em>retrieved</em>.
|
||||
* {@linkplain InDatabaseGenerator generator} and the coordinating code, since its
|
||||
* role is to specify how the generated value is <em>retrieved</em>.
|
||||
*
|
||||
* @see org.hibernate.annotations.NaturalId
|
||||
* @see org.hibernate.id.insert.UniqueKeySelectingDelegate
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
@ -43,8 +66,12 @@ public class SelectGenerator
|
|||
uniqueKeyPropertyName = parameters.getProperty( "key" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueKeyPropertyName(EntityPersister persister) {
|
||||
/**
|
||||
* The name of a property of the entity which may be used to locate the just-{@code insert}ed
|
||||
* row containing the generated value. Of course, the columns mapped by this property should
|
||||
* form a unique key of the entity.
|
||||
*/
|
||||
protected String getUniqueKeyPropertyName(EntityPersister persister) {
|
||||
if ( uniqueKeyPropertyName != null ) {
|
||||
return uniqueKeyPropertyName;
|
||||
}
|
||||
|
@ -70,6 +97,12 @@ public class SelectGenerator
|
|||
return persister.getPropertyNames()[naturalIdPropertyIndices[0]];
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate(PostInsertIdentityPersister persister) {
|
||||
Dialect dialect = persister.getFactory().getJdbcServices().getDialect();
|
||||
return new UniqueKeySelectingDelegate( persister, dialect, getUniqueKeyPropertyName( persister ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean referenceColumnsInSql(Dialect dialect) {
|
||||
return false;
|
||||
|
|
|
@ -13,14 +13,13 @@ import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
|
|||
import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.generator.InDatabaseGenerator;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
|
||||
|
||||
/**
|
||||
* Each implementation defines a strategy for retrieving a primary key
|
||||
* {@linkplain InDatabaseGenerator generated by
|
||||
* {@linkplain org.hibernate.generator.InDatabaseGenerator generated by
|
||||
* the database} from the database after execution of an {@code insert}
|
||||
* statement. The generated primary key is usually an {@code IDENTITY}
|
||||
* column, but in principle it might be something else, for example,
|
||||
|
@ -32,9 +31,9 @@ import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
|
|||
* <li>retrieving the generated identifier value using JDBC.
|
||||
* </ul>
|
||||
* The implementation should be written to handle any instance of
|
||||
* {@link InDatabaseGenerator}.
|
||||
* {@link org.hibernate.generator.InDatabaseGenerator}.
|
||||
*
|
||||
* @see InDatabaseGenerator
|
||||
* @see org.hibernate.generator.InDatabaseGenerator
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
|
|
@ -2743,29 +2743,6 @@ public abstract class AbstractEntityPersister
|
|||
return includeProperty[getVersionProperty()] || entityMetamodel.isVersionGeneratedByDatabase();
|
||||
}
|
||||
|
||||
public boolean useGetGeneratedKeys() {
|
||||
return getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled();
|
||||
}
|
||||
|
||||
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate() {
|
||||
Dialect dialect = getFactory().getJdbcServices().getDialect();
|
||||
if ( useGetGeneratedKeys() ) {
|
||||
return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate(this, dialect );
|
||||
}
|
||||
else if ( dialect.getIdentityColumnSupport().supportsInsertSelectIdentity() ) {
|
||||
return new InsertReturningDelegate(this, dialect );
|
||||
}
|
||||
else {
|
||||
return new BasicSelectingDelegate(this, dialect );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegateForProperty(String uniqueKeyPropertyName) {
|
||||
Dialect dialect = getFactory().getJdbcServices().getDialect();
|
||||
return new UniqueKeySelectingDelegate( this, dialect, uniqueKeyPropertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentitySelectString() {
|
||||
//TODO: cache this in an instvar
|
||||
|
@ -3082,10 +3059,7 @@ public abstract class AbstractEntityPersister
|
|||
private void doLateInit() {
|
||||
if ( isIdentifierAssignedByInsert() ) {
|
||||
final InDatabaseGenerator generator = (InDatabaseGenerator) getGenerator();
|
||||
final String uniqueKeyPropertyName = generator.getUniqueKeyPropertyName(this);
|
||||
identityDelegate = uniqueKeyPropertyName == null
|
||||
? getGeneratedIdentifierDelegate()
|
||||
: getGeneratedIdentifierDelegateForProperty( uniqueKeyPropertyName );
|
||||
identityDelegate = generator.getGeneratedIdentifierDelegate( this );
|
||||
}
|
||||
|
||||
tableMappings = buildTableMappings();
|
||||
|
|
|
@ -1015,14 +1015,6 @@ public interface EntityPersister extends EntityMappingType, RootTableGroupProduc
|
|||
|
||||
boolean canUseReferenceCacheEntries();
|
||||
|
||||
default InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default InsertGeneratedIdentifierDelegate getGeneratedIdentifierDelegateForProperty(String uniqueKeyPropertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The property name of the "special" identifier property in HQL
|
||||
*
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.generator.EventType;
|
||||
import org.hibernate.id.BulkInsertionCapableIdentifierGenerator;
|
||||
import org.hibernate.id.OptimizableGenerator;
|
||||
import org.hibernate.id.PostInsertIdentityPersister;
|
||||
import org.hibernate.id.enhanced.Optimizer;
|
||||
import org.hibernate.id.insert.Binder;
|
||||
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
|
||||
|
@ -559,10 +560,8 @@ public class InsertExecutionDelegate implements TableBasedInsertHandler.Executio
|
|||
|
||||
if ( generator.generatedByDatabase() ) {
|
||||
final InDatabaseGenerator databaseGenerator = (InDatabaseGenerator) generator;
|
||||
final String uniqueKeyPropertyName = databaseGenerator.getUniqueKeyPropertyName( entityPersister );
|
||||
final InsertGeneratedIdentifierDelegate identifierDelegate = uniqueKeyPropertyName == null
|
||||
? entityPersister.getGeneratedIdentifierDelegate()
|
||||
: entityPersister.getGeneratedIdentifierDelegateForProperty( uniqueKeyPropertyName );
|
||||
final InsertGeneratedIdentifierDelegate identifierDelegate =
|
||||
databaseGenerator.getGeneratedIdentifierDelegate( (PostInsertIdentityPersister) entityPersister );
|
||||
final String finalSql = identifierDelegate.prepareIdentifierGeneratingInsert( jdbcInsert.getSqlString() );
|
||||
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
|
||||
final ValueBinder jdbcValueBinder = identifierMapping.getJdbcMapping().getJdbcValueBinder();
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.orm.test.generatedkeys.select" default-access="field">
|
||||
|
||||
<database-object>
|
||||
<create>
|
||||
<![CDATA[CREATE OR REPLACE TRIGGER t_i_my_entity
|
||||
BEFORE INSERT ON my_entity
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
select nvl( max(id), 0 ) + 1
|
||||
into :new.id
|
||||
from my_entity;
|
||||
END;]]>
|
||||
</create>
|
||||
<drop>
|
||||
<![CDATA[DROP TRIGGER t_i_my_entity]]>
|
||||
</drop>
|
||||
<dialect-scope name="org.hibernate.dialect.OracleDialect"/>
|
||||
</database-object>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.generatedkeys.selectannotated;
|
||||
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
import org.hibernate.id.SelectGenerator;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:steve@hibernate.org">Steve Ebersole </a>
|
||||
*/
|
||||
@Entity @Table(name="my_entity")
|
||||
@GenericGenerator(name = "triggered", type = SelectGenerator.class)
|
||||
public class MyEntity {
|
||||
@Id @GeneratedValue(generator = "triggered")
|
||||
private Long id;
|
||||
|
||||
@NaturalId
|
||||
private String name;
|
||||
|
||||
public MyEntity() {
|
||||
}
|
||||
|
||||
public MyEntity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.generatedkeys.selectannotated;
|
||||
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = MyEntity.class,
|
||||
xmlMappings = "org/hibernate/orm/test/generatedkeys/selectannotated/MyEntity.hbm.xml"
|
||||
)
|
||||
@SessionFactory
|
||||
@RequiresDialect(value = OracleDialect.class)
|
||||
public class SelectGeneratorTest {
|
||||
|
||||
@Test
|
||||
public void testJDBC3GetGeneratedKeysSupportOnOracle(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
MyEntity e = new MyEntity( "entity-1" );
|
||||
session.persist( e );
|
||||
|
||||
// this insert should happen immediately!
|
||||
assertEquals( Long.valueOf( 1L ), e.getId(), "id not generated through forced insertion" );
|
||||
|
||||
session.remove( e );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@JiraKey("HHH-15900")
|
||||
public void testGeneratedKeyNotIdentityColumn(SessionFactoryScope scope) throws IOException {
|
||||
File output = File.createTempFile( "schema_export", ".sql" );
|
||||
output.deleteOnExit();
|
||||
|
||||
final SchemaExport schemaExport = new SchemaExport();
|
||||
schemaExport.setOutputFile( output.getAbsolutePath() );
|
||||
schemaExport.execute(
|
||||
EnumSet.of( TargetType.SCRIPT ),
|
||||
SchemaExport.Action.CREATE,
|
||||
scope.getMetadataImplementor()
|
||||
);
|
||||
|
||||
String fileContent = new String( Files.readAllBytes( output.toPath() ) );
|
||||
assertFalse( fileContent.toLowerCase().contains( "identity" ), "Column was generated as identity" );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue