1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5 * indicated by the @author tags or express copyright attribution
6 * statements applied by the authors. All third-party contributions are
7 * distributed under license by Red Hat Middleware LLC.
8 *
9 * This copyrighted material is made available to anyone wishing to use, modify,
10 * copy, or redistribute it subject to the terms and conditions of the GNU
11 * Lesser General Public License, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this distribution; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301 USA
23 *
24 */
25 package org.hibernate.transaction;
26
27 import javax.transaction.Status;
28 import javax.transaction.Synchronization;
29 import javax.transaction.SystemException;
30 import javax.transaction.Transaction;
31
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import org.hibernate.TransactionException;
36 import org.hibernate.jdbc.JDBCContext;
37 import org.hibernate.util.JTAHelper;
38
39 /**
40 * A JTA transaction synch used to allow the {@link org.hibernate.Session} to know about transaction
41 * events.
42 *
43 * @author Gavin King
44 */
45 public final class CacheSynchronization implements Synchronization {
46
47 private static final Logger log = LoggerFactory.getLogger(CacheSynchronization.class);
48
49 private final TransactionFactory.Context ctx;
50 private JDBCContext jdbcContext;
51 private final Transaction transaction;
52 private final org.hibernate.Transaction hibernateTransaction;
53
54 public CacheSynchronization(
55 TransactionFactory.Context ctx,
56 JDBCContext jdbcContext,
57 Transaction transaction,
58 org.hibernate.Transaction tx) {
59 this.ctx = ctx;
60 this.jdbcContext = jdbcContext;
61 this.transaction = transaction;
62 this.hibernateTransaction = tx;
63 }
64
65 /**
66 * {@inheritDoc}
67 */
68 public void beforeCompletion() {
69 log.trace("transaction before completion callback");
70
71 boolean flush;
72 try {
73 flush = !ctx.isFlushModeNever() &&
74 ctx.isFlushBeforeCompletionEnabled() &&
75 !JTAHelper.isRollback( transaction.getStatus() );
76 //actually, this last test is probably unnecessary, since
77 //beforeCompletion() doesn't get called during rollback
78 }
79 catch (SystemException se) {
80 log.error("could not determine transaction status", se);
81 setRollbackOnly();
82 throw new TransactionException("could not determine transaction status in beforeCompletion()", se);
83 }
84
85 try {
86 if (flush) {
87 log.trace("automatically flushing session");
88 ctx.managedFlush();
89 }
90 }
91 catch (RuntimeException re) {
92 setRollbackOnly();
93 throw re;
94 }
95 finally {
96 jdbcContext.beforeTransactionCompletion(hibernateTransaction);
97 }
98 }
99
100 private void setRollbackOnly() {
101 try {
102 transaction.setRollbackOnly();
103 }
104 catch (SystemException se) {
105 log.error("could not set transaction to rollback only", se);
106 }
107 }
108
109 /**
110 * {@inheritDoc}
111 */
112 public void afterCompletion(int status) {
113 if ( log.isTraceEnabled() ) {
114 log.trace("transaction after completion callback, status: " + status);
115 }
116 try {
117 jdbcContext.afterTransactionCompletion(status==Status.STATUS_COMMITTED, hibernateTransaction);
118 }
119 finally {
120 if ( ctx.shouldAutoClose() && !ctx.isClosed() ) {
121 log.trace("automatically closing session");
122 ctx.managedClose();
123 }
124 }
125 }
126
127 /**
128 * {@inheritDoc}
129 */
130 public String toString() {
131 return CacheSynchronization.class.getName();
132 }
133
134 }