1 //$Id: TransactionImpl.java 11171 2007-02-08 03:40:51Z epbernard $
2 package org.hibernate.ejb;
3
4 import javax.persistence.EntityTransaction;
5 import javax.persistence.PersistenceException;
6 import javax.persistence.RollbackException;
7
8 import org.hibernate.HibernateException;
9 import org.hibernate.Session;
10 import org.hibernate.Transaction;
11 import org.hibernate.StaleStateException;
12
13 /**
14 * @author Gavin King
15 * @author Emmanuel Bernard
16 */
17 public class TransactionImpl implements EntityTransaction {
18
19 private HibernateEntityManagerImplementor entityManager;
20 private Transaction tx;
21 private boolean rollbackOnly;
22
23 public TransactionImpl(AbstractEntityManagerImpl entityManager) {
24 this.entityManager = entityManager;
25 }
26
27 private Session getSession() {
28 return entityManager.getSession();
29 }
30
31 public void begin() {
32 try {
33 rollbackOnly = false;
34 if ( tx != null && tx.isActive() ) {
35 throw new IllegalStateException( "Transaction already active" );
36 }
37 //entityManager.adjustFlushMode();
38 tx = getSession().beginTransaction();
39 }
40 catch (HibernateException he) {
41 entityManager.throwPersistenceException( he );
42 }
43 }
44
45 public void commit() {
46 if ( tx == null || !tx.isActive() ) {
47 throw new IllegalStateException( "Transaction not active" );
48 }
49 if ( rollbackOnly ) {
50 tx.rollback();
51 throw new RollbackException( "Transaction marked as rollbackOnly" );
52 }
53 try {
54 tx.commit();
55 }
56 catch (Exception e) {
57 Exception wrappedException;
58 if (e instanceof StaleStateException) {
59 wrappedException = entityManager.wrapStaleStateException( (StaleStateException) e );
60 }
61 else {
62 wrappedException = e;
63 }
64 try {
65 //as per the spec we should rollback if commit fails
66 tx.rollback();
67 }
68 catch (Exception re) {
69 //swallow
70 }
71 throw new RollbackException( "Error while commiting the transaction", wrappedException );
72 }
73 finally {
74 rollbackOnly = false;
75 }
76 //if closed and we commit, the mode should have been adjusted already
77 //if ( entityManager.isOpen() ) entityManager.adjustFlushMode();
78 }
79
80 public void rollback() {
81 if ( tx == null || !tx.isActive() ) {
82 throw new IllegalStateException( "Transaction not active" );
83 }
84 try {
85 tx.rollback();
86 }
87 catch (Exception e) {
88 throw new PersistenceException( "unexpected error when rollbacking", e );
89 }
90 finally {
91 try {
92 if (entityManager != null) {
93 Session session = getSession();
94 if ( session != null && session.isOpen() ) session.clear();
95 }
96 }
97 catch (Throwable t) {
98 //we don't really care here since it's only for safety purpose
99 }
100 rollbackOnly = false;
101 }
102 }
103
104 public void setRollbackOnly() {
105 if ( ! isActive() ) throw new IllegalStateException( "Transaction not active" );
106 this.rollbackOnly = true;
107 }
108
109 public boolean getRollbackOnly() {
110 if ( ! isActive() ) throw new IllegalStateException( "Transaction not active" );
111 return rollbackOnly;
112 }
113
114 public boolean isActive() {
115 try {
116 return tx != null && tx.isActive();
117 }
118 catch (RuntimeException e) {
119 throw new PersistenceException( "unexpected error when checking transaction status", e );
120 }
121 }
122
123 }