HHH-15561 - Fixed and added test for issue
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
f13230803d
commit
0baefce734
|
@ -28,6 +28,7 @@ import org.hibernate.dialect.SimpleDatabaseVersion;
|
||||||
import org.hibernate.dialect.TimeZoneSupport;
|
import org.hibernate.dialect.TimeZoneSupport;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.hint.IndexQueryHintHandler;
|
import org.hibernate.dialect.hint.IndexQueryHintHandler;
|
||||||
|
import org.hibernate.dialect.identity.H2FinalTableIdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
|
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
|
@ -774,7 +775,7 @@ public class H2LegacyDialect extends Dialect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||||
return new H2IdentityColumnSupport();
|
return getVersion().isSameOrAfter( 2 ) ? H2FinalTableIdentityColumnSupport.INSTANCE : H2IdentityColumnSupport.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.PessimisticLockException;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
import org.hibernate.dialect.hint.IndexQueryHintHandler;
|
import org.hibernate.dialect.hint.IndexQueryHintHandler;
|
||||||
|
import org.hibernate.dialect.identity.H2FinalTableIdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
|
import org.hibernate.dialect.identity.H2IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
import org.hibernate.dialect.identity.IdentityColumnSupport;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
|
@ -741,7 +742,7 @@ public class H2Dialect extends Dialect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||||
return new H2IdentityColumnSupport();
|
return getVersion().isSameOrAfter( 2 ) ? H2FinalTableIdentityColumnSupport.INSTANCE : H2IdentityColumnSupport.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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.dialect.identity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identity column support for H2 2+ versions
|
||||||
|
* @author Jan Schatteman
|
||||||
|
*/
|
||||||
|
public class H2FinalTableIdentityColumnSupport extends H2IdentityColumnSupport {
|
||||||
|
|
||||||
|
public static final H2FinalTableIdentityColumnSupport INSTANCE = new H2FinalTableIdentityColumnSupport();
|
||||||
|
|
||||||
|
private H2FinalTableIdentityColumnSupport() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsInsertSelectIdentity() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String appendIdentitySelectToInsert(String identityColumnName, String insertString) {
|
||||||
|
return "select " + identityColumnName + " from final table ( " + insertString + " )";
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,12 @@ package org.hibernate.dialect.identity;
|
||||||
* @author Andrea Boriero
|
* @author Andrea Boriero
|
||||||
*/
|
*/
|
||||||
public class H2IdentityColumnSupport extends IdentityColumnSupportImpl {
|
public class H2IdentityColumnSupport extends IdentityColumnSupportImpl {
|
||||||
|
|
||||||
|
public static final H2IdentityColumnSupport INSTANCE = new H2IdentityColumnSupport();
|
||||||
|
|
||||||
|
protected H2IdentityColumnSupport() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsIdentityColumns() {
|
public boolean supportsIdentityColumns() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -57,6 +57,23 @@ public interface IdentityColumnSupport {
|
||||||
*/
|
*/
|
||||||
String appendIdentitySelectToInsert(String insertString);
|
String appendIdentitySelectToInsert(String insertString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provided we {@link #supportsInsertSelectIdentity}, then attach the
|
||||||
|
* "select identity" clause to the insert statement.
|
||||||
|
* <p/>
|
||||||
|
* Note, if {@link #supportsInsertSelectIdentity} == false then
|
||||||
|
* the insert-string should be returned without modification.
|
||||||
|
*
|
||||||
|
* @param identityColumnName The name of the identity column
|
||||||
|
* @param insertString The insert command
|
||||||
|
*
|
||||||
|
* @return The insert command with any necessary identity select
|
||||||
|
* clause attached.
|
||||||
|
*/
|
||||||
|
default String appendIdentitySelectToInsert(String identityColumnName, String insertString) {
|
||||||
|
return appendIdentitySelectToInsert( insertString );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the select command to use to retrieve the last generated IDENTITY
|
* Get the select command to use to retrieve the last generated IDENTITY
|
||||||
* value for a particular table
|
* value for a particular table
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.id.insert;
|
package org.hibernate.id.insert;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.sql.Insert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialized IdentifierGeneratingInsert which appends the database
|
* Specialized IdentifierGeneratingInsert which appends the database
|
||||||
|
@ -15,11 +16,18 @@ import org.hibernate.dialect.Dialect;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class InsertSelectIdentityInsert extends IdentifierGeneratingInsert {
|
public class InsertSelectIdentityInsert extends IdentifierGeneratingInsert {
|
||||||
|
protected String identityColumnName;
|
||||||
|
|
||||||
|
public Insert addIdentityColumn(String columnName) {
|
||||||
|
identityColumnName = columnName;
|
||||||
|
return super.addIdentityColumn( columnName );
|
||||||
|
}
|
||||||
|
|
||||||
public InsertSelectIdentityInsert(Dialect dialect) {
|
public InsertSelectIdentityInsert(Dialect dialect) {
|
||||||
super( dialect );
|
super( dialect );
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toStatementString() {
|
public String toStatementString() {
|
||||||
return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( super.toStatementString() );
|
return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( identityColumnName, super.toStatementString() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* 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.id;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.dialect.H2Dialect;
|
||||||
|
|
||||||
|
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.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jan Schatteman
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-15561")
|
||||||
|
@RequiresDialect( value = H2Dialect.class )
|
||||||
|
public class IdentityIdEntityTest {
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void cleanup(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> session.createMutationQuery( "delete from id_entity" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@ServiceRegistry(
|
||||||
|
settings = { @Setting( name = AvailableSettings.USE_GET_GENERATED_KEYS, value = "false") }
|
||||||
|
)
|
||||||
|
@DomainModel( annotatedClasses = { IdentityEntity.class } )
|
||||||
|
@SessionFactory
|
||||||
|
public void testIdentityEntityWithDisabledGetGeneratedKeys(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
try {
|
||||||
|
IdentityEntity ie = new IdentityEntity();
|
||||||
|
ie.setTimestamp( new Date() );
|
||||||
|
session.persist( ie );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( "Creation of an IDENTITY-id-based entity failed when \"hibernate.jdbc.use_get_generated_keys\" was set to false (" + e.getMessage() + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@ServiceRegistry(
|
||||||
|
settings = { @Setting( name = "use_jdbc_metadata_defaults", value = "false") }
|
||||||
|
)
|
||||||
|
@DomainModel( annotatedClasses = { IdentityEntity.class } )
|
||||||
|
@SessionFactory
|
||||||
|
public void testIdentityEntityWithDisabledJdbcMetadataDefaults(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
try {
|
||||||
|
IdentityEntity ie = new IdentityEntity();
|
||||||
|
ie.setTimestamp( new Date() );
|
||||||
|
session.persist( ie );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fail( "Creation of an IDENTITY-id-based entity failed when \"use_jdbc_metadata_defaults\" was set to false (" + e.getMessage() + ")" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "id_entity")
|
||||||
|
public static class IdentityEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private Date timestamp;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(Date timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue