在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.length; i++) {
values[i] = "?";
}
String sql_field = tool.arryToString(fields, ",");
String sql_values = tool.arryToString(values, ",");
preparedStatementInsert = "insert into " + tableName + " (" + sql_field + " ) values (" + sql_values + ")";//合成preparedStatement语句
完整地源代码参见源文件ProcessVO.java的方法_preparedStatementInsert。
通过以上算法,可以看出,JadePool不需要xml映射、注入映射,而是通过查询已经实例化的DbCenter实例得到数据库的结构信息;对照数据库结构信息过滤掉无效字段,进一步区分主键字段、非主键字段,针对有效字段进一步合成插入语句;因此,JadePool插入操作具有较高的智能化水平,给JadePool用户带来了方便。