1212import javax .transaction .TransactionManager ;
1313import java .sql .Connection ;
1414import java .sql .SQLException ;
15+ import java .util .concurrent .Callable ;
1516
1617import org .hibernate .HibernateException ;
1718import org .hibernate .engine .jdbc .connections .spi .JdbcConnectionAccess ;
@@ -52,21 +53,64 @@ protected SqlExceptionHelper sqlExceptionHelper() {
5253}
5354
5455@ Override
55- public <T > T delegateWork (WorkExecutorVisitable <T > work , boolean transacted ) throws HibernateException {
56+ public <T > T delegateWork (final WorkExecutorVisitable <T > work , final boolean transacted ) throws HibernateException {
57+ return doInSuspendedTransaction (new HibernateCallable <T >() {
58+ @ Override
59+ public T call () throws HibernateException {
60+ HibernateCallable <T > workCallable = new HibernateCallable <T >() {
61+ @ Override
62+ public T call () throws HibernateException {
63+ return doTheWork (work );
64+ }
65+ };
66+ if ( transacted ) {
67+ return doInNewTransaction ( workCallable , transactionManager );
68+ }
69+ else {
70+ return workCallable .call ();
71+ }
72+ }
73+ });
74+ }
75+
76+ @ Override
77+ public <T > T delegateCallable (final Callable <T > callable , final boolean transacted ) throws HibernateException {
78+ return doInSuspendedTransaction (new HibernateCallable <T >() {
79+ @ Override
80+ public T call () throws HibernateException {
81+ HibernateCallable <T > workCallable = new HibernateCallable <T >() {
82+ @ Override
83+ public T call () throws HibernateException {
84+ try {
85+ return callable .call ();
86+ }
87+ catch (HibernateException e ) {
88+ throw e ;
89+ }
90+ catch (Exception e ) {
91+ throw new HibernateException (e );
92+ }
93+ }
94+ };
95+ if ( transacted ) {
96+ return doInNewTransaction ( workCallable , transactionManager );
97+ }
98+ else {
99+ return workCallable .call ();
100+ }
101+ }
102+ });
103+ }
104+
105+ private <T > T doInSuspendedTransaction (HibernateCallable <T > callable ) {
56106try {
57107// First we suspend any current JTA transaction
58108Transaction surroundingTransaction = transactionManager .suspend ();
59109LOG .debugf ( "Surrounding JTA transaction suspended [%s]" , surroundingTransaction );
60110
61111boolean hadProblems = false ;
62112try {
63- // then perform the requested work
64- if ( transacted ) {
65- return doTheWorkInNewTransaction ( work , transactionManager );
66- }
67- else {
68- return doTheWorkInNoTransaction ( work );
69- }
113+ return callable .call ();
70114}
71115catch (HibernateException e ) {
72116hadProblems = true ;
@@ -91,13 +135,13 @@ public <T> T delegateWork(WorkExecutorVisitable<T> work, boolean transacted) thr
91135}
92136}
93137
94- private <T > T doTheWorkInNewTransaction ( WorkExecutorVisitable <T > work , TransactionManager transactionManager ) {
138+ private <T > T doInNewTransaction ( HibernateCallable <T > callable , TransactionManager transactionManager ) {
95139try {
96140// start the new isolated transaction
97141transactionManager .begin ();
98142
99143try {
100- T result = doTheWork ( work );
144+ T result = callable . call ( );
101145// if everything went ok, commit the isolated transaction
102146transactionManager .commit ();
103147return result ;
@@ -120,10 +164,6 @@ private <T> T doTheWorkInNewTransaction(WorkExecutorVisitable<T> work, Transacti
120164}
121165}
122166
123- private <T > T doTheWorkInNoTransaction (WorkExecutorVisitable <T > work ) {
124- return doTheWork ( work );
125- }
126-
127167private <T > T doTheWork (WorkExecutorVisitable <T > work ) {
128168try {
129169// obtain our isolated connection
@@ -152,4 +192,9 @@ private <T> T doTheWork(WorkExecutorVisitable<T> work) {
152192throw sqlExceptionHelper ().convert ( e , "unable to obtain isolated JDBC connection" );
153193}
154194}
195+
196+ // Callable that does not throw Exception; in Java <8 there's no Supplier
197+ private interface HibernateCallable <T > {
198+ T call () throws HibernateException ;
199+ }
155200}
0 commit comments