日期:2014-05-16  浏览次数:20495 次

合成PreparedStatement插入语句

在JadePool中,支持多种插入记录的方法,最重要、最方便、最常用方法是:

public int insert(String tableName, Map<String, Object> mapRecord) throws SQLException //插入单条记录
public int insert(String tableName, Map<String, Object> mapRecord, boolean autoInsertKey) throws SQLException //插入单条记录,并自动插入主键值
public int insert(String tableName, List<Map> listRecord) throws SQLException////插入多条记录
public int insert(String tableName, List<Map> listRecord, boolean autoInsertKey) throws SQLException //插入多条记录,并自动插入主键值

它们都调用底层最核心的方法

private int _preparedStatementInsert(String tableName, List<Map> listRecord, boolean autoInsertKey) throws SQLException

我们从这些方法的参数可以看出,待插入的数据是Map变量或者是List<Map>变量,至于怎样完成插入操作,用户不需要关心,用户只需要把待插入的数据准备好就可以了。在Map变量中,只有键名等于表的字段名的数据才会插入到表中

JadePool是怎样施展魔法,将这些记录插入到数据库中的呢?

先看下面调用PreparedStatement插入记录的示意性代码:

    private java.sql.Connection con;

    public int preparedStatementInsert() throws SQLException, FileNotFoundException {
        String preparedStatement_insert = "insert into tableName  (col_long,col_string,col_binarystream,col_date ) values (?,?,?,?)";
        //设字段1是长整形,字段2是字符串型,字段3是Blob型,字段n是日期型
        PreparedStatement pstmt = con.prepareStatement(preparedStatement_insert);
        pstmt.setLong(1, 123l);
        pstmt.setString(2, "HashMap关系数据映射技术");
        File f = new File("d:\\a.jpg");
        FileInputStream is = new FileInputStream(f);
        pstmt.setBinaryStream(3, is);
        pstmt.setDate(4, new java.sql.Date(System.currentTimeMillis()));
        int num = pstmt.executeUpdate();
        return num;
    }

_preparedStatementInsert会根据参数自动合成PreparedStatement插入语句preparedStatementInsert,这是确保成功插入记录的关键。

_preparedStatementInsert在合成插入语句preparedStatementInsert上做了以下工作:

  • 过滤mapRecord记录中无效字段,得有效字段Object[] fields

  • 根据isUpdateKey对有效字段继续分组:true时,再得主键字段组Object[] keys和非主键字段组Object[]fields

  • 自动组合成PreparedStatement所需要的插入语句,算法如下:

        String preparedStatementInsert = "";

        Map<String, Object> _m = new LinkedHashMap(listRecord.get(0));//获取一条记录,作为创建preparedStatementSQL语句的依据
        Object maxFieldValue = null;
        String[] tableFields = db.getFields(tableName);//表中的字段名的集合 //db是DbCenter的一个实例
        String[] tableKeys = db.getKeys(tableName);//表中的主键字段集
        if (autoInsertKey) {
            Map lastRecord = this.queryLastRecord(tableName);//准备自动插入的主键
            if (tableKeys.length > 0) {
                maxFieldValue = lastRecord.get(tableKeys[0]);
                _m.put(tableKeys[0], "");//防止记录中不含tableKeys[0]主键字段
            } else {
                maxFieldValue = lastRecord.get(tableFields[0]);
                _m.put(tableFields[0], "");//防止记录中不含tableKeys[0]主键字段
            }
        }
        Object[] recordFields = (_m.keySet()).toArray(); //获取记录里的字段名的集合
        //private JadeTool tool = new JadeTool();
        for (int i = 0; i < recordFields.length; i++) {
            if (!tool.isInFields(tableFields, recordFields[i].toString())) {
                _m.remove(recordFields[i].toString());//移除无效字段, 查看记录中的字段在表中是否存在,如果不存在,则移除 
            }
        }

        Object[] fields = (_m.keySet()).toArray(); //过滤后的有效字段
        String[] values = new String[fields.length]; //保存通配符'?'
        for (int i = 0; i < fields.