在CSDN的JAVA基础版,常常有人问及如何得到PreparedStatement最终执行的SQL语句;或者如何在控制台输出占位符的真实值.....
原因就是PreparedStatement执行的sql语句有大量的占位符?....
问题诸如JDBC中:
如何得到 conn.prepareStatement 最终执行的sql语句。
sql="update table1 set a=?,b=?"
stmt = con.prepareStatement(sql);
stmt.setObjec t(1,"a");
stmt.setObjec t(2,"b");
希望可以通过stmt或者conn 得到:
update table1 set a='a',b='b'
亦或Hibernate中
如我执行:find("select * from t_table where id = ?",new Integer(5));
在控制台显示SQL时只显示:select * from t_table where id = ?
如何才能做到将控制台显示的占位符用其真实的值来替换?
即控制台输出时显示:select * from t_table where id = 5
无它,无论JDBC还是Hiberante都不提供默认解决方案,但是参数是设置进去的,我们在设置的过程中可以有充分的理由来截取并获得自己想要的东西,类似于AOP理论。
共享我在工程中的使用方法:
插入操作:
/**
     * 执行插入数据库的语句
     * @param sql
     * @param params
     * @return 返回生成的主键
     */
    public int executeInsert(String sql, Object[] params) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            //1 获得连接
            conn = MyDBConnection.getInstance().getConnection();
            //2 设置提交方式为程序控制
            conn.setAutoCommit(false);
            //3 获得语句对象
            pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            //4 设置SQL语句的参数
            if (null != params && 0 < params.length) {
                setParams(pstmt, params);
            }
            //5 打印SQL语句
            if (MyDBConstants.showSQL) {
                getPreparedSQL(sql, params);
            }
            //6 执行语句
            pstmt.executeUpdate();
            //7 程序提交
            conn.commit();
            //8 返回生成的主键
            rs = pstmt.getGeneratedKeys();
            int generatedKey = 0;
            if (rs.next()) {
                generatedKey = rs.getInt(1);
            }
            if (0 < generatedKey)
                throw new MySQLException("插入记录时出错");
            return generatedKey;
        } catch (SQLException e) {
            //回滚
            MyDBUtil.rollBack(conn);
            throw new MySQLException(e);
        } finally {
            //关闭打开的操作
            MyDBUtil.close(conn, pstmt, rs);
        }
    }
更新查找操作:
/**
     * 执行更新或者删除数据库的语句
     * @param sql
     * @param params
     * @return 返回执行成功与否
     */
    public boolean executeUpdateDel(String sql, Object[] params) {
        boolean isSuccess = false;
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            //1 获得连接
            conn = MyDBConnection.getInstance().getConnection();
            //2 设置提交方式为程序控制
            conn.setAutoCommit(false);
            //3 获得语句对象
            pstmt = conn.prepareStatement(sql);
            //4 设置SQL语句的参数
            if (null != params && 0 < params.length) {
                setParams(pstmt, params);
            }
            //5 打印SQL语句
            if (MyDBConstants.showSQL) {
                getPreparedSQL(sql, params);
            }
            //6 执行语句
            pstmt.executeUpdate();
            //7 程序提交
            conn.commit();
            //8 设置语句执行的标记
            isSuccess = true;
        } catch (SQLException e) {
            //回滚
            MyDBUtil.rollBack(conn);
            throw new MySQLException(e);
        } finally {
            //关闭打开的操作
            MyDBUtil.close(conn, pstmt);
        }
        return isSuccess;
    }
执行查询
 1 /**
 2      * 执行查询数据库的语句;
 9      *
10      * @return
11      */
12     public Object executeQuery(String sql, Object[] params) {
13         Connection conn = null;
14         PreparedStatement pstmt = null;
15         ResultSet rs = null;
16         try {
17             //1 获得连接
18             conn = MyDBConnection.getInstance().getConnection();
19             //2 设置提交方式为程序控制
20             conn.setAutoCommit(false);
21             //3 获得语句对象
22             pstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
23             //4 设置SQL语句的参数
24             if (null != params && 0 < params.length) {
25                 setParams(pstmt, params);
26             }
27             //5 打印SQL语句
28             if (MyDBConstants.showSQL) {
29                 getPreparedSQL(sql, params);
30             }
31             //6 执行语句
32             rs = pstmt.executeQuery();
33 
34             //9 程序提交
35             conn.commit();
36 
37             //10 获得记录
38             Object vo = new Object();
39             if (null != rs && rs.next()) {
40                 vo = rs2vo(rs);
41             }
42 //            return results;
43             return vo;
44         } catch (SQLException e) {
45             //回滚
46             MyDBUtil.rollBack(conn);
47             throw new MySQLException(e);
48         } finally {
49             //关闭打开的操作
50             MyDBUtil.close(conn, pstmt, rs);
51         }
52     }
看到
getPreparedSQL(sql, params)了么? 这个地方就是要实现我们预期效果的地方:

 得到PrepareStatement最终执行的sql语句的方法
得到PrepareStatement最终执行的sql语句的方法
 1 /**
 2      * 获得PreparedStatement向数据库提交的SQL语句
 3      * @param sql
 4      * @param params
 5      * @return
 6      */
 7     private String getPreparedSQL(String sql, Object[] params) {
 8         //1 如果没有参数,说明是不是动态SQL语句
 9                 int paramNum = 0;
10                 if (null != params)  paramNum = params.length;
11         if (1 > paramNum) return sql;
12         //2 如果有参数,则是动态SQL语句
13         StringBuffer returnSQL = new StringBuffer();
14         String[] subSQL = sql.split("\\?");
15         for (int i = 0; i < paramNum; i++) {
16             if (params[i] instanceof Date) {
17                 returnSQL.append(subSQL[i]).append(" '").append(MyDateUtil.dateUtil2SQL((java.util.Date)params[i])).append("' ");
18             } else {
19                 returnSQL.append(subSQL[i]).append(" '").append(params[i]).append("' ");
20             }
21         }
22 
23         if (subSQL.length > params.length) {
24             returnSQL.append(subSQL[subSQL.length - 1]);
25         }
26         return returnSQL.toString();
27     }
28 
29     /**
30      * 为PreparedStatement预编译的SQL语句设置参数
31      * @param pstmt
32      * @param params
33      */
34     private void setParams(PreparedStatement pstmt, Object[] params) {
35             if (null != params) {
36                 for (int i = 0, paramNum = params.length; i < paramNum; i++) {
37                     try {
38                         if (null != params[i] &&
39                             params[i] instanceof java.util.Date) {
40                             pstmt.setDate(i + 1, MyDateUtil.dateUtil2SQL(
41                                     (java.util.Date) params[i]));
42                         } else {
43                             pstmt.setObject(i + 1, params[i]);
44                         }
45                     } catch (SQLException e) {
46                         throw new MySQLException(e);
47                     }
48                 }
49             }
50     }
然后轻松核实你的控制台或者日志文件吧......