1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.db.wrapper;
22  
23  import java.sql.Connection;
24  import java.sql.PreparedStatement;
25  import java.sql.SQLException;
26  
27  import org.efaps.db.Context;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  
32  /**
33   * <p>An easy wrapper for a SQL update statement. To initialize this class use
34   * {@link org.efaps.db.databases.AbstractDatabase#newUpdate(String, String, long)}
35   * to get a database specific update.</p>
36   *
37   * <p><b>Example:</b><br/>
38   * <pre>
39   * SQLUpdate insert = Context.getDbType().newUpdate("MYTABLE", "ID", 12);
40   * </pre></p>
41   *
42   * @author The eFaps Team
43   * @version $Id$
44   */
45  public class SQLUpdate
46      extends AbstractSQLInsertUpdate<SQLUpdate>
47  {
48      /**
49       * Logging instance used in this class.
50       */
51      private static final Logger LOG = LoggerFactory.getLogger(SQLUpdate.class);
52  
53      /**
54       * Id of the row which is updated.
55       */
56      private final long id;
57  
58  
59      /**
60       * Initializes this update. Do not call the constructor directly, instead
61       * use
62       * {@link org.efaps.db.databases.AbstractDatabase#newUpdate(String, String, long)}
63       * to get the database specific implementation.
64       *
65       * @param _tableName    name of the table to update
66       * @param _idCol        name of the column with the id
67       * @param _id           id to update
68       */
69      public SQLUpdate(final String _tableName,
70                       final String _idCol,
71                       final long _id)
72      {
73          super(_tableName, _idCol);
74          this.id = _id;
75      }
76  
77      /**
78       * Executes the SQL update.
79       *
80       * @param _con      SQL connection
81       * @throws SQLException if update failed or the row for given {@link #id}
82       *                      does not exists
83       */
84      public void execute(final Connection _con)
85          throws SQLException
86      {
87          final StringBuilder cmd = new StringBuilder()
88              .append(Context.getDbType().getSQLPart(SQLPart.UPDATE)).append(" ")
89              .append(Context.getDbType().getTableQuote())
90              .append(getTableName())
91              .append(Context.getDbType().getTableQuote()).append(" ")
92              .append(Context.getDbType().getSQLPart(SQLPart.SET)).append(" ");
93  
94          // append SQL values
95          boolean first = true;
96          for (final ColumnWithSQLValue col : getColumnWithSQLValues())  {
97              if (first)  {
98                  first = false;
99              } else  {
100                 cmd.append(Context.getDbType().getSQLPart(SQLPart.COMMA));
101             }
102             cmd.append(Context.getDbType().getColumnQuote())
103                 .append(col.getColumnName())
104                 .append(Context.getDbType().getColumnQuote())
105                 .append(Context.getDbType().getSQLPart(SQLPart.EQUAL))
106                 .append(col.getSqlValue());
107         }
108 
109         // append values
110         for (final AbstractColumnWithValue<?> col : getColumnWithValues())  {
111             if (first)  {
112                 first = false;
113             } else  {
114                 cmd.append(Context.getDbType().getSQLPart(SQLPart.COMMA));
115             }
116             cmd.append(Context.getDbType().getColumnQuote())
117                 .append(col.getColumnName())
118                 .append(Context.getDbType().getColumnQuote())
119                 .append(Context.getDbType().getSQLPart(SQLPart.EQUAL))
120                 .append("?");
121         }
122 
123         // append where clause
124         cmd.append(" ").append(Context.getDbType().getSQLPart(SQLPart.WHERE)).append(" ")
125             .append(Context.getDbType().getColumnQuote())
126             .append(getIdColumn())
127             .append(Context.getDbType().getColumnQuote())
128             .append(Context.getDbType().getSQLPart(SQLPart.EQUAL))
129             .append("?");
130 
131         if (SQLUpdate.LOG.isDebugEnabled()) {
132             SQLUpdate.LOG.debug(cmd.toString());
133         }
134 
135         final PreparedStatement stmt = _con.prepareStatement(cmd.toString());
136         int index = 1;
137         for (final AbstractColumnWithValue<?> col : getColumnWithValues())  {
138             if (SQLUpdate.LOG.isDebugEnabled()) {
139                 SQLUpdate.LOG.debug("    " + index + " = " + col.getValue());
140             }
141             col.set(index++, stmt);
142         }
143 
144         if (SQLUpdate.LOG.isDebugEnabled()) {
145             SQLUpdate.LOG.debug("    " + index + " = " + this.id);
146         }
147         stmt.setLong(index, this.id);
148 
149         try  {
150             final int rows = stmt.executeUpdate();
151             if (rows == 0) {
152                 throw new SQLException("Object for SQL table '" + getTableName()
153                         + "' with id '" + this.id + "' does not exists and was not updated.");
154             }
155         } finally  {
156             stmt.close();
157         }
158     }
159 
160     /**
161      * Getter method for the instance variable {@link #id}.
162      *
163      * @return value of instance variable {@link #id}
164      */
165     public long getId()
166     {
167         return this.id;
168     }
169 }