View Javadoc
1   /*
2    * Copyright (c) 2002-2021, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.importexport.business.importdata;
35  
36  import fr.paris.lutece.plugins.importexport.business.AbstractImportExportDAO;
37  import fr.paris.lutece.plugins.importexport.business.ColumnType;
38  import fr.paris.lutece.plugins.importexport.business.ImportExportElement;
39  import fr.paris.lutece.plugins.importexport.business.TableColumn;
40  import fr.paris.lutece.portal.service.i18n.I18nService;
41  import fr.paris.lutece.portal.service.plugin.Plugin;
42  import fr.paris.lutece.portal.service.util.AppException;
43  import fr.paris.lutece.portal.service.util.AppLogService;
44  import fr.paris.lutece.util.sql.DAOUtil;
45  import fr.paris.lutece.util.sql.Transaction;
46  
47  import java.sql.Date;
48  import java.sql.SQLException;
49  import java.sql.Timestamp;
50  import java.sql.Types;
51  import java.text.DateFormat;
52  import java.text.ParseException;
53  import java.util.Iterator;
54  import java.util.List;
55  import java.util.Locale;
56  
57  import org.apache.commons.codec.DecoderException;
58  import org.apache.commons.codec.binary.Hex;
59  import org.apache.commons.lang3.StringUtils;
60  
61  /**
62   * DAO to import elements from the database<br />
63   * <b>Warning, this DAO is state full !</b>
64   */
65  public class ImportDataDAO extends AbstractImportExportDAO
66  {
67      private static final String SQL_QUERY_SELECT = " SELECT ";
68      private static final String SQL_QUERY_FROM = " FROM ";
69      private static final String SQL_QUERY_INSERT_INTO = " INSERT INTO ";
70      private static final String SQL_QUERY_VALUES = " VALUES ";
71      private static final String SQL_QUERY_UPDATE = " UPDATE ";
72      private static final String SQL_QUERY_UPDATE_SET = " SET ";
73      private static final String SQL_QUERY_EQUALS = " = ? ";
74      private static final String SQL_QUERY_WHERE = " WHERE ";
75      private static final String SQL_QUERY_AND = " AND ";
76      private static final String SQL_QUERY_DELETE_FROM = " DELETE FROM ";
77  
78      private static final String CONSTANT_QUESTION_MARK = "?";
79      private static final String CONSTANT_COMA = ",";
80      private static final String CONSTANT_OPEN_PARENTHESIS = " ( ";
81      private static final String CONSTANT_CLOSE_PARENTHESIS = " ) ";
82      private static final String CONSTANT_SEMICOLON = ";";
83      private static final String CONSTANT_STRING_NULL = "null";
84      private static final String CONSTANT_HEXA_START = "0x";
85  
86      private static final String ERROR_EMPTY_TABLE_NAME = "importexport.import_data.errors.emptyTableName";
87      private static final String ERROR_EMPTY_COLUMN_LIST = "importexport.import_data.errors.emptyColumnList";
88      private static final String ERROR_MESSAGE_TRANSACTION_CLOSED = "importexport.import_data.errors.transactionClosed";
89      private static final String ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE = "importexport.import_data.errors.emptyColumnList";
90  
91      private String _strSqlInsert;
92      private String _strSqlUpdate;
93      private String _sqlCheckElement;
94      private List<TableColumn> _listTableColumns;
95      private String _strTableName;
96      private Transaction _transaction;
97      private Plugin _plugin;
98      private Locale _locale;
99  
100     /**
101      * Creates a new DAO to import elements. When the DAO is created, a database connection is opened. Therefore, either methods {@link #commitTransaction} or
102      * {@link #rollbackTransaction} <b>must</b> be called to close the connection
103      * 
104      * @param listTableColumns
105      *            The list of columns of the table to import
106      * @param strTableName
107      *            The name of the table to import data in
108      * @param plugin
109      *            The plugin to get the pool from
110      * @param locale
111      *            The locale to display errors in
112      * @throws AppException
113      *             If an error occurs during the initialization of this DAO
114      */
115     public ImportDataDAO( List<String> listTableColumns, String strTableName, Plugin plugin, Locale locale ) throws AppException
116     {
117         if ( StringUtils.isEmpty( strTableName ) )
118         {
119             throw new AppException( I18nService.getLocalizedString( ERROR_EMPTY_TABLE_NAME, locale ) );
120         }
121         if ( listTableColumns == null || listTableColumns.size( ) == 0 )
122         {
123             throw new AppException( I18nService.getLocalizedString( ERROR_EMPTY_COLUMN_LIST, locale ) );
124         }
125 
126         // We create the list of columns of the required table
127         this._strTableName = strTableName;
128         this._plugin = plugin;
129         this._locale = locale;
130         this._listTableColumns = getTableColumns( listTableColumns, strTableName, plugin, locale );
131         _transaction = new Transaction( );
132         if ( _transaction.getStatus( ) != Transaction.OPENED )
133         {
134             throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
135         }
136     }
137 
138     /**
139      * Insert an element to the database. The transaction is NOT committed by this method.
140      * 
141      * @param listElements
142      *            The list of elements to add in the statement. The number of elements and the name of columns must be the same as the columns associated with
143      *            this DAO. <br />
144      *            Their order must also be the same.
145      * @throws AppException
146      *             If an error occurred during the insertion
147      * @throws SQLException
148      *             If an error occurred with the database
149      */
150     public void insertElement( List<ImportExportElement> listElements ) throws AppException, SQLException
151     {
152         if ( _transaction == null || _transaction.getStatus( ) != Transaction.OPENED )
153         {
154             throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
155         }
156         if ( listElements == null || listElements.size( ) != _listTableColumns.size( ) )
157         {
158             AppException appException = new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
159             int nElemNumber = 0;
160             if ( listElements != null )
161             {
162                 nElemNumber = listElements.size( );
163             }
164             AppLogService.info( appException.getMessage( ) + " expected " + _listTableColumns.size( ) + " elements, found " + nElemNumber );
165             throw appException;
166         }
167         _transaction.prepareStatement( getSqlInsert( ) );
168         int nIndex = 1;
169         Iterator<TableColumn> columnIterator = _listTableColumns.iterator( );
170         for ( ImportExportElement element : listElements )
171         {
172             TableColumn tableColumn = columnIterator.next( );
173             // If the two lists are not synchronized, we throw an exception to skip this item
174             if ( !StringUtils.equalsIgnoreCase( tableColumn.getColumnName( ), element.getColumnName( ) ) )
175             {
176                 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
177             }
178             addSqlParameter( nIndex++, element.getValue( ), tableColumn.getColumnType( ) );
179         }
180         _transaction.executeStatement( );
181     }
182 
183     /**
184      * Update an element of the database. The transaction is NOT committed by this method.
185      * 
186      * @param listElements
187      *            The list of elements to add in the statement. The number of elements and the name of columns must be the same as the columns associated with
188      *            this DAO. <br />
189      *            Their order must also be the same.
190      * @throws AppException
191      *             If an error occurred during the update
192      * @throws SQLException
193      *             If an error occurred with the database
194      */
195     public void updateElement( List<ImportExportElement> listElements ) throws AppException, SQLException
196     {
197         if ( _transaction == null || _transaction.getStatus( ) != Transaction.OPENED )
198         {
199             throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
200         }
201         if ( listElements == null || listElements.size( ) != _listTableColumns.size( ) )
202         {
203             AppException appException = new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
204             int nElemNumber = 0;
205             if ( listElements != null )
206             {
207                 nElemNumber = listElements.size( );
208             }
209             AppLogService.info( appException.getMessage( ) + " expected " + _listTableColumns.size( ) + " elements, found " + nElemNumber );
210             throw appException;
211         }
212         _transaction.prepareStatement( getSqlUpdate( ) );
213         int nIndex = 1;
214         Iterator<TableColumn> columnIterator = _listTableColumns.iterator( );
215         for ( ImportExportElement element : listElements )
216         {
217             TableColumn tableColumn = columnIterator.next( );
218             // We skip primary keys that must be added at the end
219             if ( !tableColumn.getIsPrimaryKey( ) )
220             {
221                 // If the two lists are not synchronized, we throw an exception to skip this item
222                 if ( !StringUtils.equalsIgnoreCase( tableColumn.getColumnName( ), element.getColumnName( ) ) )
223                 {
224                     throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
225                 }
226                 addSqlParameter( nIndex++, element.getValue( ), tableColumn.getColumnType( ) );
227             }
228         }
229         // We now add primary keys
230         columnIterator = _listTableColumns.iterator( );
231         for ( ImportExportElement element : listElements )
232         {
233             TableColumn tableColumn = columnIterator.next( );
234             if ( tableColumn.getIsPrimaryKey( ) )
235             {
236                 if ( !StringUtils.equalsIgnoreCase( tableColumn.getColumnName( ), element.getColumnName( ) ) )
237                 {
238                     throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
239                 }
240                 addSqlParameter( nIndex++, element.getValue( ), tableColumn.getColumnType( ) );
241             }
242         }
243         _transaction.executeStatement( );
244     }
245 
246     /**
247      * Check if a row already exists in the database
248      * 
249      * @param listElements
250      *            The list of elements to check the existence of
251      * @return True if the element exists, false otherwise
252      * @throws SQLException
253      *             If an error occur while checking the existence of the element
254      */
255     public boolean checkElementExists( List<ImportExportElement> listElements ) throws SQLException
256     {
257         if ( listElements == null || listElements.size( ) != _listTableColumns.size( ) )
258         {
259             AppException appException = new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
260             int nElemNumber = 0;
261             if ( listElements != null )
262             {
263                 nElemNumber = listElements.size( );
264             }
265             AppLogService.info( appException.getMessage( ) + " expected " + _listTableColumns.size( ) + " elements, found " + nElemNumber );
266             throw appException;
267         }
268         DAOUtil daoUtil = new DAOUtil( getSqlCheckElementExists( ), _plugin );
269         boolean bResult = false;
270         try
271         {
272             String strPrimaryKey = listElements.get( 0 ).getValue( );
273             addSqlParameter( 1, strPrimaryKey, _listTableColumns.get( 0 ).getColumnType( ), daoUtil );
274             daoUtil.executeQuery( );
275             if ( daoUtil.next( ) )
276             {
277                 bResult = true;
278             }
279         }
280         catch( SQLException e )
281         {
282             AppLogService.error( e.getMessage( ), e );
283         }
284         finally
285         {
286             daoUtil.free( );
287         }
288 
289         return bResult;
290     }
291 
292     /**
293      * Remove every data from the table.
294      * 
295      * @throws SQLException
296      *             If an error occurs
297      */
298     public void emptyTable( ) throws SQLException
299     {
300         _transaction.prepareStatement( SQL_QUERY_DELETE_FROM + _strTableName );
301         _transaction.executeStatement( );
302     }
303 
304     /**
305      * Commit the transaction to the database, and close the connection.
306      */
307     public void commitTransaction( )
308     {
309         if ( _transaction != null )
310         {
311             _transaction.commit( );
312             _transaction = null;
313         }
314         else
315         {
316             SQLException sqlException = new SQLException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
317             AppLogService.error( sqlException.getMessage( ), sqlException );
318         }
319     }
320 
321     /**
322      * Roll back the transaction to the database, and close the connection.
323      */
324     public void rollbackTransaction( )
325     {
326         if ( _transaction != null )
327         {
328             _transaction.rollback( );
329             _transaction = null;
330         }
331         else
332         {
333             SQLException sqlException = new SQLException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
334             AppLogService.error( sqlException.getMessage( ), sqlException );
335         }
336     }
337 
338     /**
339      * Add a parameter to the current statement of the transaction according to its type.
340      * 
341      * @param nIndex
342      *            The index of the parameter to add
343      * @param strElementValue
344      *            The value of the parameter
345      * @param columnType
346      *            The type of the column
347      * @throws AppException
348      *             if the value of the parameter is not valid
349      * @throws SQLException
350      *             If an error occurred with the database
351      */
352     private void addSqlParameter( int nIndex, String strElementValue, ColumnType columnType ) throws SQLException, AppException
353     {
354         try
355         {
356             switch( columnType )
357             {
358                 case TYPE_INT:
359                     if ( isStringBlankOrNull( strElementValue ) )
360                     {
361                         _transaction.getStatement( ).setNull( nIndex, Types.INTEGER );
362                     }
363                     else
364                     {
365                         _transaction.getStatement( ).setInt( nIndex, Integer.parseInt( strElementValue ) );
366                     }
367                     break;
368                 case TYPE_LONG:
369                     if ( isStringBlankOrNull( strElementValue ) )
370                     {
371                         _transaction.getStatement( ).setNull( nIndex, Types.BIGINT );
372                     }
373                     else
374                     {
375                         _transaction.getStatement( ).setLong( nIndex, Long.parseLong( strElementValue ) );
376                     }
377                     break;
378                 case TYPE_DOUBLE:
379                     if ( isStringBlankOrNull( strElementValue ) )
380                     {
381                         _transaction.getStatement( ).setNull( nIndex, Types.DOUBLE );
382                     }
383                     else
384                     {
385                         _transaction.getStatement( ).setDouble( nIndex, Double.parseDouble( strElementValue ) );
386                     }
387                     break;
388                 case TYPE_STRING:
389                     _transaction.getStatement( ).setString( nIndex, strElementValue );
390                     break;
391                 case TYPE_TIMESTAMP:
392                     Timestamp timestamp;
393                     if ( isStringBlankOrNull( strElementValue ) )
394                     {
395                         timestamp = null;
396                     }
397                     else
398                     {
399                         // If the timestamp value is numeric
400                         if ( StringUtils.isNumeric( strElementValue ) )
401                         {
402                             timestamp = new Timestamp( Long.parseLong( strElementValue ) );
403                         }
404                         else
405                         {
406                             // If the timestamp value is literal
407                             try
408                             {
409                                 timestamp = Timestamp.valueOf( strElementValue );
410                             }
411                             catch( IllegalArgumentException e )
412                             {
413                                 throw new SQLException( e );
414                             }
415                         }
416                     }
417                     _transaction.getStatement( ).setTimestamp( nIndex, timestamp );
418                     break;
419                 case TYPE_DATE:
420                     Date date;
421                     if ( isStringBlankOrNull( strElementValue ) )
422                     {
423                         date = null;
424                     }
425                     else
426                     {
427                         try
428                         {
429                             date = new Date( DateFormat.getDateInstance( ).parse( strElementValue ).getTime( ) );
430                         }
431                         catch( ParseException e )
432                         {
433                             throw new SQLException( e );
434                         }
435                     }
436                     _transaction.getStatement( ).setDate( nIndex, date );
437                     break;
438                 case TYPE_BYTE:
439                     byte [ ] blobItem;
440                     if ( isStringBlankOrNull( strElementValue ) )
441                     {
442                         blobItem = null;
443                     }
444                     else
445                     {
446                         String strValue = strElementValue;
447                         // If the blob contains the sequence "0x" that indicates that it is encoded in hex, we remove it since we do know it is hex
448                         // Furthermore, the 'x' character is not a valid hex character, so we can safely remove it
449                         if ( strValue.startsWith( CONSTANT_HEXA_START ) )
450                         {
451                             strValue = strValue.substring( CONSTANT_HEXA_START.length( ) );
452                         }
453                         try
454                         {
455                             blobItem = Hex.decodeHex( strValue.toCharArray( ) );
456                         }
457                         catch( DecoderException e )
458                         {
459                             throw new SQLException( e );
460                         }
461                     }
462                     _transaction.getStatement( ).setBytes( nIndex, blobItem );
463                     break;
464                 default:
465                     AppLogService.error( "Unknown column type : " + columnType );
466             }
467         }
468         catch( SQLException e )
469         {
470             AppLogService.error( e.getMessage( ), e );
471             throw e;
472         }
473     }
474 
475     /**
476      * Add a parameter to a DAOUtil according to its type.
477      * 
478      * @param nIndex
479      *            The index of the parameter to add
480      * @param strElementValue
481      *            The value of the parameter
482      * @param columnType
483      *            The type of the column
484      * @param daoUtil
485      *            The DAOUtil to add the parameter to
486      * @throws AppException
487      *             if the value of the parameter is not valid
488      * @throws SQLException
489      *             If an error occurred with the database
490      */
491     private void addSqlParameter( int nIndex, String strElementValue, ColumnType columnType, DAOUtil daoUtil ) throws AppException, SQLException
492     {
493         try
494         {
495             switch( columnType )
496             {
497                 case TYPE_INT:
498                     if ( isStringBlankOrNull( strElementValue ) )
499                     {
500                         daoUtil.setIntNull( nIndex );
501                     }
502                     else
503                     {
504                         daoUtil.setInt( nIndex, Integer.parseInt( strElementValue ) );
505                     }
506                     break;
507                 case TYPE_LONG:
508                     if ( isStringBlankOrNull( strElementValue ) )
509                     {
510                         daoUtil.setLongNull( nIndex );
511                     }
512                     else
513                     {
514                         daoUtil.setLong( nIndex, Long.parseLong( strElementValue ) );
515                     }
516                     break;
517                 case TYPE_DOUBLE:
518                     if ( isStringBlankOrNull( strElementValue ) )
519                     {
520                         daoUtil.setDoubleNull( nIndex );
521                     }
522                     else
523                     {
524                         daoUtil.setDouble( nIndex, Double.parseDouble( strElementValue ) );
525                     }
526                     break;
527                 case TYPE_STRING:
528                     daoUtil.setString( nIndex, strElementValue );
529                     break;
530                 case TYPE_TIMESTAMP:
531                     Timestamp timestamp;
532                     if ( isStringBlankOrNull( strElementValue ) )
533                     {
534                         timestamp = null;
535                     }
536                     else
537                     {
538                         // If the timestamp value is numeric
539                         if ( StringUtils.isNumeric( strElementValue ) )
540                         {
541                             timestamp = new Timestamp( Long.parseLong( strElementValue ) );
542                         }
543                         else
544                         {
545                             // If the timestamp value is literal
546                             try
547                             {
548                                 timestamp = Timestamp.valueOf( strElementValue );
549                             }
550                             catch( IllegalArgumentException e )
551                             {
552                                 throw new AppException( );
553                             }
554                         }
555                     }
556                     daoUtil.setTimestamp( nIndex, timestamp );
557                     break;
558                 case TYPE_DATE:
559                     Date date;
560                     if ( isStringBlankOrNull( strElementValue ) )
561                     {
562                         date = null;
563                     }
564                     else
565                     {
566                         try
567                         {
568                             date = new Date( DateFormat.getDateInstance( ).parse( strElementValue ).getTime( ) );
569                         }
570                         catch( ParseException e )
571                         {
572                             throw new SQLException( e );
573                         }
574                     }
575                     daoUtil.setDate( nIndex, date );
576                     break;
577                 case TYPE_BYTE:
578                     byte [ ] blobItem;
579                     try
580                     {
581                         blobItem = Hex.decodeHex( strElementValue.toCharArray( ) );
582                     }
583                     catch( DecoderException e )
584                     {
585                         throw new SQLException( e );
586                     }
587                     daoUtil.setBytes( nIndex, blobItem );
588                     break;
589                 default:
590                     AppLogService.error( "Unknown column type : " + columnType );
591             }
592         }
593         catch( SQLException e )
594         {
595             AppLogService.error( e.getMessage( ), e );
596             throw e;
597         }
598     }
599 
600     /**
601      * Get the SQL script to insert an element of this DAO
602      * 
603      * @return The SQL script to insert an element of this DAO
604      */
605     private String getSqlInsert( )
606     {
607         if ( StringUtils.isNotBlank( _strSqlInsert ) )
608         {
609             return _strSqlInsert;
610         }
611         int nListSize = _listTableColumns.size( );
612         StringBuilder sbSql = new StringBuilder( SQL_QUERY_INSERT_INTO );
613         sbSql.append( _strTableName );
614         sbSql.append( CONSTANT_OPEN_PARENTHESIS );
615         sbSql.append( _listTableColumns.get( 0 ).getColumnName( ) );
616         for ( int i = 1; i < nListSize; i++ )
617         {
618             sbSql.append( CONSTANT_COMA );
619             sbSql.append( _listTableColumns.get( i ).getColumnName( ) );
620         }
621         sbSql.append( CONSTANT_CLOSE_PARENTHESIS );
622         sbSql.append( SQL_QUERY_VALUES );
623         sbSql.append( CONSTANT_OPEN_PARENTHESIS );
624         sbSql.append( CONSTANT_QUESTION_MARK );
625         for ( int i = 1; i < nListSize; i++ )
626         {
627             sbSql.append( CONSTANT_COMA );
628             sbSql.append( CONSTANT_QUESTION_MARK );
629         }
630         sbSql.append( CONSTANT_CLOSE_PARENTHESIS );
631         sbSql.append( CONSTANT_SEMICOLON );
632 
633         _strSqlInsert = sbSql.toString( );
634         return _strSqlInsert;
635     }
636 
637     /**
638      * Get the SQL script to update an element of this DAO
639      * 
640      * @return The SQL script to update an element of this DAO
641      */
642     private String getSqlUpdate( )
643     {
644         if ( StringUtils.isNotBlank( _strSqlUpdate ) )
645         {
646             return _strSqlUpdate;
647         }
648         StringBuilder sbSql = new StringBuilder( SQL_QUERY_UPDATE );
649         sbSql.append( _strTableName );
650         sbSql.append( SQL_QUERY_UPDATE_SET );
651 
652         boolean bIsFirstColumn = true;
653         for ( TableColumn tableColumn : _listTableColumns )
654         {
655             if ( !tableColumn.getIsPrimaryKey( ) )
656             {
657                 if ( bIsFirstColumn )
658                 {
659                     bIsFirstColumn = false;
660                 }
661                 else
662                 {
663                     sbSql.append( CONSTANT_COMA );
664                 }
665                 sbSql.append( tableColumn.getColumnName( ) );
666                 sbSql.append( SQL_QUERY_EQUALS );
667             }
668         }
669         sbSql.append( SQL_QUERY_WHERE );
670         bIsFirstColumn = true;
671         for ( TableColumn tableColumn : _listTableColumns )
672         {
673             if ( tableColumn.getIsPrimaryKey( ) )
674             {
675                 if ( bIsFirstColumn )
676                 {
677                     bIsFirstColumn = false;
678                 }
679                 else
680                 {
681                     sbSql.append( SQL_QUERY_AND );
682                 }
683                 sbSql.append( tableColumn.getColumnName( ) );
684                 sbSql.append( SQL_QUERY_EQUALS );
685             }
686         }
687 
688         _strSqlUpdate = sbSql.toString( );
689         return _strSqlUpdate;
690     }
691 
692     /**
693      * Get the SQL query to check if an item already exist in the table of the database
694      * 
695      * @return The SQL query to execute
696      */
697     private String getSqlCheckElementExists( )
698     {
699         if ( StringUtils.isNotBlank( _sqlCheckElement ) )
700         {
701             return _sqlCheckElement;
702         }
703         StringBuilder sbSql = new StringBuilder( SQL_QUERY_SELECT );
704         sbSql.append( _listTableColumns.get( 0 ).getColumnName( ) );
705         sbSql.append( SQL_QUERY_FROM );
706         sbSql.append( _strTableName );
707         sbSql.append( SQL_QUERY_WHERE );
708         sbSql.append( _listTableColumns.get( 0 ).getColumnName( ) );
709         sbSql.append( SQL_QUERY_EQUALS );
710         _sqlCheckElement = sbSql.toString( );
711         return _sqlCheckElement;
712     }
713 
714     /**
715      * Check if a string is null, empty, blank or equals to the 'null' string.
716      * 
717      * @param strString
718      *            The string to check
719      * @return True if the string null, empty, blank or equals to the 'null' string, false otherwise
720      */
721     private boolean isStringBlankOrNull( String strString )
722     {
723         return StringUtils.isBlank( strString ) || StringUtils.equalsIgnoreCase( strString, CONSTANT_STRING_NULL );
724     }
725 
726     /**
727      * Finalize the DAO. If the transaction has not been closed, then it is rolled backed and closed
728      * 
729      * @throws Throwable
730      *             If an exception is thrown
731      */
732     @Override
733     protected void finalize( ) throws Throwable
734     {
735         if ( _transaction != null )
736         {
737             _transaction.rollback( );
738         }
739         super.finalize( );
740     }
741 }