|
75 | 75 | import org.hibernate.SharedSessionBuilder;
|
76 | 76 | import org.hibernate.SimpleNaturalIdLoadAccess;
|
77 | 77 | import org.hibernate.Transaction;
|
| 78 | +import org.hibernate.TransactionException; |
78 | 79 | import org.hibernate.TransientObjectException;
|
79 | 80 | import org.hibernate.TypeHelper;
|
80 | 81 | import org.hibernate.UnknownProfileException;
|
|
101 | 102 | import org.hibernate.engine.spi.SessionFactoryImplementor;
|
102 | 103 | import org.hibernate.engine.spi.SessionOwner;
|
103 | 104 | import org.hibernate.engine.spi.Status;
|
104 |
| -import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper; |
| 105 | +import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform; |
105 | 106 | import org.hibernate.engine.transaction.spi.TransactionObserver;
|
106 | 107 | import org.hibernate.event.service.spi.EventListenerGroup;
|
107 | 108 | import org.hibernate.event.service.spi.EventListenerRegistry;
|
|
157 | 158 | import org.hibernate.resource.jdbc.spi.StatementInspector;
|
158 | 159 | import org.hibernate.resource.transaction.TransactionCoordinator;
|
159 | 160 | import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
|
| 161 | +import org.hibernate.resource.transaction.backend.jta.internal.synchronization.AfterCompletionAction; |
| 162 | +import org.hibernate.resource.transaction.backend.jta.internal.synchronization.ExceptionMapper; |
| 163 | +import org.hibernate.resource.transaction.backend.jta.internal.synchronization.ManagedFlushChecker; |
160 | 164 | import org.hibernate.resource.transaction.spi.TransactionStatus;
|
161 | 165 | import org.hibernate.stat.SessionStatistics;
|
162 | 166 | import org.hibernate.stat.internal.SessionStatisticsImpl;
|
@@ -222,6 +226,10 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
|
222 | 226 |
|
223 | 227 | private transient JdbcSessionContext jdbcSessionContext;
|
224 | 228 |
|
| 229 | + private transient ExceptionMapper exceptionMapper; |
| 230 | + private transient ManagedFlushChecker managedFlushChecker; |
| 231 | + private transient AfterCompletionAction afterCompletionAction; |
| 232 | + |
225 | 233 | /**
|
226 | 234 | * Constructor used for openSession(...) processing, as well as construction
|
227 | 235 | * of sessions for getCurrentSession().
|
@@ -264,6 +272,8 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
|
264 | 272 | this.autoCloseSessionEnabled = autoCloseSessionEnabled;
|
265 | 273 | this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
|
266 | 274 |
|
| 275 | + initializeFromSessionOwner( sessionOwner ); |
| 276 | + |
267 | 277 | if ( statementInspector == null ) {
|
268 | 278 | this.statementInspector = new StatementInspector() {
|
269 | 279 | @Override
|
@@ -355,6 +365,34 @@ public void afterCompletion(boolean successful, boolean delayed) {
|
355 | 365 |
|
356 | 366 | }
|
357 | 367 |
|
| 368 | + private void initializeFromSessionOwner(SessionOwner sessionOwner) { |
| 369 | + if ( sessionOwner != null ) { |
| 370 | + if ( sessionOwner.getExceptionMapper() != null ) { |
| 371 | + exceptionMapper = sessionOwner.getExceptionMapper(); |
| 372 | + } |
| 373 | + else { |
| 374 | + exceptionMapper = STANDARD_EXCEPTION_MAPPER; |
| 375 | + } |
| 376 | + if ( sessionOwner.getAfterCompletionAction() != null ) { |
| 377 | + afterCompletionAction = sessionOwner.getAfterCompletionAction(); |
| 378 | + } |
| 379 | + else { |
| 380 | + afterCompletionAction = STANDARD_AFTER_COMPLETION_ACTION; |
| 381 | + } |
| 382 | + if ( sessionOwner.getManagedFlushChecker() != null ) { |
| 383 | + managedFlushChecker = sessionOwner.getManagedFlushChecker(); |
| 384 | + } |
| 385 | + else { |
| 386 | + managedFlushChecker = STANDARD_MANAGED_FLUSH_CHECKER; |
| 387 | + } |
| 388 | + } |
| 389 | + else { |
| 390 | + exceptionMapper = STANDARD_EXCEPTION_MAPPER; |
| 391 | + afterCompletionAction = STANDARD_AFTER_COMPLETION_ACTION; |
| 392 | + managedFlushChecker = STANDARD_MANAGED_FLUSH_CHECKER; |
| 393 | + } |
| 394 | + } |
| 395 | + |
358 | 396 | @Override
|
359 | 397 | public SharedSessionBuilder sessionWithOptions() {
|
360 | 398 | return new SharedSessionBuilderImpl( this );
|
@@ -707,7 +745,7 @@ private void fireLock(String entityName, Object object, LockOptions options) {
|
707 | 745 | fireLock( new LockEvent( entityName, object, options, this ) );
|
708 | 746 | }
|
709 | 747 |
|
710 |
| - private void fireLock( Object object, LockOptions options) { |
| 748 | + private void fireLock(Object object, LockOptions options) { |
711 | 749 | fireLock( new LockEvent( object, options, this ) );
|
712 | 750 | }
|
713 | 751 |
|
@@ -1209,7 +1247,8 @@ public void flush() throws HibernateException {
|
1209 | 1247 | public void forceFlush(EntityEntry entityEntry) throws HibernateException {
|
1210 | 1248 | errorIfClosed();
|
1211 | 1249 | if ( LOG.isDebugEnabled() ) {
|
1212 |
| - LOG.debugf( "Flushing to force deletion of re-saved object: %s", |
| 1250 | + LOG.debugf( |
| 1251 | + "Flushing to force deletion of re-saved object: %s", |
1213 | 1252 | MessageHelper.infoString( entityEntry.getPersister(), entityEntry.getId(), getFactory() ) );
|
1214 | 1253 | }
|
1215 | 1254 |
|
@@ -1293,7 +1332,7 @@ public int executeNativeUpdate(NativeSQLQuerySpecification nativeQuerySpecificat
|
1293 | 1332 | } finally {
|
1294 | 1333 | afterOperation( success );
|
1295 | 1334 | delayedAfterCompletion();
|
1296 |
| - } |
| 1335 | + } |
1297 | 1336 | return result;
|
1298 | 1337 | }
|
1299 | 1338 |
|
@@ -2148,6 +2187,8 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound
|
2148 | 2187 | this.jdbcSessionContext = new JdbcSessionContextImpl( factory, statementInspector );
|
2149 | 2188 | sessionOwner = (SessionOwner) ois.readObject();
|
2150 | 2189 |
|
| 2190 | + initializeFromSessionOwner( sessionOwner ); |
| 2191 | + |
2151 | 2192 | jdbcCoordinator = JdbcCoordinatorImpl.deserialize( ois, this );
|
2152 | 2193 |
|
2153 | 2194 | this.transactionCoordinator = getTransactionCoordinatorBuilder().buildTransactionCoordinator( jdbcCoordinator, this );
|
@@ -2239,6 +2280,8 @@ public void beforeTransactionCompletion() {
|
2239 | 2280 | public void afterTransactionCompletion(boolean successful, boolean delayed) {
|
2240 | 2281 | LOG.tracef( "SessionImpl#afterTransactionCompletion(successful=%s, delayed=%s)", successful, delayed );
|
2241 | 2282 |
|
| 2283 | + afterCompletionAction.doAction( successful ); |
| 2284 | + |
2242 | 2285 | persistenceContext.afterTransactionCompletion();
|
2243 | 2286 | actionQueue.afterTransactionCompletion( successful );
|
2244 | 2287 |
|
@@ -2834,24 +2877,65 @@ public void afterTransactionBegin() {
|
2834 | 2877 |
|
2835 | 2878 | @Override
|
2836 | 2879 | public void flushBeforeTransactionCompletion() {
|
2837 |
| - boolean flush = false; |
| 2880 | + boolean flush = isTransactionFlushable() && managedFlushChecker.shouldDoManagedFlush( this ); |
2838 | 2881 | try {
|
2839 |
| - flush = (!isFlushModeNever() && |
2840 |
| - !flushBeforeCompletionEnabled) || ( |
2841 |
| - !isClosed() |
2842 |
| - && !isFlushModeNever() |
2843 |
| - && flushBeforeCompletionEnabled |
2844 |
| - && !JtaStatusHelper.isRollback( |
2845 |
| - getSessionFactory().getSettings() |
2846 |
| - .getJtaPlatform() |
2847 |
| - .getCurrentStatus() |
2848 |
| - )); |
2849 |
| - } |
2850 |
| - catch (SystemException se) { |
2851 |
| - throw new HibernateException( "could not determine transaction status in beforeCompletion()", se ); |
2852 |
| - } |
2853 |
| - if ( flush ) { |
2854 |
| - managedFlush(); |
| 2882 | + if ( flush ) { |
| 2883 | + managedFlush(); |
| 2884 | + } |
2855 | 2885 | }
|
| 2886 | + catch (HibernateException he) { |
| 2887 | + throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", he ); |
| 2888 | + } |
| 2889 | + catch (RuntimeException re) { |
| 2890 | + throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", re ); |
| 2891 | + } |
| 2892 | + } |
| 2893 | + |
| 2894 | + private boolean isTransactionFlushable() { |
| 2895 | + if ( currentHibernateTransaction == null ) { |
| 2896 | + // assume it is flushable - CMT, auto-commit, etc |
| 2897 | + return true; |
| 2898 | + } |
| 2899 | + final TransactionStatus status = currentHibernateTransaction.getStatus(); |
| 2900 | + return status == TransactionStatus.ACTIVE || status ==TransactionStatus.COMMITTING; |
| 2901 | + } |
| 2902 | + |
| 2903 | + private static final ExceptionMapper STANDARD_EXCEPTION_MAPPER = new ExceptionMapper() { |
| 2904 | + @Override |
| 2905 | + public RuntimeException mapStatusCheckFailure(String message, SystemException systemException) { |
| 2906 | + return new TransactionException( |
| 2907 | + "could not determine transaction status in beforeCompletion()", |
| 2908 | + systemException |
| 2909 | + ); |
| 2910 | + } |
| 2911 | + |
| 2912 | + @Override |
| 2913 | + public RuntimeException mapManagedFlushFailure(String message, RuntimeException failure) { |
| 2914 | + LOG.unableToPerformManagedFlush( failure.getMessage() ); |
| 2915 | + return failure; |
| 2916 | + } |
| 2917 | + }; |
| 2918 | + |
| 2919 | + private static final AfterCompletionAction STANDARD_AFTER_COMPLETION_ACTION = new AfterCompletionAction() { |
| 2920 | + @Override |
| 2921 | + public void doAction(boolean successful) { |
| 2922 | + // nothing to do by default. |
| 2923 | + } |
| 2924 | + }; |
| 2925 | + |
| 2926 | + private static final ManagedFlushChecker STANDARD_MANAGED_FLUSH_CHECKER = new ManagedFlushChecker() { |
| 2927 | + @Override |
| 2928 | + public boolean shouldDoManagedFlush(SessionImpl session) { |
| 2929 | + boolean isFlushModeNever = session.isFlushModeNever(); |
| 2930 | + return (!isFlushModeNever && |
| 2931 | + !session.flushBeforeCompletionEnabled) || |
| 2932 | + !session.isClosed() |
| 2933 | + && !isFlushModeNever |
| 2934 | + && session.flushBeforeCompletionEnabled; |
| 2935 | + } |
| 2936 | + }; |
| 2937 | + |
| 2938 | + private JtaPlatform getJtaPlatform() { |
| 2939 | + return factory.getServiceRegistry().getService( JtaPlatform.class ); |
2856 | 2940 | }
|
2857 | 2941 | }
|
0 commit comments