HHH-10422 - Add test for issue (from HHH-9983)
(cherry picked from commit1f3048e572
) HHH-10422 - Fix Error saving entity with identity id on Oracle 12c (from HHH-9983) (cherry picked from commit33458ab6f8
) 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:
parent
de3ce125bc
commit
659157a45c
|
@ -40,6 +40,8 @@ import org.hibernate.dialect.function.SQLFunction;
|
|||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||
import org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions;
|
||||
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.OptimisticForceIncrementLockingStrategy;
|
||||
import org.hibernate.dialect.lock.OptimisticLockingStrategy;
|
||||
|
@ -728,7 +730,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
* @return The native generator class.
|
||||
*/
|
||||
public Class getNativeIdentifierGeneratorClass() {
|
||||
if ( supportsIdentityColumns() ) {
|
||||
if ( getIdentityColumnSupport().supportsIdentityColumns() ) {
|
||||
return IdentityGenerator.class;
|
||||
}
|
||||
else {
|
||||
|
@ -739,11 +741,25 @@ public abstract class Dialect implements ConversionContext {
|
|||
|
||||
// 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?
|
||||
*
|
||||
* @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() {
|
||||
return false;
|
||||
}
|
||||
|
@ -754,7 +770,12 @@ public abstract class Dialect implements ConversionContext {
|
|||
*
|
||||
* @return True if the dialect supports selecting the just
|
||||
* 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() {
|
||||
return false;
|
||||
}
|
||||
|
@ -764,7 +785,12 @@ public abstract class Dialect implements ConversionContext {
|
|||
* completely separate identity data type
|
||||
*
|
||||
* @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() {
|
||||
return true;
|
||||
}
|
||||
|
@ -779,7 +805,12 @@ public abstract class Dialect implements ConversionContext {
|
|||
* @param insertString The insert command
|
||||
* @return The insert command with any necessary identity select
|
||||
* 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) {
|
||||
return insertString;
|
||||
}
|
||||
|
@ -793,7 +824,12 @@ public abstract class Dialect implements ConversionContext {
|
|||
* @param type The {@link java.sql.Types} type code.
|
||||
* @return The appropriate select command
|
||||
* @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 {
|
||||
return getIdentitySelectString();
|
||||
}
|
||||
|
@ -819,7 +855,12 @@ public abstract class Dialect implements ConversionContext {
|
|||
* @param type The {@link java.sql.Types} type code.
|
||||
* @return The appropriate DDL fragment.
|
||||
* @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 {
|
||||
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.
|
||||
*
|
||||
* @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() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.dialect;
|
||||
|
||||
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.SQL2008StandardLimitHandler;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
|
@ -38,6 +40,7 @@ public class Oracle12cDialect extends Oracle10gDialect {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getNativeIdentifierGeneratorClass() {
|
||||
return SequenceStyleGenerator.class;
|
||||
}
|
||||
|
@ -52,4 +55,8 @@ public class Oracle12cDialect extends Oracle10gDialect {
|
|||
return SQL2008StandardLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||
return new Oracle12cIdentityColumnSupport( this );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -38,9 +38,9 @@ public class IdentityGenerator extends AbstractPostInsertGenerator {
|
|||
Dialect dialect,
|
||||
boolean isGetGeneratedKeysEnabled) throws HibernateException {
|
||||
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 );
|
||||
}
|
||||
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
|
||||
|
|
|
@ -20,6 +20,6 @@ public class InsertSelectIdentityInsert extends IdentifierGeneratingInsert {
|
|||
}
|
||||
|
||||
public String toStatementString() {
|
||||
return getDialect().appendIdentitySelectToInsert( super.toStatementString() );
|
||||
return getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( super.toStatementString() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -535,11 +535,11 @@ public class Table implements RelationalModel, Serializable, Exportable {
|
|||
|
||||
if ( identityColumn && col.getQuotedName( dialect ).equals( pkname ) ) {
|
||||
// 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( ' ' )
|
||||
.append( dialect.getIdentityColumnString( col.getSqlTypeCode( p ) ) );
|
||||
.append( dialect.getIdentityColumnSupport().getIdentityColumnString( col.getSqlTypeCode( p ) ) );
|
||||
}
|
||||
else {
|
||||
|
||||
|
|
|
@ -2496,7 +2496,7 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
// append the SQL to return the generated identifier
|
||||
if ( j == 0 && identityInsert && useInsertSelectIdentity() ) { //TODO: suck into Insert
|
||||
result = getFactory().getDialect().appendIdentitySelectToInsert( result );
|
||||
result = getFactory().getDialect().getIdentityColumnSupport().appendIdentitySelectToInsert( result );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2748,7 +2748,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
|
||||
protected boolean useInsertSelectIdentity() {
|
||||
return !useGetGeneratedKeys() && getFactory().getDialect().supportsInsertSelectIdentity();
|
||||
return !useGetGeneratedKeys() && getFactory().getDialect().getIdentityColumnSupport().supportsInsertSelectIdentity();
|
||||
}
|
||||
|
||||
protected boolean useGetGeneratedKeys() {
|
||||
|
@ -2794,11 +2794,12 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
public String getIdentitySelectString() {
|
||||
//TODO: cache this in an instvar
|
||||
return getFactory().getDialect().getIdentitySelectString(
|
||||
getTableName( 0 ),
|
||||
getKeyColumns( 0 )[0],
|
||||
getIdentifierType().sqlTypes( getFactory() )[0]
|
||||
);
|
||||
return getFactory().getDialect().getIdentityColumnSupport()
|
||||
.getIdentitySelectString(
|
||||
getTableName( 0 ),
|
||||
getKeyColumns( 0 )[0],
|
||||
getIdentifierType().sqlTypes( getFactory() )[0]
|
||||
);
|
||||
}
|
||||
|
||||
public String getSelectByUniqueKeyString(String propertyName) {
|
||||
|
|
|
@ -75,7 +75,7 @@ public class Insert {
|
|||
}
|
||||
|
||||
public Insert addIdentityColumn(String columnName) {
|
||||
String value = dialect.getIdentityInsertString();
|
||||
String value = dialect.getIdentityColumnSupport().getIdentityInsertString();
|
||||
if ( value != null ) {
|
||||
addColumn( columnName, value );
|
||||
}
|
||||
|
|
|
@ -86,11 +86,11 @@ public class StandardTableExporter implements Exporter<Table> {
|
|||
|
||||
if ( isPrimaryKeyIdentity && colName.equals( pkColName ) ) {
|
||||
// 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( ' ' )
|
||||
.append( dialect.getIdentityColumnString( col.getSqlTypeCode( metadata ) ) );
|
||||
.append( dialect.getIdentityColumnSupport().getIdentityColumnString( col.getSqlTypeCode( metadata ) ) );
|
||||
}
|
||||
else {
|
||||
buf.append( col.getSqlType( dialect, metadata ) );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ abstract public class DialectChecks {
|
|||
|
||||
public static class SupportsIdentityColumns implements DialectCheck {
|
||||
public boolean isMatch(Dialect dialect) {
|
||||
return dialect.supportsIdentityColumns();
|
||||
return dialect.getIdentityColumnSupport().supportsIdentityColumns();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue