1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.util.sql;
35
36 import fr.paris.lutece.portal.service.database.AppConnectionService;
37 import fr.paris.lutece.portal.service.database.PluginConnectionService;
38 import fr.paris.lutece.portal.service.plugin.Plugin;
39 import fr.paris.lutece.portal.service.util.AppException;
40
41 import org.apache.commons.lang.StringUtils;
42
43 import org.apache.log4j.Logger;
44
45 import java.sql.Connection;
46 import java.sql.PreparedStatement;
47 import java.sql.SQLException;
48
49
50
51
52
53 public class Transaction
54 {
55
56
57
58 public static final int OPENED = -1;
59
60
61
62
63 public static final int COMMITTED = 0;
64
65
66
67
68 public static final int ROLLEDBACK = 1;
69 private static final String DEFAULT_MODULE_NAME = "core";
70 private static final String LOGGER_DEBUG_SQL = "lutece.debug.sql.";
71
72
73
74
75 private String _strSQL = StringUtils.EMPTY;
76
77
78 private Connection _connection;
79
80
81 private PluginConnectionService _connectionService;
82
83
84 private String _strPluginName;
85
86
87 private Logger _logger;
88 private PreparedStatement _statement;
89 private int _nStatus = OPENED;
90 private boolean _bAutoCommit;
91
92
93
94
95 public Transaction( )
96 {
97 beginTransaction( null );
98 }
99
100
101
102
103
104 public Transaction( Plugin plugin )
105 {
106 beginTransaction( plugin );
107 }
108
109
110
111
112
113
114
115 public PreparedStatement prepareStatement( String strSQL )
116 throws SQLException
117 {
118
119 if ( _statement != null )
120 {
121 _statement.close( );
122 }
123
124
125 _strSQL = strSQL;
126
127 if ( _connection == null )
128 {
129 throw new SQLException( "Plugin : '" + _strPluginName +
130 "' - Connection has been closed. The new prepared statement can not be created : " + strSQL );
131 }
132
133 _statement = _connection.prepareStatement( _strSQL );
134
135 return _statement;
136 }
137
138
139
140
141
142 public PreparedStatement getStatement( )
143 {
144 return _statement;
145 }
146
147
148
149
150
151 public void executeStatement( ) throws SQLException
152 {
153 _logger.debug( "Plugin : '" + _strPluginName + "' - EXECUTE STATEMENT : " + _strSQL );
154 _statement.executeUpdate( );
155 }
156
157
158
159
160 public void commit( )
161 {
162 try
163 {
164 if ( _connection == null )
165 {
166 throw new SQLException( "Plugin : '" + _strPluginName +
167 "' - Transaction has already been closed and can not be committed" );
168 }
169
170 _connection.commit( );
171 _logger.debug( "Plugin : '" + _strPluginName + "' - COMMIT TRANSACTION" );
172 closeTransaction( COMMITTED );
173 }
174 catch ( SQLException e )
175 {
176 rollback( e );
177 }
178 }
179
180
181
182
183 public void rollback( )
184 {
185 rollback( null );
186 }
187
188
189
190
191
192 public void rollback( Exception e )
193 {
194 if ( e != null )
195 {
196 _logger.error( "Transaction Error - Rollback in progress " + e.getMessage( ), e.getCause( ) );
197 }
198
199 try
200 {
201 if ( _connection != null )
202 {
203 _connection.rollback( );
204 _logger.debug( "Plugin : '" + _strPluginName + "' - ROLLBACK TRANSACTION" );
205 }
206 else
207 {
208 _logger.debug( "Plugin : '" + _strPluginName + "' - TRANSACTION HAS ALREADY BEEN ROLLED BACK" );
209 }
210 }
211 catch ( SQLException ex )
212 {
213 _logger.error( "Transaction Error - Rollback error : " + ex.getMessage( ), ex.getCause( ) );
214 }
215 finally
216 {
217 closeTransaction( ROLLEDBACK );
218 }
219 }
220
221
222
223
224
225 public int getStatus( )
226 {
227 return _nStatus;
228 }
229
230
231
232
233
234
235 protected Connection getConnection( )
236 {
237 return _connection;
238 }
239
240
241
242
243
244 protected void beginTransaction( Plugin plugin )
245 {
246 if ( plugin != null )
247 {
248 _strPluginName = plugin.getName( );
249 _connectionService = plugin.getConnectionService( );
250 }
251 else
252 {
253 _strPluginName = DEFAULT_MODULE_NAME;
254 _connectionService = AppConnectionService.getDefaultConnectionService( );
255 }
256
257 if ( _connectionService == null )
258 {
259 throw new AppException( "Database access error. Please check component installations and db.properties." );
260 }
261
262 _logger = Logger.getLogger( LOGGER_DEBUG_SQL + _strPluginName );
263 _logger.debug( "Plugin : '" + _strPluginName + "' - BEGIN TRANSACTION" );
264
265 try
266 {
267 _connection = _connectionService.getConnection( );
268
269
270 _bAutoCommit = _connection.getAutoCommit( );
271 _connection.setAutoCommit( false );
272 }
273 catch ( SQLException e )
274 {
275 rollback( e );
276 }
277 }
278
279
280
281
282
283 private void closeTransaction( int nStatus )
284 {
285 _nStatus = nStatus;
286
287 try
288 {
289 if ( _statement != null )
290 {
291 _statement.close( );
292 }
293
294
295 if ( _connection != null )
296 {
297 _connection.setAutoCommit( _bAutoCommit );
298 }
299 }
300 catch ( SQLException ex )
301 {
302 _logger.error( "Transaction Error - Unable to close transaction " + ex.getMessage( ), ex.getCause( ) );
303 }
304 finally
305 {
306 _connectionService.freeConnection( _connection );
307 _connection = null;
308 }
309 }
310
311
312
313
314
315
316 @Override
317 protected void finalize( ) throws Throwable
318 {
319 if ( _nStatus == OPENED )
320 {
321 _logger.error( "The transaction has not been commited" );
322 closeTransaction( OPENED );
323 }
324
325 super.finalize( );
326 }
327 }