HHH-10422 - Add test for issue (from HHH-9983)

(cherry picked from commit 1f3048e572)

HHH-10422 - Fix Error saving entity with identity id on Oracle 12c (from HHH-9983)

(cherry picked from commit 33458ab6f8)

Conflicts:
	hibernate-core/src/main/java/org/hibernate/dialect/Oracle12cDialect.java
	hibernate-core/src/main/java/org/hibernate/dialect/identity/Oracle12cIdentityColumnSupport.java

HHH-10422 : Backport HHH-9983 to fix identity IDs using Oracle12cDialect in 5.0

HHH-10422 : Custom identity support test

HHH-10422 : Custom identity support test
This commit is contained in:
Andrea Boriero 2015-09-02 11:14:00 +01:00 committed by Steve Ebersole
parent de3ce125bc
commit 659157a45c
16 changed files with 601 additions and 66 deletions

View File

@ -40,6 +40,8 @@ import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate; import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions; import org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions;
import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupportImpl;
import org.hibernate.dialect.lock.LockingStrategy; import org.hibernate.dialect.lock.LockingStrategy;
import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy; import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy;
import org.hibernate.dialect.lock.OptimisticLockingStrategy; import org.hibernate.dialect.lock.OptimisticLockingStrategy;
@ -728,7 +730,7 @@ public abstract class Dialect implements ConversionContext {
* @return The native generator class. * @return The native generator class.
*/ */
public Class getNativeIdentifierGeneratorClass() { public Class getNativeIdentifierGeneratorClass() {
if ( supportsIdentityColumns() ) { if ( getIdentityColumnSupport().supportsIdentityColumns() ) {
return IdentityGenerator.class; return IdentityGenerator.class;
} }
else { else {
@ -739,11 +741,25 @@ public abstract class Dialect implements ConversionContext {
// IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Get the appropriate {@link IdentityColumnSupport}
*
* @return the IdentityColumnSupport
*/
public IdentityColumnSupport getIdentityColumnSupport(){
return new IdentityColumnSupportImpl( this );
}
/** /**
* Does this dialect support identity column key generation? * Does this dialect support identity column key generation?
* *
* @return True if IDENTITY columns are supported; false otherwise. * @return True if IDENTITY columns are supported; false otherwise.
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().supportsIdentityColumns()} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public boolean supportsIdentityColumns() { public boolean supportsIdentityColumns() {
return false; return false;
} }
@ -754,7 +770,12 @@ public abstract class Dialect implements ConversionContext {
* *
* @return True if the dialect supports selecting the just * @return True if the dialect supports selecting the just
* generated IDENTITY in the insert statement. * generated IDENTITY in the insert statement.
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().supportsInsertSelectIdentity()} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public boolean supportsInsertSelectIdentity() { public boolean supportsInsertSelectIdentity() {
return false; return false;
} }
@ -764,7 +785,12 @@ public abstract class Dialect implements ConversionContext {
* completely separate identity data type * completely separate identity data type
* *
* @return boolean * @return boolean
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().hasDataTypeInIdentityColumn()} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public boolean hasDataTypeInIdentityColumn() { public boolean hasDataTypeInIdentityColumn() {
return true; return true;
} }
@ -779,7 +805,12 @@ public abstract class Dialect implements ConversionContext {
* @param insertString The insert command * @param insertString The insert command
* @return The insert command with any necessary identity select * @return The insert command with any necessary identity select
* clause attached. * clause attached.
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().appendIdentitySelectToInsert(String)} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public String appendIdentitySelectToInsert(String insertString) { public String appendIdentitySelectToInsert(String insertString) {
return insertString; return insertString;
} }
@ -793,7 +824,12 @@ public abstract class Dialect implements ConversionContext {
* @param type The {@link java.sql.Types} type code. * @param type The {@link java.sql.Types} type code.
* @return The appropriate select command * @return The appropriate select command
* @throws MappingException If IDENTITY generation is not supported. * @throws MappingException If IDENTITY generation is not supported.
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().getIdentitySelectString(String,String,int)} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public String getIdentitySelectString(String table, String column, int type) throws MappingException { public String getIdentitySelectString(String table, String column, int type) throws MappingException {
return getIdentitySelectString(); return getIdentitySelectString();
} }
@ -819,7 +855,12 @@ public abstract class Dialect implements ConversionContext {
* @param type The {@link java.sql.Types} type code. * @param type The {@link java.sql.Types} type code.
* @return The appropriate DDL fragment. * @return The appropriate DDL fragment.
* @throws MappingException If IDENTITY generation is not supported. * @throws MappingException If IDENTITY generation is not supported.
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().getIdentityColumnString(int)} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public String getIdentityColumnString(int type) throws MappingException { public String getIdentityColumnString(int type) throws MappingException {
return getIdentityColumnString(); return getIdentityColumnString();
} }
@ -842,7 +883,12 @@ public abstract class Dialect implements ConversionContext {
* Need if the dialect does not support inserts that specify no column values. * Need if the dialect does not support inserts that specify no column values.
* *
* @return The appropriate keyword. * @return The appropriate keyword.
*
* @deprecated {@link #getIdentityColumnSupport()} should be overridden instead;
* if {@code getIdentityColumnSupport().getIdentityInsertString()} does not delegate
* to this method, then this method is ignored.
*/ */
@Deprecated
public String getIdentityInsertString() { public String getIdentityInsertString() {
return null; return null;
} }

View File

@ -7,6 +7,8 @@
package org.hibernate.dialect; package org.hibernate.dialect;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.identity.Oracle12cIdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler; import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler;
import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator;
@ -38,6 +40,7 @@ public class Oracle12cDialect extends Oracle10gDialect {
return true; return true;
} }
@Override
public Class getNativeIdentifierGeneratorClass() { public Class getNativeIdentifierGeneratorClass() {
return SequenceStyleGenerator.class; return SequenceStyleGenerator.class;
} }
@ -52,4 +55,8 @@ public class Oracle12cDialect extends Oracle10gDialect {
return SQL2008StandardLimitHandler.INSTANCE; return SQL2008StandardLimitHandler.INSTANCE;
} }
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new Oracle12cIdentityColumnSupport( this );
}
} }

View File

@ -0,0 +1,73 @@
/*
* 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;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.id.insert.AbstractReturningDelegate;
import org.hibernate.id.insert.IdentifierGeneratingInsert;
import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
/**
* Delegate for dealing with IDENTITY columns using JDBC3 getGeneratedKeys
*
* @author Andrea Boriero
*/
public class GetGeneratedKeysDelegate
extends AbstractReturningDelegate
implements InsertGeneratedIdentifierDelegate {
private final PostInsertIdentityPersister persister;
private final Dialect dialect;
public GetGeneratedKeysDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
super( persister );
this.persister = persister;
this.dialect = dialect;
}
@Override
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect );
insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[0] );
return insert;
}
@Override
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, PreparedStatement.RETURN_GENERATED_KEYS );
}
@Override
public Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session)
throws SQLException {
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
ResultSet rs = null;
try {
rs = insert.getGeneratedKeys();
return IdentifierGeneratorHelper.getGeneratedIdentity(
rs,
persister.getRootTableKeyColumnNames()[0],
persister.getIdentifierType()
);
}
finally {
if ( rs != null ) {
session.getJdbcCoordinator().getResourceRegistry().release( rs, insert );
}
}
}
}

View File

@ -0,0 +1,104 @@
/*
* 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;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.PostInsertIdentityPersister;
/**
* Represents a support for the Dialect identity key generation
*
* @author Andrea Boriero
*/
public interface IdentityColumnSupport {
/**
* Does this dialect support identity column key generation?
*
* @return True if IDENTITY columns are supported; false otherwise.
*/
public boolean supportsIdentityColumns();
/**
* Does the dialect support some form of inserting and selecting
* the generated IDENTITY value all in the same statement.
*
* @return True if the dialect supports selecting the just
* generated IDENTITY in the insert statement.
*/
public boolean supportsInsertSelectIdentity();
/**
* Whether this dialect have an Identity clause added to the data type or a
* completely separate identity data type
*
* @return boolean
*/
public boolean hasDataTypeInIdentityColumn();
/**
* 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 insertString The insert command
*
* @return The insert command with any necessary identity select
* clause attached.
*/
public String appendIdentitySelectToInsert(String insertString);
/**
* Get the select command to use to retrieve the last generated IDENTITY
* value for a particular table
*
* @param table The table into which the insert was done
* @param column The PK column.
* @param type The {@link java.sql.Types} type code.
*
* @return The appropriate select command
*
* @throws MappingException If IDENTITY generation is not supported.
*/
public String getIdentitySelectString(String table, String column, int type) throws MappingException;
/**
* The syntax used during DDL to define a column as being an IDENTITY of
* a particular type.
*
* @param type The {@link java.sql.Types} type code.
*
* @return The appropriate DDL fragment.
*
* @throws MappingException If IDENTITY generation is not supported.
*/
public String getIdentityColumnString(int type) throws MappingException;
/**
* The keyword used to insert a generated value into an identity column (or null).
* Need if the dialect does not support inserts that specify no column values.
*
* @return The appropriate keyword.
*/
public String getIdentityInsertString();
/**
* The Delegate for dealing with IDENTITY columns using JDBC3 getGeneratedKeys
*
* @param persister The persister
* @param dialect The dialect against which to generate the delegate
*
* @return the dialect specific GetGeneratedKeys delegate
*/
public GetGeneratedKeysDelegate buildGetGeneratedKeysDelegate(
PostInsertIdentityPersister persister,
Dialect dialect);
}

View File

@ -0,0 +1,64 @@
/*
* 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;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.PostInsertIdentityPersister;
/**
* @author Andrea Boriero
*/
public class IdentityColumnSupportImpl implements IdentityColumnSupport {
private final Dialect dialect;
public IdentityColumnSupportImpl(Dialect dialect) {
this.dialect = dialect;
}
@Override
public boolean supportsIdentityColumns() {
return dialect.supportsIdentityColumns();
}
@Override
public boolean supportsInsertSelectIdentity() {
return dialect.supportsInsertSelectIdentity();
}
@Override
public boolean hasDataTypeInIdentityColumn() {
return dialect.hasDataTypeInIdentityColumn();
}
@Override
public String appendIdentitySelectToInsert(String insertString) {
return dialect.appendIdentitySelectToInsert( insertString );
}
@Override
public String getIdentitySelectString(String table, String column, int type) throws MappingException {
return dialect.getIdentitySelectString( table, column, type );
}
@Override
public String getIdentityColumnString(int type) throws MappingException {
return dialect.getIdentityColumnString( type );
}
@Override
public String getIdentityInsertString() {
return dialect.getIdentityInsertString();
}
@Override
public GetGeneratedKeysDelegate buildGetGeneratedKeysDelegate(
PostInsertIdentityPersister persister,
Dialect dialect) {
return new GetGeneratedKeysDelegate( persister, dialect );
}
}

View File

@ -0,0 +1,40 @@
/*
* 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;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.identity.GetGeneratedKeysDelegate;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.PostInsertIdentityPersister;
/**
* @author Andrea Boriero
*/
public class Oracle12cGetGeneratedKeysDelegate extends GetGeneratedKeysDelegate {
private String[] keyColumns;
public Oracle12cGetGeneratedKeysDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
super( persister, dialect );
this.keyColumns = getPersister().getRootTableKeyColumnNames();
if ( keyColumns.length > 1 ) {
throw new HibernateException( "Identity generator cannot be used with multi-column keys" );
}
}
@Override
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, keyColumns );
}
}

View File

@ -0,0 +1,26 @@
/*
* 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;
import org.hibernate.dialect.Dialect;
import org.hibernate.id.PostInsertIdentityPersister;
/**
* @author Andrea Boriero
*/
public class Oracle12cIdentityColumnSupport extends IdentityColumnSupportImpl {
public Oracle12cIdentityColumnSupport(Dialect dialect) {
super( dialect );
}
@Override
public GetGeneratedKeysDelegate buildGetGeneratedKeysDelegate(
PostInsertIdentityPersister persister, Dialect dialect) {
return new Oracle12cGetGeneratedKeysDelegate( persister, dialect );
}
}

View File

@ -38,9 +38,9 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
Dialect dialect, Dialect dialect,
boolean isGetGeneratedKeysEnabled) throws HibernateException { boolean isGetGeneratedKeysEnabled) throws HibernateException {
if ( isGetGeneratedKeysEnabled ) { if ( isGetGeneratedKeysEnabled ) {
return new GetGeneratedKeysDelegate( persister, dialect ); return dialect.getIdentityColumnSupport().buildGetGeneratedKeysDelegate( persister, dialect );
} }
else if ( dialect.supportsInsertSelectIdentity() ) { else if ( dialect.getIdentityColumnSupport().supportsInsertSelectIdentity() ) {
return new InsertSelectDelegate( persister, dialect ); return new InsertSelectDelegate( persister, dialect );
} }
else { else {
@ -48,56 +48,7 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
} }
} }
/**
* Delegate for dealing with IDENTITY columns using JDBC3 getGeneratedKeys
*/
public static class GetGeneratedKeysDelegate
extends AbstractReturningDelegate
implements InsertGeneratedIdentifierDelegate {
private final PostInsertIdentityPersister persister;
private final Dialect dialect;
public GetGeneratedKeysDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
super( persister );
this.persister = persister;
this.dialect = dialect;
}
@Override
public IdentifierGeneratingInsert prepareIdentifierGeneratingInsert() {
IdentifierGeneratingInsert insert = new IdentifierGeneratingInsert( dialect );
insert.addIdentityColumn( persister.getRootTableKeyColumnNames()[0] );
return insert;
}
@Override
protected PreparedStatement prepare(String insertSQL, SessionImplementor session) throws SQLException {
return session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( insertSQL, PreparedStatement.RETURN_GENERATED_KEYS );
}
@Override
public Serializable executeAndExtract(PreparedStatement insert, SessionImplementor session)
throws SQLException {
session.getJdbcCoordinator().getResultSetReturn().executeUpdate( insert );
ResultSet rs = null;
try {
rs = insert.getGeneratedKeys();
return IdentifierGeneratorHelper.getGeneratedIdentity(
rs,
persister.getRootTableKeyColumnNames()[0],
persister.getIdentifierType()
);
}
finally {
if ( rs != null ) {
session.getJdbcCoordinator().getResourceRegistry().release( rs, insert );
}
}
}
}
/** /**
* Delegate for dealing with IDENTITY columns where the dialect supports returning * Delegate for dealing with IDENTITY columns where the dialect supports returning

View File

@ -20,6 +20,6 @@ public class InsertSelectIdentityInsert extends IdentifierGeneratingInsert {
} }
public String toStatementString() { public String toStatementString() {
return getDialect().appendIdentitySelectToInsert( super.toStatementString() ); return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( super.toStatementString() );
} }
} }

View File

@ -535,11 +535,11 @@ public class Table implements RelationalModel, Serializable, Exportable {
if ( identityColumn && col.getQuotedName( dialect ).equals( pkname ) ) { if ( identityColumn && col.getQuotedName( dialect ).equals( pkname ) ) {
// to support dialects that have their own identity data type // to support dialects that have their own identity data type
if ( dialect.hasDataTypeInIdentityColumn() ) { if ( dialect.getIdentityColumnSupport().hasDataTypeInIdentityColumn() ) {
buf.append( col.getSqlType( dialect, p ) ); buf.append( col.getSqlType( dialect, p ) );
} }
buf.append( ' ' ) buf.append( ' ' )
.append( dialect.getIdentityColumnString( col.getSqlTypeCode( p ) ) ); .append( dialect.getIdentityColumnSupport().getIdentityColumnString( col.getSqlTypeCode( p ) ) );
} }
else { else {

View File

@ -2496,7 +2496,7 @@ public abstract class AbstractEntityPersister
// append the SQL to return the generated identifier // append the SQL to return the generated identifier
if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { //TODO: suck into Insert if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { //TODO: suck into Insert
result = getFactory().getDialect().appendIdentitySelectToInsert( result ); result = getFactory().getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( result );
} }
return result; return result;
@ -2748,7 +2748,7 @@ public abstract class AbstractEntityPersister
} }
protected boolean useInsertSelectIdentity() { protected boolean useInsertSelectIdentity() {
return !useGetGeneratedKeys() && getFactory().getDialect().supportsInsertSelectIdentity(); return !useGetGeneratedKeys() && getFactory().getDialect().getIdentityColumnSupport().supportsInsertSelectIdentity();
} }
protected boolean useGetGeneratedKeys() { protected boolean useGetGeneratedKeys() {
@ -2794,11 +2794,12 @@ public abstract class AbstractEntityPersister
public String getIdentitySelectString() { public String getIdentitySelectString() {
//TODO: cache this in an instvar //TODO: cache this in an instvar
return getFactory().getDialect().getIdentitySelectString( return getFactory().getDialect().getIdentityColumnSupport()
getTableName( 0 ), .getIdentitySelectString(
getKeyColumns( 0 )[0], getTableName( 0 ),
getIdentifierType().sqlTypes( getFactory() )[0] getKeyColumns( 0 )[0],
); getIdentifierType().sqlTypes( getFactory() )[0]
);
} }
public String getSelectByUniqueKeyString(String propertyName) { public String getSelectByUniqueKeyString(String propertyName) {

View File

@ -75,7 +75,7 @@ public class Insert {
} }
public Insert addIdentityColumn(String columnName) { public Insert addIdentityColumn(String columnName) {
String value = dialect.getIdentityInsertString(); String value = dialect.getIdentityColumnSupport().getIdentityInsertString();
if ( value != null ) { if ( value != null ) {
addColumn( columnName, value ); addColumn( columnName, value );
} }

View File

@ -86,11 +86,11 @@ public class StandardTableExporter implements Exporter<Table> {
if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) { if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) {
// to support dialects that have their own identity data type // to support dialects that have their own identity data type
if ( dialect.hasDataTypeInIdentityColumn() ) { if ( dialect.getIdentityColumnSupport().hasDataTypeInIdentityColumn() ) {
buf.append( col.getSqlType( dialect, metadata ) ); buf.append( col.getSqlType( dialect, metadata ) );
} }
buf.append( ' ' ) buf.append( ' ' )
.append( dialect.getIdentityColumnString( col.getSqlTypeCode( metadata ) ) ); .append( dialect.getIdentityColumnSupport().getIdentityColumnString( col.getSqlTypeCode( metadata ) ) );
} }
else { else {
buf.append( col.getSqlType( dialect, metadata ) ); buf.append( col.getSqlType( dialect, metadata ) );

View File

@ -0,0 +1,145 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: Apache License, Version 2.0
* See the LICENSE file in the root directory or visit http://www.apache.org/licenses/LICENSE-2.0
*/
package org.hibernate.test.idgen.identity;
import org.junit.Test;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.identity.GetGeneratedKeysDelegate;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.id.PostInsertIdentityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* @author Gail Badner
*/
@TestForIssue( jiraKey = "HHH-10422")
public class CustomIdentityColumnSupportTest extends BaseUnitTestCase {
@Test
public void testLegacyIdentityColumnSupport() {
testIdentityColumnSupport( new LegacyIdentityColumnSupportDialect().getIdentityColumnSupport() );
}
@Test
public void testCustomIdentityColumnSupport() {
testIdentityColumnSupport( new IdentityColumnSupportDialect().getIdentityColumnSupport() );
}
private void testIdentityColumnSupport(IdentityColumnSupport support) {
assertEquals( true, support.supportsIdentityColumns() );
assertEquals( true, support.supportsInsertSelectIdentity() );
assertEquals( false, support.hasDataTypeInIdentityColumn() );
assertEquals( "abcInsertString", support.appendIdentitySelectToInsert( "InsertString" ) );
try {
support.getIdentitySelectString( "a", "b", 1 );
fail( "should have thrown MappingException" );
}
catch( MappingException ex ) {
assertEquals( "blah", ex.getMessage() );
}
try {
support.getIdentityColumnString( 1 );
fail( "should have thrown MappingException" );
}
catch( MappingException ex ) {
assertEquals( "blah, blah", ex.getMessage() );
}
assertEquals( "insert string", support.getIdentityInsertString() );
}
private static class LegacyIdentityColumnSupportDialect extends Dialect {
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public boolean supportsInsertSelectIdentity() {
return true;
}
@Override
public boolean hasDataTypeInIdentityColumn() {
return false;
}
@Override
public String appendIdentitySelectToInsert(String insertString) {
return "abc" + insertString;
}
@Override
public String getIdentitySelectString(String table, String column, int type) throws MappingException {
throw new MappingException( "blah" );
}
@Override
public String getIdentityColumnString(int type) throws MappingException {
throw new MappingException( "blah, blah" );
}
@Override
public String getIdentityInsertString() {
return "insert string";
}
}
private static class IdentityColumnSupportDialect extends Dialect {
public IdentityColumnSupport getIdentityColumnSupport(){
return new IdentityColumnSupport() {
@Override
public boolean supportsIdentityColumns() {
return true;
}
@Override
public boolean supportsInsertSelectIdentity() {
return true;
}
@Override
public boolean hasDataTypeInIdentityColumn() {
return false;
}
@Override
public String appendIdentitySelectToInsert(String insertString) {
return "abc" + insertString;
}
@Override
public String getIdentitySelectString(String table, String column, int type) throws MappingException {
throw new MappingException( "blah" );
}
@Override
public String getIdentityColumnString(int type) throws MappingException {
throw new MappingException( "blah, blah" );
}
@Override
public String getIdentityInsertString() {
return "insert string";
}
@Override
public GetGeneratedKeysDelegate buildGetGeneratedKeysDelegate(PostInsertIdentityPersister persister, Dialect dialect) {
return new GetGeneratedKeysDelegate( persister, dialect );
}
};
}
}
}

View File

@ -0,0 +1,78 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: Apache License, Version 2.0
* See the LICENSE file in the root directory or visit http://www.apache.org/licenses/LICENSE-2.0
*/
package org.hibernate.test.idgen.identity.hhh9983;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.dialect.Oracle12cDialect;
import org.junit.Test;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* @author Andrea Boriero
*/
@TestForIssue(jiraKey = "HHH-9983")
@RequiresDialect(Oracle12cDialect.class)
public class SaveEntityTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {Company.class};
}
@Test
public void testSave() {
Session s = openSession();
Transaction transaction = s.beginTransaction();
try {
s.save( new Company() );
s.getTransaction().commit();
}
finally {
s.close();
}
}
@Entity
@Table(name = "Company")
public class Company {
private Integer id;
private String name;
public Company() {
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -35,7 +35,7 @@ abstract public class DialectChecks {
public static class SupportsIdentityColumns implements DialectCheck { public static class SupportsIdentityColumns implements DialectCheck {
public boolean isMatch(Dialect dialect) { public boolean isMatch(Dialect dialect) {
return dialect.supportsIdentityColumns(); return dialect.getIdentityColumnSupport().supportsIdentityColumns();
} }
} }