SQLCommand.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:20k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: SQLCommand.java,v 1.10 2005/10/10 17:01:15 rbair Exp $
  3.  *
  4.  * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
  5.  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  * 
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21. package org.jdesktop.dataset.provider.sql;
  22. import java.beans.PropertyChangeListener;
  23. import java.beans.PropertyChangeSupport;
  24. import java.sql.PreparedStatement;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import org.jdesktop.dataset.DataColumn;
  29. import org.jdesktop.dataset.DataRow;
  30. /**
  31.  * <p>A fully customizeable DataCommand for use with a {@link SQLDataProvider}. This
  32.  * DataCommand requires the user to specify their select, insert, update and
  33.  * delete sql statements manually using {@link #setSelectSQL(String)}, 
  34.  * {@link #setInsertSQL(String)}, {@link #setUpdateSQL(String)}, 
  35.  * {@link #setDeleteSQL(String)}. 
  36.  * 
  37.  * <p>The SQL for these statements can
  38.  * contain named parameters. As a DataCommand, the SQLCommand can track values for named
  39.  * parameters ({@link org.jdesktop.dataset.DataCommand#setParameter(String, Object)}, so that when the 
  40.  * SQLDataProvider requests the PreparedStatement to execute, the parameters in the SQL
  41.  * statement are assigned the values stored in the DataCommand. For example, suppose your
  42.  * SQLCommand instance was only to work with a row in the Employee table for "Jones". You'd
  43.  * do the following:
  44.  * <pre>
  45.  * SQLCommand cmd = new SQLCommand();
  46.  * cmd.setSelectSql("Select * from Employee where name = :emp-name");
  47.  * cmd.setParameter("emp-name", "Jones");
  48.  * </pre>
  49.  * The INSERT, UPDATE, and DELETE statements can access any of the parameters defined in this
  50.  * DataCommand as well.
  51.  * 
  52.  * <p>SQLCommand also allows you to specify a simplified set of criteria to base your query on. You may,
  53.  * for instance, simply specify the name of the table and the select, insert, update and delete queries
  54.  * will be automatically generated for you. A flag indicates whether to use custom SQL queries, or to use
  55.  * the simplified query generation routines</p>
  56.  *
  57.  * @author rbair
  58.  */
  59.  // TODO Optionally, a count SQL statement can be specified which will be used for provider better feedback to the user (percent done, total number of records to read, time estimate, etc).
  60. public class SQLCommand extends AbstractSqlCommand {
  61.     private String deleteSql;
  62.     private String insertSql;
  63.     private String selectSql;
  64.     private String updateSql;
  65.     private boolean custom;
  66.     /**
  67.      * The name of the table from which to get results. If this value is
  68.      * null, then the TableCommand is in an uninitialized state
  69.      */
  70.     private String tableName;
  71.     /**
  72.      * The where clause for this query. This is never null, but may be empty
  73.      */
  74.     private String whereClause = "";
  75.     /**
  76.      * The order by clause for this query. This is never null, but may be empty
  77.      */
  78.     private String orderByClause = "";
  79.     /**
  80.      * The having clause for this query. This is never null, but may be empty
  81.      */
  82.     private String havingClause = "";
  83.     
  84.     /**
  85.      * Helper used for notifying of bean property changes.
  86.      */
  87.     private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  88.     
  89.     /** 
  90.      * Creates a new instance of TableCommand 
  91.      */
  92.     public SQLCommand() {
  93.     }
  94.     public SQLCommand(String tableName) {
  95.         this(tableName, null);
  96.     }
  97.     
  98.     public SQLCommand(String tableName, String whereClause) {
  99.         setTableName(tableName);
  100.         setWhereClause(whereClause);
  101.     }
  102.     /**
  103.      */
  104.     public void setSelectSQL(String sql) {
  105.         // TODO: this is a string, why use != (PWW 04/25/05)
  106.         if (this.selectSql != sql) {
  107.             String oldValue = this.selectSql;
  108.             this.selectSql = sql;
  109.             custom = true;
  110.             pcs.firePropertyChange("selectSql", oldValue, sql);
  111.         }
  112.     }
  113.     
  114.     public String getSelectSQL() {
  115.         return selectSql;
  116.     }
  117.     
  118.     /**
  119.      */
  120.     public void setUpdateSQL(String sql) {
  121.         if (this.updateSql != sql) {
  122.             String oldValue = this.updateSql;
  123.             this.updateSql = sql;
  124.             custom = true;
  125.             pcs.firePropertyChange("updateSql", oldValue, sql);
  126.         }
  127.     }
  128.     
  129.     public String getUpdateSQL() {
  130.         return updateSql;
  131.     }
  132.     
  133.     /**
  134.      */
  135.     public void setInsertSQL(String sql) {
  136.         if (this.insertSql != sql) {
  137.             String oldValue = this.insertSql;
  138.             this.insertSql = sql;
  139.             custom = true;
  140.             pcs.firePropertyChange("insertSql", oldValue, sql);
  141.         }
  142.     }
  143.     
  144.     public String getInsertSQL() {
  145.         return insertSql;
  146.     }
  147.     
  148.     /**
  149.      */
  150.     public void setDeleteSQL(String sql) {
  151.         if (this.deleteSql != sql) {
  152.             String oldValue = this.deleteSql;
  153.             this.deleteSql = sql;
  154.             custom = true;
  155.             pcs.firePropertyChange("deleteSql", oldValue, sql);
  156.         }
  157.     }
  158.     
  159.     public String getDeleteSQL() {
  160.         return deleteSql;
  161.     }
  162.     
  163.     public boolean isCustom() {
  164.         return custom;
  165.     }
  166.     
  167.     public void setCustom(boolean c) {
  168.         if (custom != c) {
  169.             custom = c;
  170.             pcs.firePropertyChange("custom", !custom, custom);
  171.         }
  172.     }
  173.     
  174.     /**
  175.      * Sets the name of the table in the Database from which to load/save
  176.      * data
  177.      */
  178.     public void setTableName(String tableName) {
  179.         if (this.tableName != tableName) {
  180.             String oldValue = this.tableName;
  181.             this.tableName = tableName;
  182.             pcs.firePropertyChange("tableName", oldValue, tableName);
  183.         }
  184.     }
  185.     
  186.     public String getTableName() {
  187.         return tableName;
  188.     }
  189.     
  190.     /**
  191.      * Sets the where clause to use in the query. This clause *must* include
  192.      * the &quot;where&quot; keyword
  193.      */
  194.     public void setWhereClause(String clause) {
  195.         if (whereClause != clause) {
  196.             String oldValue = this.whereClause;
  197.             whereClause = clause == null ? "" : clause;
  198.             pcs.firePropertyChange("whereClause", oldValue, whereClause);
  199.         }
  200.     }
  201.     
  202.     public String getWhereClause() {
  203.         return whereClause;
  204.     }
  205.     
  206.     public void setOrderByClause(String clause) {
  207.         if (orderByClause != clause) {
  208.             String oldValue = this.orderByClause;
  209.             orderByClause = clause == null ? "" : clause;
  210.             pcs.firePropertyChange("orderByClause", oldValue, orderByClause);
  211.         }
  212.     }
  213.     
  214.     public String getOrderByClause() {
  215.         return orderByClause;
  216.     }
  217.     
  218.     public void setHavingClause(String clause) {
  219.         if (havingClause != clause) {
  220.             String oldValue = this.havingClause;
  221.             havingClause = clause == null ? "" : clause;
  222.             pcs.firePropertyChange("havingClause", oldValue, havingClause);
  223.         }
  224.     }
  225.     
  226.     public String getHavingClause() {
  227.         return havingClause;
  228.     }
  229.     
  230.     /**
  231.      * 
  232.      * @param listener
  233.      */
  234.     public void addPropertyChangeListener(PropertyChangeListener listener) {
  235.         pcs.addPropertyChangeListener(listener);
  236.     }
  237.     /**
  238.      * 
  239.      * @param propertyName
  240.      * @param listener
  241.      */
  242.     public void addPropertyChangeListener(String propertyName,
  243.             PropertyChangeListener listener) {
  244.         pcs.addPropertyChangeListener(propertyName, listener);
  245.     }
  246.     
  247.     /**
  248.      *
  249.      */
  250.     public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
  251.      pcs.removePropertyChangeListener(propertyName, listener);
  252.     }
  253.     public String[] getParameterNames() {
  254.         if (custom) {
  255.             return super.getParameterNames(new String[]{selectSql, updateSql, insertSql, deleteSql});
  256.         } else {
  257.             return super.getParameterNames(new String[]{whereClause, orderByClause, havingClause});
  258.         }
  259.     }
  260.     private PreparedStatement createPreparedStatement(String parameterizedSql, JDBCDataConnection conn) throws Exception {
  261.         //replace all of the named parameters in the sql with their
  262.         //corrosponding values. This is done by first converting the sql
  263.         //to proper JDBC sql by inserting '?' for each and every param.
  264.         //As this is done, a record is kept of which parameters go with
  265.         //which indexes. Then, the parameter values are applied.
  266.         //map containing the indexes for each named param
  267.         Map<String,List<Integer>> indexes = new HashMap<String,List<Integer>>();
  268.         String sql = constructSql(parameterizedSql, indexes);
  269.         PreparedStatement ps = conn.prepareStatement(sql);
  270.         //now, apply the given set of parameters
  271.         for (String paramName : getParameterNames()) {
  272.             List<Integer> list = indexes.get(paramName);
  273.             if (list != null) {
  274.                 for (int index : list) {
  275.                     ps.setObject(index + 1, getParameter(paramName));
  276.                 }
  277.             }
  278.         }
  279.         return ps;
  280.     }
  281.     
  282.     protected PreparedStatement getSelectStatement(JDBCDataConnection conn) throws Exception {
  283.         if (custom) {
  284.             if (selectSql == null) {
  285.                 //this SQLCommand has not been configured, throw an exception
  286.                 throw new Exception("SQLCommand not configured with a select sql statement");
  287.             }
  288.             try {
  289.                 return createPreparedStatement(selectSql, conn);
  290.             } catch (Exception e) {
  291.                 System.err.println(selectSql);
  292.                 e.printStackTrace();
  293.                 return null;
  294.             }
  295.         } else {
  296.             if (tableName == null) {
  297.                 //this TableCommand has not been configured, throw an exception
  298.                 throw new Exception("TableCommand not configured with a table name");
  299.             }
  300.             try {
  301.                 //construct the select sql by combining the tableName portion and
  302.                 //the various clause portions
  303.                 StringBuilder buffer = new StringBuilder();
  304.                 buffer.append("select * from ");
  305.                 buffer.append(tableName);
  306.                 buffer.append(" ");
  307.                 buffer.append(whereClause);
  308.                 buffer.append(" ");
  309.                 buffer.append(orderByClause);
  310.                 buffer.append(" ");
  311.                 buffer.append(havingClause);
  312.                 String sql = buffer.toString().trim();
  313.                 return createPreparedStatement(sql, conn);
  314.             } catch (Exception e) {
  315.                 e.printStackTrace();
  316.                 return null;
  317.             }
  318.         }
  319.     }
  320.     
  321.     protected PreparedStatement getUpdateStatement(JDBCDataConnection conn, DataRow row) throws Exception {
  322.         if (custom) {
  323.             if (updateSql == null) {
  324.                 //this SQLCommand has not been configured, throw an exception
  325.                 throw new Exception("SQLCommand not configured with an update sql statement");
  326.             }
  327.             try {
  328.                 Map<String,Object> values = new HashMap<String,Object>();
  329.                 //iterate over all of the columns in the row.
  330.                 List<DataColumn> columns = row.getTable().getColumns();
  331.                 for (int i=0; i<columns.size(); i++) {
  332.                     DataColumn col = columns.get(i);
  333.                     values.put(col.getName(), row.getValue(col));
  334.                 }
  335.                 //do the where clause
  336.                 int keyColCount = 0;
  337.                 for (int i=0; i<columns.size(); i++) {
  338.                     DataColumn col = columns.get(i);
  339.                     if (col.isKeyColumn()) {
  340.                         values.put("orig_" + col.getName(), row.getOriginalValue(col));
  341.                         keyColCount++;
  342.                     }
  343.                 }
  344.                 return super.prepareStatement(updateSql, values, conn);
  345.             } catch (Exception e) {
  346.                 System.err.println(updateSql);
  347.                 e.printStackTrace();
  348.                 return null;
  349.             }
  350.         } else {
  351.             if (tableName == null) {
  352.                 //this TableCommand has not been configured, throw an exception
  353.                 throw new Exception("TableCommand not configured with a table name");
  354.             }
  355.             try {
  356.                 Map<String,Object> values = new HashMap<String,Object>();
  357.                 //construct the select sql by combining the tableName portion and
  358.                 //the various clause portions
  359.                 StringBuilder buffer = new StringBuilder();
  360.                 buffer.append("update ");
  361.                 buffer.append(tableName);
  362.                 buffer.append(" set ");
  363.                 //iterate over all of the columns in the row. Each cell that has been
  364.                 //modified needs to be included in this update statement
  365.                 List<DataColumn> columns = row.getTable().getColumns();
  366.                 int modCount = 0;
  367.                 for (int i=0; i<columns.size(); i++) {
  368.                     DataColumn col = columns.get(i);
  369.                     if (row.isModified(col)) {
  370.                         buffer.append(col.getName());
  371.                         buffer.append(" = :" + col.getName() + ", ");
  372.                         values.put(col.getName(), row.getValue(col));
  373.                         modCount++;
  374.                     }
  375.                 }
  376.                 //if nothing was modified, skip this row
  377.                 if (modCount == 0) {
  378.                     return null;
  379.                 }
  380.                 //remove the trailing comma
  381.                 buffer.delete(buffer.length()-2, buffer.length());
  382.                 //do the where clause
  383.                 buffer.append(" where ");
  384.                 int keyColCount = 0;
  385.                 for (int i=0; i<columns.size(); i++) {
  386.                     DataColumn col = columns.get(i);
  387.                     if (col.isKeyColumn()) {
  388.                         buffer.append(col.getName());
  389.                         buffer.append(" = :orig_" + col.getName() + " and ");
  390.                         values.put("orig_" + col.getName(), row.getOriginalValue(col));
  391.                         keyColCount++;
  392.                     }
  393.                 }
  394.                 if (keyColCount == 0) {
  395.                     System.err.println("WARNING!!! No key columns were specified, the entire table '" + tableName + "' will be updated!!");
  396.                     //remove the where clause
  397.                     buffer.delete(buffer.length() - 7, buffer.length());
  398.                 } else {
  399.                     buffer.delete(buffer.length() - 4, buffer.length());
  400.                 }
  401.                 String sql = buffer.toString().trim();
  402.                 return super.prepareStatement(sql, values, conn);
  403.             } catch (Exception e) {
  404.                 e.printStackTrace();
  405.                 return null;
  406.             }
  407.         }
  408.     }
  409.     protected PreparedStatement getInsertStatement(JDBCDataConnection conn, DataRow row) throws Exception {
  410.         if (custom) {
  411.             if (insertSql == null) {
  412.                 //this SQLCommand has not been configured, throw an exception
  413.                 throw new Exception("SQLCommand not configured with an insert sql statement");
  414.             }
  415.             try {
  416.                 Map<String,Object> values = new HashMap<String,Object>();
  417.                 for (DataColumn col : row.getTable().getColumns()) {
  418.                     values.put(col.getName(), row.getValue(col));
  419.                 }
  420.                 return super.prepareStatement(insertSql, values, conn);
  421.             } catch (Exception e) {
  422.                 System.err.println(insertSql);
  423.                 e.printStackTrace();
  424.                 return null;
  425.             }
  426.         } else {
  427.             if (tableName == null) {
  428.                 //this TableCommand has not been configured, throw an exception
  429.                 throw new Exception("TableCommand not configured with a table name");
  430.             }
  431.             try {
  432.                 Map<String,Object> values = new HashMap<String,Object>();
  433.                 StringBuilder buffer = new StringBuilder();
  434.                 buffer.append("insert into ");
  435.                 buffer.append(tableName);
  436.                 buffer.append("(");
  437.                 for (DataColumn col : row.getTable().getColumns()) {
  438.                     buffer.append(col.getName());
  439.                     buffer.append(", ");
  440.                 }
  441.                 buffer.replace(buffer.length()-2, buffer.length(), ")");
  442.                 buffer.append(" values(");
  443.                 for (DataColumn col : row.getTable().getColumns()) {
  444.                     buffer.append(":" + col.getName() + ", ");
  445.                     values.put(col.getName(), row.getValue(col));
  446.                 }
  447.                 buffer.replace(buffer.length()-2, buffer.length(), ")");
  448.                 String sql = buffer.toString().trim();
  449.                 return super.prepareStatement(sql, values, conn);
  450.             } catch (Exception e) {
  451.                 e.printStackTrace();
  452.                 return null;
  453.             }
  454.         }
  455.     }
  456.     protected PreparedStatement getDeleteStatement(JDBCDataConnection conn, DataRow row) throws Exception {
  457.         if (custom) {
  458.             if (deleteSql == null) {
  459.                 //this SQLCommand has not been configured, throw an exception
  460.                 throw new Exception("SQLCommand not configured with a delete sql statement");
  461.             }
  462.             try {
  463.                 Map<String,Object> values = new HashMap<String,Object>();
  464.                 List<DataColumn> columns = row.getTable().getColumns();
  465.                 for (int i=0; i<columns.size(); i++) {
  466.                     DataColumn col = columns.get(i);
  467.                     if (col.isKeyColumn()) {
  468.                         values.put("orig_" + col.getName(), row.getOriginalValue(col));
  469.                     }
  470.                 }
  471.                 return super.prepareStatement(deleteSql, values, conn);
  472.             } catch (Exception e) {
  473.                 System.err.println(deleteSql);
  474.                 e.printStackTrace();
  475.                 return null;
  476.             }
  477.         } else {
  478.             if (tableName == null) {
  479.                 //this TableCommand has not been configured, throw an exception
  480.                 throw new Exception("TableCommand not configured with a table name");
  481.             }
  482.             try {
  483.                 Map<String,Object> values = new HashMap<String,Object>();
  484.                 StringBuilder buffer = new StringBuilder();
  485.                 buffer.append("delete from ");
  486.                 buffer.append(tableName);
  487.                 buffer.append(" where ");
  488.                 int keyColCount = 0;
  489.                 List<DataColumn> columns = row.getTable().getColumns();
  490.                 for (int i=0; i<columns.size(); i++) {
  491.                     DataColumn col = columns.get(i);
  492.                     if (col.isKeyColumn()) {
  493.                         buffer.append(col.getName());
  494.                         buffer.append(" = :orig_" + col.getName() + " and ");
  495.                         values.put("orig_" + col.getName(), row.getOriginalValue(col));
  496.                         keyColCount++;
  497.                     }
  498.                 }
  499.                 if (keyColCount == 0) {
  500.                     System.err.println("WARNING!!! No key columns were specified, the entire table '" + tableName + "' will be deleted!!");
  501.                     //remove the where clause
  502.                     buffer.delete(buffer.length() - 7, buffer.length());
  503.                 } else {
  504.                     buffer.delete(buffer.length() - 4, buffer.length());
  505.                 }
  506.                 String sql = buffer.toString().trim();
  507.                 return super.prepareStatement(sql, values, conn);
  508.             } catch (Exception e) {
  509.                 e.printStackTrace();
  510.                 return null;
  511.             }
  512.         }
  513.     }
  514. }