SQL的绑定参数后就可以执行了,主要有三个方法,填充主键到对象、更新、查询。定义了一个接口如下:
public interface DataBind {
public Object fillPrimaryKey(Method method, Object object) throws Exception;
public Object excuteUpdate(String sql, Object object, boolean isAutoIncrement) throws Exception;
public List<CaseInsensitiveMap<String, Object>> excuteQuery(String sql, Object object) throws Exception;
}
初始我们限定了数据访问层传递的参数只有一个,类型可以是一个实体对象、Map、八点基本类型+Stirng和java.util.Date、或者不传,对于不同的类型,参数的绑定都是不同,所以定义了几个不同的实现类来应对不同参数的场景。
1、BeanDataBind处理传参为实体对象时的数据绑定
2、MapDataBind处理传参为Map时的数据绑定
3、NullDataBind处理不传参的场景
4、PrimitiveDataBind处理传参为基本类型的场景
类的UML图如下:
接下来看,SQL的执行过程都定义在AbstractDataBind中。
1、主键的填充到对象,必须在insert之前执行
public Object fillPrimaryKey(Method method, Object object) throws Exception {
PreparedStatement pst = null;
ResultSet rs = null;
try {
GetPrimaryKey getPrimaryKey = method.getAnnotation(GetPrimaryKey.class);
Connection connection = ConnectionThreadVariable.getConnetion();
pst = connection.prepareStatement(getPrimaryKey.sql());
rs = pst.executeQuery();
rs.next();
Object primaryKey = rs.getObject(1);
fillPrimaryKeyToObject(object, getPrimaryKey.primaryKeyProperty(), primaryKey);
logger.debug("执行:" + getPrimaryKey.sql() + ",执行结果:" + primaryKey);
return primaryKey;
} catch (Exception e) {
throw new TeaOrmException(e);
} finally {
pst.close();
rs.close();
}
}
2、执行更新操作,更新操作中有一种特殊情况,执行insert语句,并且主键是数据自动生成,那么要获取生成的主键,必须带上Statement.RETURN_GENERATED_KEYS参数创建Statement
public Object excuteUpdate(String sql, Object object, boolean isAutoIncrement) throws Exception {
SqlTransformResult sqlTransformResult = transformSql(sql, object);
Connection connection = ConnectionThreadVariable.getConnetion();
PreparedStatement pst = null;
Object result = null;
try {
if (isAutoIncrement) {
pst = connection.prepareStatement(sqlTransformResult.getSql(), Statement.RETURN_GENERATED_KEYS);
} else {
pst = connection.prepareStatement(sqlTransformResult.getSql());
}
logger.debug("执行:" + sqlTransformResult.getSql());
bindPrepareStatement(sqlTransformResult.getNeedBindFields(), pst, object);
if (isAutoIncrement) {
pst.executeUpdate();
ResultSet rs = pst.getGeneratedKeys();
rs.next();
result = rs.getObject(1);
rs.close();
} else {
result = pst.executeUpdate();
}
} catch (Exception e) {
throw new TeaOrmException(e);
} finally {
pst.close();
}
return result;
}
3、执行查询操作, 最终返回的是一个List,泛型是一个忽略大小写的Map
public List<CaseInsensitiveMap<String, Object>> excuteQuery(String sql, Object object) throws Exception {
List<CaseInsensitiveMap<String, Object>> result = new ArrayList<CaseInsensitiveMap<String, Object>>();
SqlTransformResult sqlTransformResult = transformSql(sql, object);
Connection connection = ConnectionThreadVariable.getConnetion();
PreparedStatement pst = null;
ResultSet rs = null;
PreparedStatement countPst = null;
ResultSet countRs = null;
try {
PageProcessor pageProcessor = PageProcessorManager.getPageProcessor();
// 查询总数
if (PageThreadVariable.isPaging()) {
countPst = connection.prepareStatement(pageProcessor.countSql(sqlTransformResult.getSql()));
bindPrepareStatement(sqlTransformResult.getNeedBindFields(), countPst, object);
countRs = countPst.executeQuery();
countRs.next();
PageThreadVariable.setTotalRecordCount(countRs.getLong(1));
logger.debug("执行:" + pageProcessor.countSql(sqlTransformResult.getSql()));
}
// 查询分页数据
if (PageThreadVariable.isPaging()) {
pst = connection.prepareStatement(pageProcessor.pageSql(sqlTransformResult.getSql()));
logger.debug("执行:" + pageProcessor.pageSql(sqlTransformResult.getSql()));
} else {
pst = connection.prepareStatement(sqlTransformResult.getSql());
logger.debug("执行:" + sqlTransformResult.getSql());
}
bindPrepareStatement(sqlTransformResult.getNeedBindFields(), pst, object);
rs = pst.executeQuery();
ResultSetMetaData resultSetMetaData = rs.getMetaData();
int columnCount = resultSetMetaData.getColumnCount();
if (rs != null) {
while (rs.next()) {
CaseInsensitiveMap<String, Object> map = new CaseInsensitiveMap<String, Object>();
for (int i = 1; i <= columnCount; i++) {
String columnName = resultSetMetaData.getColumnName(i);
map.put(columnName, rs.getObject(columnName));
}
result.add(map);
}
}
} catch (Exception e) {
throw new TeaOrmException(e);
} finally {
if (rs != null)
rs.close();
if (countRs != null)
countRs.close();
if (pst != null)
pst.close();
if (countPst != null)
countPst.close();
}
return result;
}
4、AbstractDataBind还有三个抽象方法,具体功能由之类去实现
bindPrepareStatement绑定预编译的参数、 fillfixedValue填充非预编译的值到sql,如用$$包裹的变量,fillPrimaryKeyToObject把通过sql生成的主键写到对象里 。
至此,SQL的预编译参数和非预编译参数可以绑定,并执行。分页的设计,将在下一篇中讲。
项目地址:https://git.oschina.net/lxkm/teaframework
博客:https://blog.youkuaiyun.com/dong_lxkm