HHH-15587 replace use of enums for specifying Expectations
use of class objects is simpler, more elegant, and more flexible
This commit is contained in:
parent
2451268f16
commit
2b8f363e7b
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
/**
|
||||
* Enumerates strategies for checking JDBC return codes for custom SQL DML queries.
|
||||
* <p>
|
||||
|
@ -19,13 +21,20 @@ package org.hibernate.annotations;
|
|||
* @see SQLUpdate#check()
|
||||
* @see SQLDelete#check()
|
||||
* @see SQLDeleteAll#check()
|
||||
*
|
||||
* @see Expectation
|
||||
*
|
||||
* @deprecated Use an {@link Expectation} class instead.
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public enum ResultCheckStyle {
|
||||
/**
|
||||
* No return code checking. Might mean that no checks are required, or that
|
||||
* failure is indicated by a {@link java.sql.SQLException} being thrown, for
|
||||
* example, by a {@link java.sql.CallableStatement stored procedure} which
|
||||
* performs explicit checks.
|
||||
*
|
||||
* @see org.hibernate.jdbc.Expectation.None
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
|
@ -34,6 +43,8 @@ public enum ResultCheckStyle {
|
|||
* {@link java.sql.Statement#executeBatch()}. The row count is checked
|
||||
* against an expected value. For example, the expected row count for
|
||||
* an {@code INSERT} statement is always 1.
|
||||
*
|
||||
* @see org.hibernate.jdbc.Expectation.RowCount
|
||||
*/
|
||||
COUNT,
|
||||
/**
|
||||
|
@ -42,6 +53,8 @@ public enum ResultCheckStyle {
|
|||
* stored procedure}.
|
||||
* <p>
|
||||
* Statement batching is disabled when {@code PARAM} is selected.
|
||||
*
|
||||
* @see org.hibernate.jdbc.Expectation.OutParameter
|
||||
*/
|
||||
PARAM
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
@ -42,8 +44,20 @@ public @interface SQLDelete {
|
|||
boolean callable() default false;
|
||||
|
||||
/**
|
||||
* For persistence operation what style of determining results (success/failure) is to be used.
|
||||
* An {@link Expectation} class used to verify that the operation was successful.
|
||||
*
|
||||
* @see Expectation.None
|
||||
* @see Expectation.RowCount
|
||||
* @see Expectation.OutParameter
|
||||
*/
|
||||
Class<? extends Expectation> verify() default Expectation.class;
|
||||
|
||||
/**
|
||||
* A {@link ResultCheckStyle} used to verify that the operation was successful.
|
||||
*
|
||||
* @deprecated use {@link #verify()} with an {@link Expectation} class
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
ResultCheckStyle check() default ResultCheckStyle.NONE;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
@ -34,8 +36,20 @@ public @interface SQLDeleteAll {
|
|||
boolean callable() default false;
|
||||
|
||||
/**
|
||||
* For persistence operation what style of determining results (success/failure) is to be used.
|
||||
* An {@link Expectation} class used to verify that the operation was successful.
|
||||
*
|
||||
* @see Expectation.None
|
||||
* @see Expectation.RowCount
|
||||
* @see Expectation.OutParameter
|
||||
*/
|
||||
Class<? extends Expectation> verify() default Expectation.class;
|
||||
|
||||
/**
|
||||
* A {@link ResultCheckStyle} used to verify that the operation was successful.
|
||||
*
|
||||
* @deprecated use {@link #verify()} with an {@link Expectation} class
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
ResultCheckStyle check() default ResultCheckStyle.NONE;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
@ -58,8 +60,20 @@ public @interface SQLInsert {
|
|||
boolean callable() default false;
|
||||
|
||||
/**
|
||||
* For persistence operation what style of determining results (success/failure) is to be used.
|
||||
* An {@link Expectation} class used to verify that the operation was successful.
|
||||
*
|
||||
* @see Expectation.None
|
||||
* @see Expectation.RowCount
|
||||
* @see Expectation.OutParameter
|
||||
*/
|
||||
Class<? extends Expectation> verify() default Expectation.class;
|
||||
|
||||
/**
|
||||
* A {@link ResultCheckStyle} used to verify that the operation was successful.
|
||||
*
|
||||
* @deprecated use {@link #verify()} with an {@link Expectation} class
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
ResultCheckStyle check() default ResultCheckStyle.NONE;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.annotations;
|
||||
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
@ -61,8 +63,20 @@ public @interface SQLUpdate {
|
|||
boolean callable() default false;
|
||||
|
||||
/**
|
||||
* For persistence operation what style of determining results (success/failure) is to be used.
|
||||
* An {@link Expectation} class used to verify that the operation was successful.
|
||||
*
|
||||
* @see Expectation.None
|
||||
* @see Expectation.RowCount
|
||||
* @see Expectation.OutParameter
|
||||
*/
|
||||
Class<? extends Expectation> verify() default Expectation.class;
|
||||
|
||||
/**
|
||||
* A {@link ResultCheckStyle} used to verify that the operation was successful.
|
||||
*
|
||||
* @deprecated use {@link #verify()} with an {@link Expectation} class
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
ResultCheckStyle check() default ResultCheckStyle.NONE;
|
||||
|
||||
/**
|
||||
|
|
|
@ -65,6 +65,7 @@ import org.hibernate.annotations.OptimisticLock;
|
|||
import org.hibernate.annotations.Parameter;
|
||||
import org.hibernate.annotations.Persister;
|
||||
import org.hibernate.annotations.QueryCacheLayout;
|
||||
import org.hibernate.annotations.ResultCheckStyle;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.SQLDeleteAll;
|
||||
import org.hibernate.annotations.SQLInsert;
|
||||
|
@ -95,6 +96,8 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
|||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.Expectations;
|
||||
import org.hibernate.mapping.Any;
|
||||
import org.hibernate.mapping.Backref;
|
||||
import org.hibernate.mapping.CheckConstraint;
|
||||
|
@ -1321,6 +1324,7 @@ public abstract class CollectionBinder {
|
|||
propertyHolder.addProperty( prop, declaringClass );
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void bindLoader() {
|
||||
//SQL overriding
|
||||
|
||||
|
@ -1331,7 +1335,9 @@ public abstract class CollectionBinder {
|
|||
sqlInsert.callable(),
|
||||
fromResultCheckStyle( sqlInsert.check() )
|
||||
);
|
||||
|
||||
if ( sqlInsert.verify() != Expectation.class ) {
|
||||
collection.setInsertExpectation( sqlInsert.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLUpdate sqlUpdate = property.getAnnotation( SQLUpdate.class );
|
||||
|
@ -1341,6 +1347,9 @@ public abstract class CollectionBinder {
|
|||
sqlUpdate.callable(),
|
||||
fromResultCheckStyle( sqlUpdate.check() )
|
||||
);
|
||||
if ( sqlUpdate.verify() != Expectation.class ) {
|
||||
collection.setUpdateExpectation( sqlUpdate.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLDelete sqlDelete = property.getAnnotation( SQLDelete.class );
|
||||
|
@ -1350,6 +1359,9 @@ public abstract class CollectionBinder {
|
|||
sqlDelete.callable(),
|
||||
fromResultCheckStyle( sqlDelete.check() )
|
||||
);
|
||||
if ( sqlDelete.verify() != Expectation.class ) {
|
||||
collection.setDeleteExpectation( sqlDelete.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLDeleteAll sqlDeleteAll = property.getAnnotation( SQLDeleteAll.class );
|
||||
|
@ -1359,6 +1371,9 @@ public abstract class CollectionBinder {
|
|||
sqlDeleteAll.callable(),
|
||||
fromResultCheckStyle( sqlDeleteAll.check() )
|
||||
);
|
||||
if ( sqlDeleteAll.verify() != Expectation.class ) {
|
||||
collection.setDeleteAllExpectation( sqlDeleteAll.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLSelect sqlSelect = property.getAnnotation( SQLSelect.class );
|
||||
|
|
|
@ -90,6 +90,7 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
|||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jpa.event.spi.CallbackType;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.CheckConstraint;
|
||||
|
@ -1387,7 +1388,9 @@ public class EntityBinder {
|
|||
sqlInsert.callable(),
|
||||
fromResultCheckStyle( sqlInsert.check() )
|
||||
);
|
||||
|
||||
if ( sqlInsert.verify() != Expectation.class ) {
|
||||
persistentClass.setInsertExpectation( sqlInsert.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLUpdate sqlUpdate = findMatchingSqlAnnotation( "", SQLUpdate.class, SQLUpdates.class );
|
||||
|
@ -1397,6 +1400,9 @@ public class EntityBinder {
|
|||
sqlUpdate.callable(),
|
||||
fromResultCheckStyle( sqlUpdate.check() )
|
||||
);
|
||||
if ( sqlUpdate.verify() != Expectation.class ) {
|
||||
persistentClass.setUpdateExpectation( sqlUpdate.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLDelete sqlDelete = findMatchingSqlAnnotation( "", SQLDelete.class, SQLDeletes.class );
|
||||
|
@ -1406,6 +1412,9 @@ public class EntityBinder {
|
|||
sqlDelete.callable(),
|
||||
fromResultCheckStyle( sqlDelete.check() )
|
||||
);
|
||||
if ( sqlDelete.verify() != Expectation.class ) {
|
||||
persistentClass.setDeleteExpectation( sqlDelete.verify() );
|
||||
}
|
||||
}
|
||||
|
||||
final SQLDeleteAll sqlDeleteAll = annotatedClass.getAnnotation( SQLDeleteAll.class );
|
||||
|
@ -2265,6 +2274,9 @@ public class EntityBinder {
|
|||
sqlInsert.callable(),
|
||||
fromResultCheckStyle( sqlInsert.check() )
|
||||
);
|
||||
if ( sqlInsert.verify() != Expectation.class ) {
|
||||
join.setInsertExpectation( sqlInsert.verify() );
|
||||
}
|
||||
}
|
||||
else if ( matchingTable != null ) {
|
||||
final String insertSql = matchingTable.sqlInsert().sql();
|
||||
|
@ -2284,6 +2296,9 @@ public class EntityBinder {
|
|||
sqlUpdate.callable(),
|
||||
fromResultCheckStyle( sqlUpdate.check() )
|
||||
);
|
||||
if ( sqlUpdate.verify() != Expectation.class ) {
|
||||
join.setUpdateExpectation( sqlUpdate.verify() );
|
||||
}
|
||||
}
|
||||
else if ( matchingTable != null ) {
|
||||
final String updateSql = matchingTable.sqlUpdate().sql();
|
||||
|
@ -2303,6 +2318,9 @@ public class EntityBinder {
|
|||
sqlDelete.callable(),
|
||||
fromResultCheckStyle( sqlDelete.check() )
|
||||
);
|
||||
if ( sqlDelete.verify() != Expectation.class ) {
|
||||
join.setDeleteExpectation( sqlDelete.verify() );
|
||||
}
|
||||
}
|
||||
else if ( matchingTable != null ) {
|
||||
final String deleteSql = matchingTable.sqlDelete().sql();
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.AssertionFailure;
|
|||
import org.hibernate.annotations.ResultCheckStyle;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
|
||||
/**
|
||||
* For persistence operations (INSERT, UPDATE, DELETE) what style of
|
||||
|
@ -21,7 +22,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
* new {@code org.hibernate.ResultCheck} enum.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @deprecated Use an {@link org.hibernate.jdbc.Expectation} class
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public enum ExecuteUpdateResultCheckStyle {
|
||||
/**
|
||||
* Do not perform checking. Either user simply does not want checking, or is
|
||||
|
@ -85,4 +89,26 @@ public enum ExecuteUpdateResultCheckStyle {
|
|||
public static ExecuteUpdateResultCheckStyle determineDefault(@Nullable String customSql, boolean callable) {
|
||||
return customSql != null && callable ? PARAM : COUNT;
|
||||
}
|
||||
|
||||
public static @Nullable Class<? extends Expectation> expectationClass(@Nullable ExecuteUpdateResultCheckStyle style) {
|
||||
if ( style == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return style.expectationClass();
|
||||
}
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> expectationClass() {
|
||||
switch (this) {
|
||||
case NONE:
|
||||
return Expectation.None.class;
|
||||
case COUNT:
|
||||
return Expectation.RowCount.class;
|
||||
case PARAM:
|
||||
return Expectation.OutParameter.class;
|
||||
default:
|
||||
throw new AssertionFailure( "Unrecognized ExecuteUpdateResultCheckStyle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,43 @@
|
|||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.jdbc;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.exception.GenericJDBCException;
|
||||
|
||||
import static org.hibernate.jdbc.Expectations.checkBatched;
|
||||
import static org.hibernate.jdbc.Expectations.checkNonBatched;
|
||||
import static org.hibernate.jdbc.Expectations.sqlExceptionHelper;
|
||||
import static org.hibernate.jdbc.Expectations.toCallableStatement;
|
||||
|
||||
/**
|
||||
* Defines an expected DML operation outcome.
|
||||
* Used to verify that a JDBC operation completed successfully.
|
||||
* <p>
|
||||
* The two standard implementations are {@link RowCount} for
|
||||
* row count checking, and {@link OutParameter} for checking
|
||||
* the return code assigned to an output parameter of a
|
||||
* {@link CallableStatement}. Custom implementations are
|
||||
* permitted.
|
||||
* <p>
|
||||
* An {@code Expectation} is usually selected via an annotation,
|
||||
* for example:
|
||||
* <pre>
|
||||
* @Entity
|
||||
* @SQLUpdate(sql = "update Record set uid = gen_random_uuid(), whatever = ? where id = ?",
|
||||
* verify = Expectation.RowCount.class)
|
||||
* class Record { ... }
|
||||
* </pre>
|
||||
*
|
||||
* @see org.hibernate.annotations.SQLInsert#verify
|
||||
* @see org.hibernate.annotations.SQLUpdate#verify
|
||||
* @see org.hibernate.annotations.SQLDelete#verify
|
||||
* @see org.hibernate.annotations.SQLDeleteAll#verify
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -22,12 +52,14 @@ public interface Expectation {
|
|||
*
|
||||
* @return True if batching can be combined with this expectation; false otherwise.
|
||||
*/
|
||||
boolean canBeBatched();
|
||||
default boolean canBeBatched() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of parameters this expectation implies. E.g.,
|
||||
* {@link Expectations.BasicParamExpectation} requires a single
|
||||
* OUT parameter for reading back the number of affected rows.
|
||||
* {@link OutParameter} requires a single OUT parameter for
|
||||
* reading back the number of affected rows.
|
||||
*/
|
||||
default int getNumberOfParametersUsed() {
|
||||
return 0;
|
||||
|
@ -40,11 +72,12 @@ public interface Expectation {
|
|||
* @param rowCount The RDBMS reported "number of rows affected".
|
||||
* @param statement The statement representing the operation
|
||||
* @param batchPosition The position in the batch (if batching)
|
||||
* @param statementSQL The SQL backing the prepared statement, for logging purposes
|
||||
* @param sql The SQL backing the prepared statement, for logging purposes
|
||||
* @throws SQLException Exception from the JDBC driver
|
||||
* @throws HibernateException Problem processing the outcome.
|
||||
*/
|
||||
void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String statementSQL) throws SQLException, HibernateException;
|
||||
void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String sql)
|
||||
throws SQLException, HibernateException;
|
||||
|
||||
/**
|
||||
* Perform any special statement preparation.
|
||||
|
@ -54,5 +87,101 @@ public interface Expectation {
|
|||
* @throws SQLException Exception from the JDBC driver
|
||||
* @throws HibernateException Problem performing preparation.
|
||||
*/
|
||||
int prepare(PreparedStatement statement) throws SQLException, HibernateException;
|
||||
default int prepare(PreparedStatement statement) throws SQLException, HibernateException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* No return code checking. Might mean that no checks are required, or that
|
||||
* failure is indicated by a {@link java.sql.SQLException} being thrown, for
|
||||
* example, by a {@link java.sql.CallableStatement stored procedure} which
|
||||
* performs explicit checks.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
class None implements Expectation {
|
||||
@Override
|
||||
public void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String sql) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Row count checking. A row count is an integer value returned by
|
||||
* {@link java.sql.PreparedStatement#executeUpdate()} or
|
||||
* {@link java.sql.Statement#executeBatch()}. The row count is checked
|
||||
* against an expected value. For example, the expected row count for
|
||||
* an {@code INSERT} statement is always 1.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
class RowCount implements Expectation {
|
||||
@Override
|
||||
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String sql) {
|
||||
if ( batchPosition < 0 ) {
|
||||
checkNonBatched( expectedRowCount(), rowCount, sql );
|
||||
}
|
||||
else {
|
||||
checkBatched( expectedRowCount(), rowCount, batchPosition, sql );
|
||||
}
|
||||
}
|
||||
|
||||
protected int expectedRowCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Essentially identical to {@link RowCount} except that the row count
|
||||
* is obtained via an output parameter of a {@link CallableStatement
|
||||
* stored procedure}.
|
||||
* <p>
|
||||
* Statement batching is disabled when {@code OutParameter} is used.
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
class OutParameter implements Expectation {
|
||||
@Override
|
||||
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String sql) {
|
||||
final int result;
|
||||
try {
|
||||
result = toCallableStatement( statement ).getInt( parameterIndex() );
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
sqlExceptionHelper.logExceptions( sqle, "Could not extract row count from CallableStatement" );
|
||||
throw new GenericJDBCException( "Could not extract row count from CallableStatement", sqle );
|
||||
}
|
||||
if ( batchPosition < 0 ) {
|
||||
checkNonBatched( expectedRowCount(), result, sql );
|
||||
}
|
||||
else {
|
||||
checkBatched( expectedRowCount(), result, batchPosition, sql );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfParametersUsed() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prepare(PreparedStatement statement) throws SQLException, HibernateException {
|
||||
toCallableStatement( statement ).registerOutParameter( parameterIndex(), Types.NUMERIC );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeBatched() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected int parameterIndex() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected int expectedRowCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,10 @@ import java.sql.PreparedStatement;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.InstantiationException;
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.StaleStateException;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
|
@ -27,85 +30,44 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
public class Expectations {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( Expectations.class );
|
||||
|
||||
private static final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper( false );
|
||||
|
||||
public static final int USUAL_EXPECTED_COUNT = 1;
|
||||
public static final int USUAL_PARAM_POSITION = 1;
|
||||
|
||||
static final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper( false );
|
||||
|
||||
// Base Expectation impls ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link RowCount}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public static class BasicExpectation implements Expectation {
|
||||
private final int expectedRowCount;
|
||||
private final int expected;
|
||||
|
||||
protected BasicExpectation(int expectedRowCount) {
|
||||
this.expectedRowCount = expectedRowCount;
|
||||
expected = expectedRowCount;
|
||||
if ( expectedRowCount < 0 ) {
|
||||
throw new IllegalArgumentException( "Expected row count must be greater than zero" );
|
||||
}
|
||||
}
|
||||
|
||||
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String statementSQL) {
|
||||
rowCount = determineRowCount( rowCount, statement );
|
||||
@Override
|
||||
public final void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String sql) {
|
||||
final int result = determineRowCount( rowCount, statement );
|
||||
if ( batchPosition < 0 ) {
|
||||
checkNonBatched( rowCount, statementSQL );
|
||||
checkNonBatched( expected, result, sql );
|
||||
}
|
||||
else {
|
||||
checkBatched( rowCount, batchPosition, statementSQL );
|
||||
checkBatched( expected, result, batchPosition, sql );
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBatched(int rowCount, int batchPosition, String statementSQL) {
|
||||
if ( rowCount == -2 ) {
|
||||
LOG.debugf( "Success of batch update unknown: %s", batchPosition );
|
||||
}
|
||||
else if ( rowCount == -3 ) {
|
||||
throw new BatchFailedException( "Batch update failed: " + batchPosition );
|
||||
}
|
||||
else {
|
||||
if ( expectedRowCount > rowCount ) {
|
||||
throw new StaleStateException(
|
||||
"Batch update returned unexpected row count from update ["
|
||||
+ batchPosition + "]; actual row count: " + rowCount
|
||||
+ "; expected: " + expectedRowCount + "; statement executed: "
|
||||
+ statementSQL
|
||||
);
|
||||
}
|
||||
if ( expectedRowCount < rowCount ) {
|
||||
String msg = "Batch update returned unexpected row count from update [" +
|
||||
batchPosition + "]; actual row count: " + rowCount +
|
||||
"; expected: " + expectedRowCount;
|
||||
throw new BatchedTooManyRowsAffectedException( msg, expectedRowCount, rowCount, batchPosition );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkNonBatched(int rowCount, String statementSQL) {
|
||||
if ( expectedRowCount > rowCount ) {
|
||||
throw new StaleStateException(
|
||||
"Unexpected row count: " + rowCount + "; expected: " + expectedRowCount
|
||||
+ "; statement executed: " + statementSQL
|
||||
);
|
||||
}
|
||||
if ( expectedRowCount < rowCount ) {
|
||||
String msg = "Unexpected row count: " + rowCount + "; expected: " + expectedRowCount;
|
||||
throw new TooManyRowsAffectedException( msg, expectedRowCount, rowCount );
|
||||
}
|
||||
}
|
||||
|
||||
public int prepare(PreparedStatement statement) throws SQLException, HibernateException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean canBeBatched() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected int determineRowCount(int reportedRowCount, PreparedStatement statement) {
|
||||
return reportedRowCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link OutParameter}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public static class BasicParamExpectation extends BasicExpectation {
|
||||
private final int parameterPosition;
|
||||
|
||||
|
@ -140,39 +102,88 @@ public class Expectations {
|
|||
throw new GenericJDBCException( "could not extract row counts from CallableStatement", sqle );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CallableStatement toCallableStatement(PreparedStatement statement) {
|
||||
if ( !(statement instanceof CallableStatement) ) {
|
||||
throw new HibernateException(
|
||||
"BasicParamExpectation operates exclusively on CallableStatements : " + statement.getClass()
|
||||
);
|
||||
}
|
||||
static CallableStatement toCallableStatement(PreparedStatement statement) {
|
||||
if ( statement instanceof CallableStatement ) {
|
||||
return (CallableStatement) statement;
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( "Expectation.OutParameter operates exclusively on CallableStatements: "
|
||||
+ statement.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
static void checkBatched(int expected, int rowCount, int batchPosition, String sql) {
|
||||
if ( rowCount == -2 ) {
|
||||
LOG.debugf( "Success of batch update unknown: %s", batchPosition );
|
||||
}
|
||||
else if ( rowCount == -3 ) {
|
||||
throw new BatchFailedException( "Batch update failed: " + batchPosition );
|
||||
}
|
||||
else if ( expected > rowCount ) {
|
||||
throw new StaleStateException(
|
||||
"Batch update returned unexpected row count from update ["
|
||||
+ batchPosition + "]; actual row count: " + rowCount
|
||||
+ "; expected: " + 1 + "; statement executed: "
|
||||
+ sql
|
||||
);
|
||||
}
|
||||
else if ( expected < rowCount ) {
|
||||
String msg = "Batch update returned unexpected row count from update [" +
|
||||
batchPosition + "]; actual row count: " + rowCount +
|
||||
"; expected: " + 1;
|
||||
throw new BatchedTooManyRowsAffectedException( msg, 1, rowCount, batchPosition );
|
||||
}
|
||||
}
|
||||
|
||||
static void checkNonBatched(int expected, int rowCount, String sql) {
|
||||
if ( expected > rowCount ) {
|
||||
throw new StaleStateException(
|
||||
"Unexpected row count: " + rowCount + "; expected: " + 1
|
||||
+ "; statement executed: " + sql
|
||||
);
|
||||
}
|
||||
if ( expected < rowCount ) {
|
||||
String msg = "Unexpected row count: " + rowCount + "; expected: " + 1;
|
||||
throw new TooManyRowsAffectedException( msg, 1, rowCount );
|
||||
}
|
||||
}
|
||||
|
||||
// Various Expectation instances ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public static final Expectation NONE = new Expectation() {
|
||||
public void verifyOutcome(int rowCount, PreparedStatement statement, int batchPosition, String statementSQL) {
|
||||
// explicitly doAfterTransactionCompletion no checking...
|
||||
/**
|
||||
* @deprecated Use {@link Expectation.None}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public static final Expectation NONE = new Expectation.None();
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Expectation.RowCount}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public static final Expectation BASIC = new Expectation.RowCount();
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Expectation.OutParameter}
|
||||
*/
|
||||
@Deprecated(since = "6.5")
|
||||
public static final Expectation PARAM = new Expectation.OutParameter();
|
||||
|
||||
@Internal
|
||||
public static Expectation createExpectation(Class<? extends Expectation> expectation, boolean callable) {
|
||||
if ( expectation == null ) {
|
||||
expectation = callable ? Expectation.OutParameter.class : Expectation.RowCount.class;
|
||||
}
|
||||
|
||||
public int prepare(PreparedStatement statement) {
|
||||
return 0;
|
||||
try {
|
||||
return expectation.newInstance();
|
||||
}
|
||||
|
||||
public boolean canBeBatched() {
|
||||
return true;
|
||||
catch ( Exception e ) {
|
||||
throw new InstantiationException( "Could not instantiate Expectation", expectation, e );
|
||||
}
|
||||
};
|
||||
|
||||
public static final Expectation BASIC = new BasicExpectation( USUAL_EXPECTED_COUNT );
|
||||
|
||||
public static final Expectation PARAM = new BasicParamExpectation( USUAL_EXPECTED_COUNT, USUAL_PARAM_POSITION );
|
||||
|
||||
}
|
||||
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public static Expectation appropriateExpectation(ExecuteUpdateResultCheckStyle style) {
|
||||
switch ( style ) {
|
||||
case NONE:
|
||||
|
@ -182,10 +193,19 @@ public class Expectations {
|
|||
case PARAM:
|
||||
return PARAM;
|
||||
default:
|
||||
throw new HibernateException( "unknown check style : " + style );
|
||||
throw new AssertionFailure( "unknown result check style: " + style );
|
||||
}
|
||||
}
|
||||
|
||||
private Expectations() {
|
||||
}
|
||||
|
||||
// Unused, for removal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public static final int USUAL_EXPECTED_COUNT = 1;
|
||||
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public static final int USUAL_PARAM_POSITION = 1;
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
|||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.resource.beans.spi.ManagedBean;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
@ -36,6 +36,9 @@ import org.hibernate.type.CustomCollectionType;
|
|||
import org.hibernate.type.Type;
|
||||
import org.hibernate.usertype.UserCollectionType;
|
||||
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.EMPTY_BOOLEAN_ARRAY;
|
||||
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationClass;
|
||||
|
||||
/**
|
||||
* A mapping model object representing a collection. Subclasses specialize to particular kinds of collection.
|
||||
*
|
||||
|
@ -104,6 +107,11 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
|
||||
private String loaderName;
|
||||
|
||||
private Class<? extends Expectation> insertExpectation;
|
||||
private Class<? extends Expectation> updateExpectation;
|
||||
private Class<? extends Expectation> deleteExpectation;
|
||||
private Class<? extends Expectation> deleteAllExpectation;
|
||||
|
||||
/**
|
||||
* hbm.xml binding
|
||||
*/
|
||||
|
@ -170,6 +178,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
this.customSQLDeleteAll = original.customSQLDeleteAll;
|
||||
this.customDeleteAllCallable = original.customDeleteAllCallable;
|
||||
this.deleteAllCheckStyle = original.deleteAllCheckStyle;
|
||||
this.insertExpectation = original.insertExpectation;
|
||||
this.updateExpectation = original.updateExpectation;
|
||||
this.deleteExpectation = original.deleteExpectation;
|
||||
this.deleteAllExpectation = original.deleteAllExpectation;
|
||||
this.loaderName = original.loaderName;
|
||||
}
|
||||
|
||||
|
@ -577,11 +589,11 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
this.queryCacheLayout = queryCacheLayout;
|
||||
}
|
||||
|
||||
|
||||
public void setCustomSQLInsert(String customSQLInsert, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
|
||||
this.customSQLInsert = customSQLInsert;
|
||||
this.customInsertCallable = callable;
|
||||
this.insertCheckStyle = checkStyle;
|
||||
this.insertExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLInsert() {
|
||||
|
@ -592,6 +604,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
return customInsertCallable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getInsertExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLInsertCheckStyle() {
|
||||
return insertCheckStyle;
|
||||
}
|
||||
|
@ -600,6 +616,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
this.customSQLUpdate = customSQLUpdate;
|
||||
this.customUpdateCallable = callable;
|
||||
this.updateCheckStyle = checkStyle;
|
||||
this.updateExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLUpdate() {
|
||||
|
@ -610,6 +627,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
return customUpdateCallable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getUpdateExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLUpdateCheckStyle() {
|
||||
return updateCheckStyle;
|
||||
}
|
||||
|
@ -618,6 +639,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
this.customSQLDelete = customSQLDelete;
|
||||
this.customDeleteCallable = callable;
|
||||
this.deleteCheckStyle = checkStyle;
|
||||
this.deleteExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLDelete() {
|
||||
|
@ -628,6 +650,10 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
return customDeleteCallable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getDeleteExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteCheckStyle() {
|
||||
return deleteCheckStyle;
|
||||
}
|
||||
|
@ -639,6 +665,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
this.customSQLDeleteAll = customSQLDeleteAll;
|
||||
this.customDeleteAllCallable = callable;
|
||||
this.deleteAllCheckStyle = checkStyle;
|
||||
this.deleteAllExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLDeleteAll() {
|
||||
|
@ -755,19 +782,19 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void setTypeParameters(java.util.Map parameterMap) {
|
||||
if ( parameterMap instanceof Properties ) {
|
||||
this.typeParameters = (Properties) parameterMap;
|
||||
public void setTypeParameters(java.util.Map typeParameters) {
|
||||
if ( typeParameters instanceof Properties ) {
|
||||
this.typeParameters = (Properties) typeParameters;
|
||||
}
|
||||
else {
|
||||
this.typeParameters = new Properties();
|
||||
typeParameters.putAll( parameterMap );
|
||||
this.typeParameters.putAll( typeParameters );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getColumnInsertability() {
|
||||
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
|
||||
return EMPTY_BOOLEAN_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -777,7 +804,7 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
|
||||
@Override
|
||||
public boolean[] getColumnUpdateability() {
|
||||
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
|
||||
return EMPTY_BOOLEAN_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -848,4 +875,36 @@ public abstract class Collection implements Fetchable, Value, Filterable, SoftDe
|
|||
public Column getSoftDeleteColumn() {
|
||||
return softDeleteColumn;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getInsertExpectation() {
|
||||
return insertExpectation;
|
||||
}
|
||||
|
||||
public void setInsertExpectation(Class<? extends Expectation> insertExpectation) {
|
||||
this.insertExpectation = insertExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getUpdateExpectation() {
|
||||
return updateExpectation;
|
||||
}
|
||||
|
||||
public void setUpdateExpectation(Class<? extends Expectation> updateExpectation) {
|
||||
this.updateExpectation = updateExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getDeleteExpectation() {
|
||||
return deleteExpectation;
|
||||
}
|
||||
|
||||
public void setDeleteExpectation(Class<? extends Expectation> deleteExpectation) {
|
||||
this.deleteExpectation = deleteExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getDeleteAllExpectation() {
|
||||
return deleteAllExpectation;
|
||||
}
|
||||
|
||||
public void setDeleteAllExpectation(Class<? extends Expectation> deleteAllExpectation) {
|
||||
this.deleteAllExpectation = deleteAllExpectation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,11 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.sql.Alias;
|
||||
|
||||
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationClass;
|
||||
|
||||
/**
|
||||
* A mapping model object representing some sort of auxiliary table, for
|
||||
* example, an {@linkplain jakarta.persistence.JoinTable association table},
|
||||
|
@ -47,6 +50,10 @@ public class Join implements AttributeContainer, Serializable {
|
|||
private boolean customDeleteCallable;
|
||||
private ExecuteUpdateResultCheckStyle deleteCheckStyle;
|
||||
|
||||
private Class<? extends Expectation> insertExpectation;
|
||||
private Class<? extends Expectation> updateExpectation;
|
||||
private Class<? extends Expectation> deleteExpectation;
|
||||
|
||||
@Override
|
||||
public void addProperty(Property property) {
|
||||
properties.add( property );
|
||||
|
@ -133,6 +140,7 @@ public class Join implements AttributeContainer, Serializable {
|
|||
this.customSQLInsert = customSQLInsert;
|
||||
this.customInsertCallable = callable;
|
||||
this.insertCheckStyle = checkStyle;
|
||||
this.insertExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLInsert() {
|
||||
|
@ -143,16 +151,8 @@ public class Join implements AttributeContainer, Serializable {
|
|||
return customInsertCallable;
|
||||
}
|
||||
|
||||
public void setInsertCheckStyle(ExecuteUpdateResultCheckStyle insertCheckStyle) {
|
||||
this.insertCheckStyle = insertCheckStyle;
|
||||
}
|
||||
|
||||
public ExecuteUpdateResultCheckStyle getInsertCheckStyle() {
|
||||
return insertCheckStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getInsertCheckStyle()}
|
||||
* @deprecated use {@link #getInsertExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLInsertCheckStyle() {
|
||||
|
@ -163,6 +163,7 @@ public class Join implements AttributeContainer, Serializable {
|
|||
this.customSQLUpdate = customSQLUpdate;
|
||||
this.customUpdateCallable = callable;
|
||||
this.updateCheckStyle = checkStyle;
|
||||
this.updateExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLUpdate() {
|
||||
|
@ -173,16 +174,8 @@ public class Join implements AttributeContainer, Serializable {
|
|||
return customUpdateCallable;
|
||||
}
|
||||
|
||||
public void setUpdateCheckStyle(ExecuteUpdateResultCheckStyle updateCheckStyle) {
|
||||
this.updateCheckStyle = updateCheckStyle;
|
||||
}
|
||||
|
||||
public ExecuteUpdateResultCheckStyle getUpdateCheckStyle() {
|
||||
return updateCheckStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getUpdateCheckStyle()}
|
||||
* @deprecated use {@link #getUpdateExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLUpdateCheckStyle() {
|
||||
|
@ -193,6 +186,7 @@ public class Join implements AttributeContainer, Serializable {
|
|||
this.customSQLDelete = customSQLDelete;
|
||||
this.customDeleteCallable = callable;
|
||||
this.deleteCheckStyle = checkStyle;
|
||||
this.deleteExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLDelete() {
|
||||
|
@ -203,16 +197,8 @@ public class Join implements AttributeContainer, Serializable {
|
|||
return customDeleteCallable;
|
||||
}
|
||||
|
||||
public void setDeleteCheckStyle(ExecuteUpdateResultCheckStyle deleteCheckStyle) {
|
||||
this.deleteCheckStyle = deleteCheckStyle;
|
||||
}
|
||||
|
||||
public ExecuteUpdateResultCheckStyle getDeleteCheckStyle() {
|
||||
return deleteCheckStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getDeleteCheckStyle()}
|
||||
* @deprecated use {@link #getDeleteExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteCheckStyle() {
|
||||
|
@ -243,7 +229,32 @@ public class Join implements AttributeContainer, Serializable {
|
|||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public void setOptional(boolean nullable) {
|
||||
this.optional = nullable;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getInsertExpectation() {
|
||||
return insertExpectation;
|
||||
}
|
||||
|
||||
public void setInsertExpectation(Class<? extends Expectation> insertExpectation) {
|
||||
this.insertExpectation = insertExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getUpdateExpectation() {
|
||||
return updateExpectation;
|
||||
}
|
||||
|
||||
public void setUpdateExpectation(Class<? extends Expectation> updateExpectation) {
|
||||
this.updateExpectation = updateExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getDeleteExpectation() {
|
||||
return deleteExpectation;
|
||||
}
|
||||
|
||||
public void setDeleteExpectation(Class<? extends Expectation> deleteExpectation) {
|
||||
this.deleteExpectation = deleteExpectation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.hibernate.Internal;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.CacheLayout;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.CustomSql;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.ClassLoaderAccess;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
|
@ -28,6 +27,7 @@ import org.hibernate.engine.OptimisticLockStyle;
|
|||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.internal.FilterConfiguration;
|
||||
import org.hibernate.internal.util.collections.JoinedList;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.jpa.event.spi.CallbackDefinition;
|
||||
|
@ -43,6 +43,7 @@ import static java.util.Collections.unmodifiableList;
|
|||
import static java.util.Comparator.comparing;
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
import static org.hibernate.internal.util.StringHelper.root;
|
||||
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.expectationClass;
|
||||
import static org.hibernate.mapping.MappingHelper.checkPropertyColumnDuplication;
|
||||
import static org.hibernate.sql.Template.collectColumnNames;
|
||||
|
||||
|
@ -120,6 +121,10 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
private Component declaredIdentifierMapper;
|
||||
private OptimisticLockStyle optimisticLockStyle;
|
||||
|
||||
private Class<? extends Expectation> insertExpectation;
|
||||
private Class<? extends Expectation> updateExpectation;
|
||||
private Class<? extends Expectation> deleteExpectation;
|
||||
|
||||
private boolean isCached;
|
||||
private CacheLayout queryCacheLayout;
|
||||
|
||||
|
@ -793,20 +798,11 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
return properties;
|
||||
}
|
||||
|
||||
public void setCustomSqlInsert(CustomSql customSql) {
|
||||
if ( customSql != null ) {
|
||||
setCustomSQLInsert(
|
||||
customSql.getSql(),
|
||||
customSql.isCallable(),
|
||||
customSql.getCheckStyle()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCustomSQLInsert(String customSQLInsert, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
|
||||
this.customSQLInsert = customSQLInsert;
|
||||
this.customInsertCallable = callable;
|
||||
this.insertCheckStyle = checkStyle;
|
||||
this.insertExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLInsert() {
|
||||
|
@ -817,36 +813,19 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
return customInsertCallable;
|
||||
}
|
||||
|
||||
public void setInsertCheckStyle(ExecuteUpdateResultCheckStyle insertCheckStyle) {
|
||||
this.insertCheckStyle = insertCheckStyle;
|
||||
}
|
||||
|
||||
public ExecuteUpdateResultCheckStyle getInsertCheckStyle() {
|
||||
return insertCheckStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getInsertCheckStyle()}
|
||||
* @deprecated use {@link #getInsertExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLInsertCheckStyle() {
|
||||
return insertCheckStyle;
|
||||
}
|
||||
|
||||
public void setCustomSqlUpdate(CustomSql customSql) {
|
||||
if ( customSql != null ) {
|
||||
setCustomSQLUpdate(
|
||||
customSql.getSql(),
|
||||
customSql.isCallable(),
|
||||
customSql.getCheckStyle()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCustomSQLUpdate(String customSQLUpdate, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
|
||||
this.customSQLUpdate = customSQLUpdate;
|
||||
this.customUpdateCallable = callable;
|
||||
this.updateCheckStyle = checkStyle;
|
||||
this.updateExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLUpdate() {
|
||||
|
@ -857,36 +836,19 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
return customUpdateCallable;
|
||||
}
|
||||
|
||||
public void setUpdateCheckStyle(ExecuteUpdateResultCheckStyle updateCheckStyle) {
|
||||
this.updateCheckStyle = updateCheckStyle;
|
||||
}
|
||||
|
||||
public ExecuteUpdateResultCheckStyle getUpdateCheckStyle() {
|
||||
return updateCheckStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getUpdateCheckStyle()}
|
||||
* @deprecated use {@link #getUpdateExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLUpdateCheckStyle() {
|
||||
return updateCheckStyle;
|
||||
}
|
||||
|
||||
public void setCustomSqlDelete(CustomSql customSql) {
|
||||
if ( customSql != null ) {
|
||||
setCustomSQLDelete(
|
||||
customSql.getSql(),
|
||||
customSql.isCallable(),
|
||||
customSql.getCheckStyle()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCustomSQLDelete(String customSQLDelete, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
|
||||
this.customSQLDelete = customSQLDelete;
|
||||
this.customDeleteCallable = callable;
|
||||
this.deleteCheckStyle = checkStyle;
|
||||
this.deleteExpectation = expectationClass( checkStyle );
|
||||
}
|
||||
|
||||
public String getCustomSQLDelete() {
|
||||
|
@ -897,16 +859,8 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
return customDeleteCallable;
|
||||
}
|
||||
|
||||
public void setDeleteCheckStyle(ExecuteUpdateResultCheckStyle deleteCheckStyle) {
|
||||
this.deleteCheckStyle = deleteCheckStyle;
|
||||
}
|
||||
|
||||
public ExecuteUpdateResultCheckStyle getDeleteCheckStyle() {
|
||||
return deleteCheckStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getDeleteCheckStyle()}
|
||||
* @deprecated use {@link #getDeleteExpectation()}
|
||||
*/
|
||||
@Deprecated(since = "6.5", forRemoval = true)
|
||||
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteCheckStyle() {
|
||||
|
@ -1307,4 +1261,28 @@ public abstract class PersistentClass implements IdentifiableTypeClass, Attribut
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getInsertExpectation() {
|
||||
return insertExpectation;
|
||||
}
|
||||
|
||||
public void setInsertExpectation(Class<? extends Expectation> insertExpectation) {
|
||||
this.insertExpectation = insertExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getUpdateExpectation() {
|
||||
return updateExpectation;
|
||||
}
|
||||
|
||||
public void setUpdateExpectation(Class<? extends Expectation> updateExpectation) {
|
||||
this.updateExpectation = updateExpectation;
|
||||
}
|
||||
|
||||
public Class<? extends Expectation> getDeleteExpectation() {
|
||||
return deleteExpectation;
|
||||
}
|
||||
|
||||
public void setDeleteExpectation(Class<? extends Expectation> deleteExpectation) {
|
||||
this.deleteExpectation = deleteExpectation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions;
|
|||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.profile.internal.FetchProfileAffectee;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -58,7 +57,6 @@ import org.hibernate.internal.FilterAliasGenerator;
|
|||
import org.hibernate.internal.FilterHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.jdbc.Expectations;
|
||||
import org.hibernate.loader.ast.internal.CollectionElementLoaderByIndex;
|
||||
import org.hibernate.loader.ast.internal.CollectionLoaderNamedQuery;
|
||||
import org.hibernate.loader.ast.internal.CollectionLoaderSingleKey;
|
||||
|
@ -137,6 +135,7 @@ import org.hibernate.type.Type;
|
|||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||
import static org.hibernate.jdbc.Expectations.createExpectation;
|
||||
import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER;
|
||||
|
||||
/**
|
||||
|
@ -1688,74 +1687,38 @@ public abstract class AbstractCollectionPersister
|
|||
collectionBootDescriptor.isInverse(),
|
||||
new MutationDetails(
|
||||
MutationType.INSERT,
|
||||
determineExpectation(
|
||||
collectionBootDescriptor.getCustomSQLInsertCheckStyle(),
|
||||
collectionBootDescriptor.getCustomSQLInsert(),
|
||||
collectionBootDescriptor.isCustomInsertCallable()
|
||||
),
|
||||
createExpectation( collectionBootDescriptor.getInsertExpectation(),
|
||||
collectionBootDescriptor.isCustomInsertCallable()),
|
||||
collectionBootDescriptor.getCustomSQLInsert(),
|
||||
collectionBootDescriptor.isCustomInsertCallable()
|
||||
),
|
||||
new MutationDetails(
|
||||
MutationType.UPDATE,
|
||||
determineExpectation(
|
||||
collectionBootDescriptor.getCustomSQLUpdateCheckStyle(),
|
||||
collectionBootDescriptor.getCustomSQLUpdate(),
|
||||
collectionBootDescriptor.isCustomUpdateCallable()
|
||||
),
|
||||
createExpectation( collectionBootDescriptor.getUpdateExpectation(),
|
||||
collectionBootDescriptor.isCustomUpdateCallable()),
|
||||
collectionBootDescriptor.getCustomSQLUpdate(),
|
||||
collectionBootDescriptor.isCustomUpdateCallable()
|
||||
),
|
||||
collectionBootDescriptor.getKey().isCascadeDeleteEnabled(),
|
||||
new MutationDetails(
|
||||
MutationType.DELETE,
|
||||
determineExpectation(
|
||||
collectionBootDescriptor.getCustomSQLDeleteAllCheckStyle(),
|
||||
collectionBootDescriptor.getCustomSQLDeleteAll(),
|
||||
collectionBootDescriptor.isCustomDeleteAllCallable(),
|
||||
Expectations.NONE
|
||||
),
|
||||
collectionBootDescriptor.isCustomDeleteAllCallable() || collectionBootDescriptor.getDeleteAllExpectation() != null
|
||||
? createExpectation( collectionBootDescriptor.getDeleteAllExpectation(),
|
||||
collectionBootDescriptor.isCustomDeleteAllCallable() )
|
||||
: new Expectation.None(),
|
||||
collectionBootDescriptor.getCustomSQLDeleteAll(),
|
||||
collectionBootDescriptor.isCustomDeleteAllCallable()
|
||||
),
|
||||
new MutationDetails(
|
||||
MutationType.DELETE,
|
||||
determineExpectation(
|
||||
collectionBootDescriptor.getCustomSQLDeleteCheckStyle(),
|
||||
collectionBootDescriptor.getCustomSQLDelete(),
|
||||
collectionBootDescriptor.isCustomDeleteCallable()
|
||||
),
|
||||
createExpectation( collectionBootDescriptor.getDeleteExpectation(),
|
||||
collectionBootDescriptor.isCustomDeleteCallable()),
|
||||
collectionBootDescriptor.getCustomSQLDelete(),
|
||||
collectionBootDescriptor.isCustomDeleteCallable()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static Expectation determineExpectation(
|
||||
ExecuteUpdateResultCheckStyle explicitStyle,
|
||||
String customSql,
|
||||
boolean customSqlCallable,
|
||||
Expectation fallback) {
|
||||
if ( explicitStyle != null ) {
|
||||
return Expectations.appropriateExpectation( explicitStyle );
|
||||
}
|
||||
|
||||
if ( customSql == null ) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return Expectations.appropriateExpectation(
|
||||
ExecuteUpdateResultCheckStyle.determineDefault( customSql, customSqlCallable )
|
||||
);
|
||||
}
|
||||
|
||||
private static Expectation determineExpectation(
|
||||
ExecuteUpdateResultCheckStyle explicitStyle,
|
||||
String customSql,
|
||||
boolean customSqlCallable) {
|
||||
return determineExpectation( explicitStyle, customSql, customSqlCallable, Expectations.BASIC );
|
||||
}
|
||||
|
||||
protected JdbcMutationOperation buildDeleteAllOperation(MutatingTableReference tableReference) {
|
||||
if ( tableMapping.getDeleteDetails().getCustomSql() != null ) {
|
||||
return buildCustomSqlDeleteAllOperation( tableReference );
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.persister.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -23,7 +22,6 @@ import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
|||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
||||
import org.hibernate.internal.FilterAliasGenerator;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
|
@ -52,7 +50,6 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
|||
import org.hibernate.persister.internal.SqlFragmentPredicate;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.tree.from.NamedTableReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -61,8 +58,6 @@ import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
|||
import org.hibernate.sql.ast.tree.from.UnknownTableReferenceException;
|
||||
import org.hibernate.sql.model.ast.builder.MutationGroupBuilder;
|
||||
import org.hibernate.sql.model.ast.builder.TableInsertBuilder;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -78,7 +73,7 @@ import static org.hibernate.internal.util.collections.ArrayHelper.toIntArray;
|
|||
import static org.hibernate.internal.util.collections.ArrayHelper.toStringArray;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.linkedMapOfSize;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.mapOfSize;
|
||||
import static org.hibernate.jdbc.Expectations.appropriateExpectation;
|
||||
import static org.hibernate.jdbc.Expectations.createExpectation;
|
||||
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.buildEncapsulatedCompositeIdentifierMapping;
|
||||
import static org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.buildNonEncapsulatedCompositeIdentifierMapping;
|
||||
import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR;
|
||||
|
@ -162,7 +157,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
// Span of the tables directly mapped by this entity and super-classes, if any
|
||||
private final int coreTableSpan;
|
||||
private final int subclassCoreTableSpan;
|
||||
// only contains values for SecondaryTables, ie. not tables part of the "coreTableSpan"
|
||||
// only contains values for SecondaryTables, i.e. not tables part of the "coreTableSpan"
|
||||
private final boolean[] isNullableTable;
|
||||
private final boolean[] isInverseTable;
|
||||
|
||||
|
@ -409,28 +404,16 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
isInverseTable[jk] = false;
|
||||
|
||||
customSQLInsert[jk] = currentClass.getCustomSQLInsert();
|
||||
insertCallable[jk] = customSQLInsert[jk] != null && currentClass.isCustomInsertCallable();
|
||||
insertExpectations[jk] = appropriateExpectation(
|
||||
currentClass.getInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[jk], insertCallable[jk] )
|
||||
: currentClass.getInsertCheckStyle()
|
||||
);
|
||||
insertCallable[jk] = currentClass.isCustomInsertCallable();
|
||||
insertExpectations[jk] = createExpectation( currentClass.getInsertExpectation(), insertCallable[jk] );
|
||||
|
||||
customSQLUpdate[jk] = currentClass.getCustomSQLUpdate();
|
||||
updateCallable[jk] = customSQLUpdate[jk] != null && currentClass.isCustomUpdateCallable();
|
||||
updateExpectations[jk] = appropriateExpectation(
|
||||
currentClass.getUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[jk], updateCallable[jk] )
|
||||
: currentClass.getUpdateCheckStyle()
|
||||
);
|
||||
updateCallable[jk] = currentClass.isCustomUpdateCallable();
|
||||
updateExpectations[jk] = createExpectation( currentClass.getUpdateExpectation(), updateCallable[jk] );
|
||||
|
||||
customSQLDelete[jk] = currentClass.getCustomSQLDelete();
|
||||
deleteCallable[jk] = customSQLDelete[jk] != null && currentClass.isCustomDeleteCallable();
|
||||
deleteExpectations[jk] = appropriateExpectation(
|
||||
currentClass.getDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[jk], deleteCallable[jk] )
|
||||
: currentClass.getDeleteCheckStyle()
|
||||
);
|
||||
deleteCallable[jk] = currentClass.isCustomDeleteCallable();
|
||||
deleteExpectations[jk] = createExpectation( currentClass.getDeleteExpectation(), deleteCallable[jk] );
|
||||
|
||||
jk--;
|
||||
currentClass = currentClass.getSuperclass();
|
||||
|
@ -446,28 +429,16 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
isNullableTable[j] = join.isOptional();
|
||||
|
||||
customSQLInsert[j] = join.getCustomSQLInsert();
|
||||
insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
|
||||
insertExpectations[j] = appropriateExpectation(
|
||||
join.getInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] )
|
||||
: join.getInsertCheckStyle()
|
||||
);
|
||||
insertCallable[j] = join.isCustomInsertCallable();
|
||||
insertExpectations[j] = createExpectation( join.getInsertExpectation(), insertCallable[j] );
|
||||
|
||||
customSQLUpdate[j] = join.getCustomSQLUpdate();
|
||||
updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable();
|
||||
updateExpectations[j] = appropriateExpectation(
|
||||
join.getUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] )
|
||||
: join.getUpdateCheckStyle()
|
||||
);
|
||||
updateCallable[j] = join.isCustomUpdateCallable();
|
||||
updateExpectations[j] = createExpectation( join.getUpdateExpectation(), updateCallable[j] );
|
||||
|
||||
customSQLDelete[j] = join.getCustomSQLDelete();
|
||||
deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable();
|
||||
deleteExpectations[j] = appropriateExpectation(
|
||||
join.getDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] )
|
||||
: join.getDeleteCheckStyle()
|
||||
);
|
||||
deleteCallable[j] = join.isCustomDeleteCallable();
|
||||
deleteExpectations[j] = createExpectation( join.getDeleteExpectation(), deleteCallable[j] );
|
||||
|
||||
j++;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.hibernate.Remove;
|
|||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
||||
import org.hibernate.internal.FilterAliasGenerator;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
|
@ -49,7 +48,7 @@ import static org.hibernate.internal.util.collections.ArrayHelper.toBooleanArray
|
|||
import static org.hibernate.internal.util.collections.ArrayHelper.toIntArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toStringArray;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.toSmallMap;
|
||||
import static org.hibernate.jdbc.Expectations.appropriateExpectation;
|
||||
import static org.hibernate.jdbc.Expectations.createExpectation;
|
||||
import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR;
|
||||
import static org.hibernate.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR;
|
||||
import static org.hibernate.sql.model.ast.builder.TableMutationBuilder.NULL;
|
||||
|
@ -170,28 +169,16 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
deleteExpectations = new Expectation[joinSpan];
|
||||
|
||||
customSQLInsert[0] = persistentClass.getCustomSQLInsert();
|
||||
insertCallable[0] = customSQLInsert[0] != null && persistentClass.isCustomInsertCallable();
|
||||
insertExpectations[0] = appropriateExpectation(
|
||||
persistentClass.getInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[0], insertCallable[0] )
|
||||
: persistentClass.getInsertCheckStyle()
|
||||
);
|
||||
insertCallable[0] = persistentClass.isCustomInsertCallable();
|
||||
insertExpectations[0] = createExpectation( persistentClass.getInsertExpectation(), insertCallable[0] );
|
||||
|
||||
customSQLUpdate[0] = persistentClass.getCustomSQLUpdate();
|
||||
updateCallable[0] = customSQLUpdate[0] != null && persistentClass.isCustomUpdateCallable();
|
||||
updateExpectations[0] = appropriateExpectation(
|
||||
persistentClass.getUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[0], updateCallable[0] )
|
||||
: persistentClass.getUpdateCheckStyle()
|
||||
);
|
||||
updateCallable[0] = persistentClass.isCustomUpdateCallable();
|
||||
updateExpectations[0] = createExpectation( persistentClass.getUpdateExpectation(), updateCallable[0] );
|
||||
|
||||
customSQLDelete[0] = persistentClass.getCustomSQLDelete();
|
||||
deleteCallable[0] = customSQLDelete[0] != null && persistentClass.isCustomDeleteCallable();
|
||||
deleteExpectations[0] = appropriateExpectation(
|
||||
persistentClass.getDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[0], deleteCallable[0] )
|
||||
: persistentClass.getDeleteCheckStyle()
|
||||
);
|
||||
deleteCallable[0] = persistentClass.isCustomDeleteCallable();
|
||||
deleteExpectations[0] = createExpectation( persistentClass.getDeleteExpectation(), deleteCallable[0] );
|
||||
|
||||
// JOINS
|
||||
|
||||
|
@ -207,28 +194,16 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() && dialect.supportsCascadeDelete();
|
||||
|
||||
customSQLInsert[j] = join.getCustomSQLInsert();
|
||||
insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
|
||||
insertExpectations[j] = appropriateExpectation(
|
||||
join.getInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] )
|
||||
: join.getInsertCheckStyle()
|
||||
);
|
||||
insertCallable[j] = join.isCustomInsertCallable();
|
||||
insertExpectations[j] = createExpectation( join.getInsertExpectation(), insertCallable[j] );
|
||||
|
||||
customSQLUpdate[j] = join.getCustomSQLUpdate();
|
||||
updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable();
|
||||
updateExpectations[j] = appropriateExpectation(
|
||||
join.getUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] )
|
||||
: join.getUpdateCheckStyle()
|
||||
);
|
||||
updateCallable[j] = join.isCustomUpdateCallable();
|
||||
updateExpectations[j] = createExpectation( join.getUpdateExpectation(), updateCallable[j] );
|
||||
|
||||
customSQLDelete[j] = join.getCustomSQLDelete();
|
||||
deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable();
|
||||
deleteExpectations[j] = appropriateExpectation(
|
||||
join.getDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] )
|
||||
: join.getDeleteCheckStyle()
|
||||
);
|
||||
deleteCallable[j] = join.isCustomDeleteCallable();
|
||||
deleteExpectations[j] = createExpectation( join.getDeleteExpectation(), deleteCallable[j] );
|
||||
|
||||
keyColumnNames[j] = new String[join.getKey().getColumnSpan()];
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.hibernate.boot.Metadata;
|
|||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.id.IdentityGenerator;
|
||||
import org.hibernate.internal.FilterAliasGenerator;
|
||||
import org.hibernate.internal.StaticFilterAliasGenerator;
|
||||
|
@ -65,7 +64,7 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.to2DStringArray;
|
||||
import static org.hibernate.internal.util.collections.ArrayHelper.toStringArray;
|
||||
import static org.hibernate.jdbc.Expectations.appropriateExpectation;
|
||||
import static org.hibernate.jdbc.Expectations.createExpectation;
|
||||
|
||||
/**
|
||||
* An {@link EntityPersister} implementing the
|
||||
|
@ -125,41 +124,20 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
subclassTableNames = new String[]{tableName};
|
||||
//Custom SQL
|
||||
|
||||
String sql;
|
||||
boolean callable;
|
||||
ExecuteUpdateResultCheckStyle checkStyle;
|
||||
sql = persistentClass.getCustomSQLInsert();
|
||||
callable = sql != null && persistentClass.isCustomInsertCallable();
|
||||
checkStyle = sql == null
|
||||
? ExecuteUpdateResultCheckStyle.COUNT
|
||||
: persistentClass.getInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable )
|
||||
: persistentClass.getInsertCheckStyle();
|
||||
customSQLInsert = new String[] {sql};
|
||||
insertCallable = new boolean[] {callable};
|
||||
insertExpectations = new Expectation[] { appropriateExpectation( checkStyle ) };
|
||||
customSQLInsert = new String[] { persistentClass.getCustomSQLInsert() };
|
||||
insertCallable = new boolean[] { persistentClass.isCustomInsertCallable() };
|
||||
insertExpectations = new Expectation[] { createExpectation( persistentClass.getInsertExpectation(),
|
||||
persistentClass.isCustomInsertCallable() ) };
|
||||
|
||||
sql = persistentClass.getCustomSQLUpdate();
|
||||
callable = sql != null && persistentClass.isCustomUpdateCallable();
|
||||
checkStyle = sql == null
|
||||
? ExecuteUpdateResultCheckStyle.COUNT
|
||||
: persistentClass.getUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable )
|
||||
: persistentClass.getUpdateCheckStyle();
|
||||
customSQLUpdate = new String[] {sql};
|
||||
updateCallable = new boolean[] {callable};
|
||||
updateExpectations = new Expectation[] { appropriateExpectation( checkStyle ) };
|
||||
customSQLUpdate = new String[] { persistentClass.getCustomSQLUpdate() };
|
||||
updateCallable = new boolean[] { persistentClass.isCustomUpdateCallable() };
|
||||
updateExpectations = new Expectation[] { createExpectation( persistentClass.getUpdateExpectation(),
|
||||
persistentClass.isCustomUpdateCallable() ) };
|
||||
|
||||
sql = persistentClass.getCustomSQLDelete();
|
||||
callable = sql != null && persistentClass.isCustomDeleteCallable();
|
||||
checkStyle = sql == null
|
||||
? ExecuteUpdateResultCheckStyle.COUNT
|
||||
: persistentClass.getDeleteCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( sql, callable )
|
||||
: persistentClass.getDeleteCheckStyle();
|
||||
customSQLDelete = new String[] {sql};
|
||||
deleteCallable = new boolean[] {callable};
|
||||
deleteExpectations = new Expectation[] { appropriateExpectation( checkStyle ) };
|
||||
customSQLDelete = new String[] { persistentClass.getCustomSQLDelete() };
|
||||
deleteCallable = new boolean[] { persistentClass.isCustomDeleteCallable() };
|
||||
deleteExpectations = new Expectation[] { createExpectation( persistentClass.getDeleteExpectation(),
|
||||
persistentClass.isCustomDeleteCallable() ) };
|
||||
|
||||
discriminatorValue = persistentClass.getSubclassId();
|
||||
discriminatorSQLValue = String.valueOf( persistentClass.getSubclassId() );
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.hibernate.annotations.SQLRestriction;
|
|||
import org.hibernate.annotations.Where;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
|
@ -141,7 +142,8 @@ public class WhereClauseOrderBySizeTest extends BaseEntityManagerFunctionalTestC
|
|||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
@SQLDelete(sql = "UPDATE Book SET deleted = true WHERE id = ?", check = ResultCheckStyle.COUNT)
|
||||
@SQLDelete(sql = "UPDATE Book SET deleted = true WHERE id = ?",
|
||||
verify = Expectation.RowCount.class)
|
||||
@SQLRestriction("deleted = false")
|
||||
public static class Book {
|
||||
@Id
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.hibernate.orm.test.mapping.attributebinder.typebinder;
|
|||
import org.hibernate.annotations.TypeBinderType;
|
||||
import org.hibernate.binder.TypeBinder;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
|
@ -11,7 +12,6 @@ import java.lang.annotation.Target;
|
|||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.NONE;
|
||||
|
||||
@TypeBinderType(binder = NoResultCheck.Binder.class)
|
||||
@Retention(RUNTIME)
|
||||
|
@ -20,9 +20,9 @@ public @interface NoResultCheck {
|
|||
class Binder implements TypeBinder<NoResultCheck> {
|
||||
@Override
|
||||
public void bind(NoResultCheck annotation, MetadataBuildingContext buildingContext, PersistentClass persistentClass) {
|
||||
persistentClass.setInsertCheckStyle(NONE);
|
||||
persistentClass.setUpdateCheckStyle(NONE);
|
||||
persistentClass.setDeleteCheckStyle(NONE);
|
||||
persistentClass.setInsertExpectation(Expectation.None.class);
|
||||
persistentClass.setUpdateExpectation(Expectation.None.class);
|
||||
persistentClass.setDeleteExpectation(Expectation.None.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.annotations.SQLSelect;
|
|||
import org.hibernate.annotations.SQLUpdate;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.metamodel.CollectionClassification;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
|
@ -109,7 +110,7 @@ public class CustomSQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
@Entity(name = "Person")
|
||||
@SQLInsert(
|
||||
sql = "INSERT INTO person (name, id, valid) VALUES (?, ?, true) ",
|
||||
check = ResultCheckStyle.COUNT
|
||||
verify = Expectation.RowCount.class
|
||||
)
|
||||
@SQLUpdate(
|
||||
sql = "UPDATE person SET name = ? where id = ? "
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.write;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.SQLInsert;
|
||||
import org.hibernate.annotations.SQLUpdate;
|
||||
import org.hibernate.jdbc.Expectation;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel( annotatedClasses = CustomSqlWithExpectationTests.CustomEntity.class )
|
||||
@SessionFactory
|
||||
public class CustomSqlWithExpectationTests {
|
||||
@Test
|
||||
public void testBasicOperations(SessionFactoryScope scope) {
|
||||
|
||||
assertEquals(0,count);
|
||||
|
||||
// insert
|
||||
scope.inTransaction( (session) -> {
|
||||
session.persist( new CustomEntity( 1, "csutmo" ) );
|
||||
} );
|
||||
|
||||
assertEquals(1,count);
|
||||
|
||||
// update
|
||||
scope.inTransaction( (session) -> {
|
||||
final CustomEntity customEntity = session.get( CustomEntity.class, 1 );
|
||||
customEntity.setName( "custom" );
|
||||
} );
|
||||
|
||||
assertEquals(2,count);
|
||||
|
||||
// delete
|
||||
scope.inTransaction( (session) -> {
|
||||
final CustomEntity customEntity = session.get( CustomEntity.class, 1 );
|
||||
assertThat( customEntity.getName() ).isEqualTo( "custom" );
|
||||
session.remove( customEntity );
|
||||
} );
|
||||
|
||||
assertEquals(3,count);
|
||||
}
|
||||
|
||||
static int count = 0;
|
||||
|
||||
public static class Custom extends Expectation.RowCount {
|
||||
@Override
|
||||
public int prepare(PreparedStatement statement) throws SQLException, HibernateException {
|
||||
count ++;
|
||||
return super.prepare(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "CustomEntity" )
|
||||
@Table( name = "custom_entity" )
|
||||
@SQLInsert( sql = "insert into custom_entity (name, id) values (?, ?)", verify = Custom.class )
|
||||
@SQLDelete( sql = "delete from custom_entity where id = ?", verify = Custom.class )
|
||||
@SQLUpdate( sql = "update custom_entity set name = ? where id = ? ", verify = Custom.class )
|
||||
public static class CustomEntity {
|
||||
@Id
|
||||
private Integer id;
|
||||
@Basic
|
||||
private String name;
|
||||
|
||||
CustomEntity() {
|
||||
// for use by Hibernate
|
||||
}
|
||||
|
||||
public CustomEntity(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue