1 16 17 package org.springframework.transaction.support; 18 19 import java.io.IOException ; 20 import java.io.ObjectInputStream ; 21 import java.io.Serializable ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 28 import org.springframework.core.Constants; 29 import org.springframework.transaction.IllegalTransactionStateException; 30 import org.springframework.transaction.InvalidTimeoutException; 31 import org.springframework.transaction.NestedTransactionNotSupportedException; 32 import org.springframework.transaction.PlatformTransactionManager; 33 import org.springframework.transaction.TransactionDefinition; 34 import org.springframework.transaction.TransactionException; 35 import org.springframework.transaction.TransactionStatus; 36 import org.springframework.transaction.TransactionSuspensionNotSupportedException; 37 import org.springframework.transaction.UnexpectedRollbackException; 38 39 85 public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable { 86 87 94 public static final int SYNCHRONIZATION_ALWAYS = 0; 95 96 104 public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1; 105 106 109 public static final int SYNCHRONIZATION_NEVER = 2; 110 111 112 113 private static final Constants constants = new Constants(AbstractPlatformTransactionManager.class); 114 115 116 117 protected transient Log logger = LogFactory.getLog(getClass()); 118 119 private int transactionSynchronization = SYNCHRONIZATION_ALWAYS; 120 121 private int defaultTimeout = TransactionDefinition.TIMEOUT_DEFAULT; 122 123 private boolean nestedTransactionAllowed = false; 124 125 private boolean globalRollbackOnParticipationFailure = true; 126 127 private boolean failEarlyOnGlobalRollbackOnly = false; 128 129 private boolean rollbackOnCommitFailure = false; 130 131 132 138 public final void setTransactionSynchronizationName(String constantName) { 139 setTransactionSynchronization(constants.asNumber(constantName).intValue()); 140 } 141 142 154 public final void setTransactionSynchronization(int transactionSynchronization) { 155 this.transactionSynchronization = transactionSynchronization; 156 } 157 158 162 public final int getTransactionSynchronization() { 163 return this.transactionSynchronization; 164 } 165 166 174 public final void setDefaultTimeout(int defaultTimeout) { 175 if (defaultTimeout < TransactionDefinition.TIMEOUT_DEFAULT) { 176 throw new InvalidTimeoutException("Invalid default timeout", defaultTimeout); 177 } 178 this.defaultTimeout = defaultTimeout; 179 } 180 181 187 public final int getDefaultTimeout() { 188 return this.defaultTimeout; 189 } 190 191 196 public final void setNestedTransactionAllowed(boolean nestedTransactionAllowed) { 197 this.nestedTransactionAllowed = nestedTransactionAllowed; 198 } 199 200 203 public final boolean isNestedTransactionAllowed() { 204 return this.nestedTransactionAllowed; 205 } 206 207 240 public final void setGlobalRollbackOnParticipationFailure(boolean globalRollbackOnParticipationFailure) { 241 this.globalRollbackOnParticipationFailure = globalRollbackOnParticipationFailure; 242 } 243 244 248 public final boolean isGlobalRollbackOnParticipationFailure() { 249 return this.globalRollbackOnParticipationFailure; 250 } 251 252 267 public final void setFailEarlyOnGlobalRollbackOnly(boolean failEarlyOnGlobalRollbackOnly) { 268 this.failEarlyOnGlobalRollbackOnly = failEarlyOnGlobalRollbackOnly; 269 } 270 271 275 public final boolean isFailEarlyOnGlobalRollbackOnly() { 276 return this.failEarlyOnGlobalRollbackOnly; 277 } 278 279 288 public final void setRollbackOnCommitFailure(boolean rollbackOnCommitFailure) { 289 this.rollbackOnCommitFailure = rollbackOnCommitFailure; 290 } 291 292 296 public final boolean isRollbackOnCommitFailure() { 297 return this.rollbackOnCommitFailure; 298 } 299 300 301 305 313 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { 314 Object transaction = doGetTransaction(); 315 316 boolean debugEnabled = logger.isDebugEnabled(); 318 if (debugEnabled) { 319 logger.debug("Using transaction object [" + transaction + "]"); 320 } 321 322 if (definition == null) { 323 definition = new DefaultTransactionDefinition(); 325 } 326 327 if (isExistingTransaction(transaction)) { 328 return handleExistingTransaction(definition, transaction, debugEnabled); 330 } 331 332 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { 334 throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); 335 } 336 337 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { 339 throw new IllegalTransactionStateException( 340 "No existing transaction found for transaction marked with propagation 'mandatory'"); 341 } 342 else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || 343 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || 344 definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { 345 Object suspendedResources = suspend(null); 346 if (debugEnabled) { 347 logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); 348 } 349 doBegin(transaction, definition); 350 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); 351 return newTransactionStatus( 352 definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); 353 } 354 else { 355 boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); 357 return newTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); 358 } 359 } 360 361 364 private TransactionStatus handleExistingTransaction( 365 TransactionDefinition definition, Object transaction, boolean debugEnabled) 366 throws TransactionException { 367 368 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) { 369 throw new IllegalTransactionStateException( 370 "Existing transaction found for transaction marked with propagation 'never'"); 371 } 372 373 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { 374 if (debugEnabled) { 375 logger.debug("Suspending current transaction"); 376 } 377 Object suspendedResources = suspend(transaction); 378 boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); 379 return newTransactionStatus( 380 definition, null, false, newSynchronization, debugEnabled, suspendedResources); 381 } 382 383 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) { 384 if (debugEnabled) { 385 logger.debug("Suspending current transaction, creating new transaction with name [" + 386 definition.getName() + "]"); 387 } 388 SuspendedResourcesHolder suspendedResources = suspend(transaction); 389 try { 390 doBegin(transaction, definition); 391 } 392 catch (TransactionException beginEx) { 393 try { 394 resume(transaction, suspendedResources); 395 } 396 catch (TransactionException resumeEx) { 397 logger.error( 398 "Inner transaction begin exception overridden by outer transaction resume exception", beginEx); 399 throw resumeEx; 400 } 401 throw beginEx; 402 } 403 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); 404 return newTransactionStatus( 405 definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); 406 } 407 408 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { 409 if (!isNestedTransactionAllowed()) { 410 throw new NestedTransactionNotSupportedException( 411 "Transaction manager does not allow nested transactions by default - " + 412 "specify 'nestedTransactionAllowed' property with value 'true'"); 413 } 414 if (debugEnabled) { 415 logger.debug("Creating nested transaction with name [" + definition.getName() + "]"); 416 } 417 if (useSavepointForNestedTransaction()) { 418 DefaultTransactionStatus status = 422 newTransactionStatus(definition, transaction, false, false, debugEnabled, null); 423 status.createAndHoldSavepoint(); 424 return status; 425 } 426 else { 427 doBegin(transaction, definition); 431 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); 432 return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); 433 } 434 } 435 436 if (debugEnabled) { 438 logger.debug("Participating in existing transaction"); 439 } 440 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); 441 return newTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); 442 } 443 444 448 protected DefaultTransactionStatus newTransactionStatus( 449 TransactionDefinition definition, Object transaction, boolean newTransaction, 450 boolean newSynchronization, boolean debug, Object suspendedResources) { 451 452 boolean actualNewSynchronization = newSynchronization && 453 !TransactionSynchronizationManager.isSynchronizationActive(); 454 if (actualNewSynchronization) { 455 TransactionSynchronizationManager.setActualTransactionActive(transaction != null); 456 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( 457 (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) ? 458 new Integer (definition.getIsolationLevel()) : null); 459 TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); 460 TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); 461 TransactionSynchronizationManager.initSynchronization(); 462 } 463 return new DefaultTransactionStatus( 464 transaction, newTransaction, actualNewSynchronization, 465 definition.isReadOnly(), debug, suspendedResources); 466 } 467 468 477 protected int determineTimeout(TransactionDefinition definition) { 478 if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT) { 479 return definition.getTimeout(); 480 } 481 return this.defaultTimeout; 482 } 483 484 485 495 protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException { 496 if (TransactionSynchronizationManager.isSynchronizationActive()) { 497 List suspendedSynchronizations = doSuspendSynchronization(); 498 try { 499 Object suspendedResources = null; 500 if (transaction != null) { 501 suspendedResources = doSuspend(transaction); 502 } 503 String name = TransactionSynchronizationManager.getCurrentTransactionName(); 504 TransactionSynchronizationManager.setCurrentTransactionName(null); 505 boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); 506 TransactionSynchronizationManager.setCurrentTransactionReadOnly(false); 507 Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); 508 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null); 509 TransactionSynchronizationManager.setActualTransactionActive(false); 510 return new SuspendedResourcesHolder( 511 suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel); 512 } 513 catch (TransactionException ex) { 514 doResumeSynchronization(suspendedSynchronizations); 516 throw ex; 517 } 518 } 519 else if (transaction != null) { 520 Object suspendedResources = doSuspend(transaction); 522 return new SuspendedResourcesHolder(suspendedResources, null, null, false, null); 523 } 524 else { 525 return null; 527 } 528 } 529 530 540 protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder) throws TransactionException { 541 Object suspendedResources = resourcesHolder.suspendedResources; 542 if (suspendedResources != null) { 543 doResume(transaction, suspendedResources); 544 } 545 List suspendedSynchronizations = resourcesHolder.suspendedSynchronizations; 546 if (suspendedSynchronizations != null) { 547 TransactionSynchronizationManager.setActualTransactionActive(suspendedResources != null); 548 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel); 549 TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly); 550 TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name); 551 doResumeSynchronization(suspendedSynchronizations); 552 } 553 } 554 555 560 private List doSuspendSynchronization() { 561 List suspendedSynchronizations = TransactionSynchronizationManager.getSynchronizations(); 562 for (Iterator it = suspendedSynchronizations.iterator(); it.hasNext();) { 563 ((TransactionSynchronization) it.next()).suspend(); 564 } 565 TransactionSynchronizationManager.clearSynchronization(); 566 return suspendedSynchronizations; 567 } 568 569 574 private void doResumeSynchronization(List suspendedSynchronizations) { 575 TransactionSynchronizationManager.initSynchronization(); 576 for (Iterator it = suspendedSynchronizations.iterator(); it.hasNext();) { 577 TransactionSynchronization synchronization = (TransactionSynchronization) it.next(); 578 synchronization.resume(); 579 TransactionSynchronizationManager.registerSynchronization(synchronization); 580 } 581 } 582 583 584 593 public final void commit(TransactionStatus status) throws TransactionException { 594 if (status.isCompleted()) { 595 throw new IllegalTransactionStateException( 596 "Transaction is already completed - do not call commit or rollback more than once per transaction"); 597 } 598 599 DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; 600 if (defStatus.isLocalRollbackOnly()) { 601 if (defStatus.isDebug()) { 602 logger.debug("Transactional code has requested rollback"); 603 } 604 processRollback(defStatus); 605 return; 606 } 607 if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { 608 if (defStatus.isDebug()) { 609 logger.debug("Global transaction is marked as rollback-only but transactional code requested commit"); 610 } 611 processRollback(defStatus); 612 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { 615 throw new UnexpectedRollbackException( 616 "Transaction rolled back because it has been marked as rollback-only"); 617 } 618 return; 619 } 620 621 processCommit(defStatus); 622 } 623 624 630 private void processCommit(DefaultTransactionStatus status) throws TransactionException { 631 try { 632 boolean beforeCompletionInvoked = false; 633 try { 634 triggerBeforeCommit(status); 635 triggerBeforeCompletion(status); 636 beforeCompletionInvoked = true; 637 boolean globalRollbackOnly = false; 638 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { 639 globalRollbackOnly = status.isGlobalRollbackOnly(); 640 } 641 if (status.hasSavepoint()) { 642 if (status.isDebug()) { 643 logger.debug("Releasing transaction savepoint"); 644 } 645 status.releaseHeldSavepoint(); 646 } 647 else if (status.isNewTransaction()) { 648 if (status.isDebug()) { 649 logger.debug("Initiating transaction commit"); 650 } 651 doCommit(status); 652 } 653 if (globalRollbackOnly) { 656 throw new UnexpectedRollbackException( 657 "Transaction silently rolled back because it has been marked as rollback-only"); 658 } 659 } 660 catch (UnexpectedRollbackException ex) { 661 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); 663 throw ex; 664 } 665 catch (TransactionException ex) { 666 if (isRollbackOnCommitFailure()) { 668 doRollbackOnCommitException(status, ex); 669 } 670 else { 671 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); 672 } 673 throw ex; 674 } 675 catch (RuntimeException ex) { 676 if (!beforeCompletionInvoked) { 677 triggerBeforeCompletion(status); 678 } 679 doRollbackOnCommitException(status, ex); 680 throw ex; 681 } 682 catch (Error err) { 683 if (!beforeCompletionInvoked) { 684 triggerBeforeCompletion(status); 685 } 686 doRollbackOnCommitException(status, err); 687 throw err; 688 } 689 690 try { 693 triggerAfterCommit(status); 694 } 695 finally { 696 triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); 697 } 698 699 } 700 finally { 701 cleanupAfterCompletion(status); 702 } 703 } 704 705 712 public final void rollback(TransactionStatus status) throws TransactionException { 713 if (status.isCompleted()) { 714 throw new IllegalTransactionStateException( 715 "Transaction is already completed - do not call commit or rollback more than once per transaction"); 716 } 717 718 DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; 719 processRollback(defStatus); 720 } 721 722 728 private void processRollback(DefaultTransactionStatus status) { 729 try { 730 try { 731 triggerBeforeCompletion(status); 732 if (status.hasSavepoint()) { 733 if (status.isDebug()) { 734 logger.debug("Rolling back transaction to savepoint"); 735 } 736 status.rollbackToHeldSavepoint(); 737 } 738 else if (status.isNewTransaction()) { 739 if (status.isDebug()) { 740 logger.debug("Initiating transaction rollback"); 741 } 742 doRollback(status); 743 } 744 else if (status.hasTransaction()) { 745 if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) { 746 if (status.isDebug()) { 747 logger.debug( 748 "Participating transaction failed - marking existing transaction as rollback-only"); 749 } 750 doSetRollbackOnly(status); 751 } 752 else { 753 if (status.isDebug()) { 754 logger.debug( 755 "Participating transaction failed - letting transaction originator decide on rollback"); 756 } 757 } 758 } 759 else { 760 logger.debug("Should roll back transaction but cannot - no transaction available"); 761 } 762 } 763 catch (RuntimeException ex) { 764 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); 765 throw ex; 766 } 767 catch (Error err) { 768 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); 769 throw err; 770 } 771 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); 772 } 773 finally { 774 cleanupAfterCompletion(status); 775 } 776 } 777 778 785 private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex) 786 throws TransactionException { 787 try { 788 if (status.isNewTransaction()) { 789 if (status.isDebug()) { 790 logger.debug("Initiating transaction rollback after commit exception", ex); 791 } 792 doRollback(status); 793 } 794 else if (status.hasTransaction() && isGlobalRollbackOnParticipationFailure()) { 795 if (status.isDebug()) { 796 logger.debug("Marking existing transaction as rollback-only after commit exception", ex); 797 } 798 doSetRollbackOnly(status); 799 } 800 } 801 catch (RuntimeException rbex) { 802 logger.error("Commit exception overridden by rollback exception", ex); 803 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); 804 throw rbex; 805 } 806 catch (Error rberr) { 807 logger.error("Commit exception overridden by rollback exception", ex); 808 triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); 809 throw rberr; 810 } 811 triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); 812 } 813 814 815 819 protected final void triggerBeforeCommit(DefaultTransactionStatus status) { 820 if (status.isNewSynchronization()) { 821 if (status.isDebug()) { 822 logger.debug("Triggering beforeCommit synchronization"); 823 } 824 TransactionSynchronizationUtils.triggerBeforeCommit(status.isReadOnly()); 825 } 826 } 827 828 832 protected final void triggerBeforeCompletion(DefaultTransactionStatus status) { 833 if (status.isNewSynchronization()) { 834 if (status.isDebug()) { 835 logger.debug("Triggering beforeCompletion synchronization"); 836 } 837 TransactionSynchronizationUtils.triggerBeforeCompletion(); 838 } 839 } 840 841 845 private void triggerAfterCommit(DefaultTransactionStatus status) { 846 if (status.isNewSynchronization()) { 847 if (status.isDebug()) { 848 logger.debug("Triggering afterCommit synchronization"); 849 } 850 TransactionSynchronizationUtils.triggerAfterCommit(); 851 } 852 } 853 854 859 private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) { 860 if (status.isNewSynchronization()) { 861 List synchronizations = TransactionSynchronizationManager.getSynchronizations(); 862 if (!status.hasTransaction() || status.isNewTransaction()) { 863 if (status.isDebug()) { 864 logger.debug("Triggering afterCompletion synchronization"); 865 } 866 invokeAfterCompletion(synchronizations, completionStatus); 869 } 870 else { 871 registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations); 875 } 876 } 877 } 878 879 892 protected final void invokeAfterCompletion(List synchronizations, int completionStatus) { 893 TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus); 894 } 895 896 902 private void cleanupAfterCompletion(DefaultTransactionStatus status) { 903 status.setCompleted(); 904 if (status.isNewSynchronization()) { 905 TransactionSynchronizationManager.clear(); 906 } 907 if (status.isNewTransaction()) { 908 doCleanupAfterCompletion(status.getTransaction()); 909 } 910 if (status.getSuspendedResources() != null) { 911 if (status.isDebug()) { 912 logger.debug("Resuming suspended transaction"); 913 } 914 resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources()); 915 } 916 } 917 918 919 923 945 protected abstract Object doGetTransaction() throws TransactionException; 946 947 962 protected boolean isExistingTransaction(Object transaction) throws TransactionException { 963 return false; 964 } 965 966 982 protected boolean useSavepointForNestedTransaction() { 983 return true; 984 } 985 986 1003 protected abstract void doBegin(Object transaction, TransactionDefinition definition) 1004 throws TransactionException; 1005 1006 1019 protected Object doSuspend(Object transaction) throws TransactionException { 1020 throw new TransactionSuspensionNotSupportedException( 1021 "Transaction manager [" + getClass().getName() + "] does not support transaction suspension"); 1022 } 1023 1024 1037 protected void doResume(Object transaction, Object suspendedResources) throws TransactionException { 1038 throw new TransactionSuspensionNotSupportedException( 1039 "Transaction manager [" + getClass().getName() + "] does not support transaction suspension"); 1040 } 1041 1042 1071 protected boolean shouldCommitOnGlobalRollbackOnly() { 1072 return false; 1073 } 1074 1075 1085 protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException; 1086 1087 1096 protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException; 1097 1098 1107 protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { 1108 throw new IllegalTransactionStateException( 1109 "Participating in existing transactions is not supported - when 'isExistingTransaction' " + 1110 "returns true, appropriate 'doSetRollbackOnly' behavior must be provided"); 1111 } 1112 1113 1128 protected void registerAfterCompletionWithExistingTransaction(Object transaction, List synchronizations) 1129 throws TransactionException { 1130 1131 logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " + 1132 "processing Spring after-completion callbacks immediately, with outcome status 'unknown'"); 1133 invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN); 1134 } 1135 1136 1143 protected void doCleanupAfterCompletion(Object transaction) { 1144 } 1145 1146 1147 1151 private void readObject(ObjectInputStream ois) throws IOException , ClassNotFoundException { 1152 ois.defaultReadObject(); 1154 1155 this.logger = LogFactory.getLog(getClass()); 1157 } 1158 1159 1160 1164 protected static class SuspendedResourcesHolder { 1165 1166 private final Object suspendedResources; 1167 private final List suspendedSynchronizations; 1168 private final String name; 1169 private final boolean readOnly; 1170 private final Integer isolationLevel; 1171 1172 private SuspendedResourcesHolder( 1173 Object suspendedResources, List suspendedSynchronizations, 1174 String name, boolean readOnly, Integer isolationLevel) { 1175 this.suspendedResources = suspendedResources; 1176 this.suspendedSynchronizations = suspendedSynchronizations; 1177 this.name = name; 1178 this.readOnly = readOnly; 1179 this.isolationLevel = isolationLevel; 1180 } 1181 } 1182 1183} 1184 | Popular Tags |