Dorado 5 : 9.1.DBStatement (RF1)

DBStatement是Dorado提供的服务器端的方便使用SQL命令的工具类,通过此工具类,开发人员可以很简单并且高效的完成对数据的增删查改。
在DBStatement中可以使用在SqlDataset中提到的Dorado的参数,可以通过DBStatement的Parameters()来操作DBStatement中的参数。此外,使用DBStatement进行的数据操作可以自动加入到Dorado当前线程的事务中。
DBStatement有两种使用方式,一种是直接设置SQL,然后执行数据操作;另外一种是定义数据操作的类型,然后设置相关数据,由DBStatement自动生成数据操作的SQL,然后执行数据操作。无论那种方式,使用完毕之后都必须显式的调用close()方法关闭数据库连接。
使用DBStatement工具类之前,应该通过DBStatement的setDataSource(String dataSource)或者在创建DBStatement对象时设置DBStatement使用的数据源的名称,如果不设置DBStatement将使用默认的数据源,也就是在setting.xml文件中common.defaultDataSoruce属性指定的DataSource。

SQL调用

DBStatement的第一种使用方法,可以通过setSql(String sql)来设置数据操作的SQL,函数申明如下:

public void setSql(java.lang.String sql)

SQL语句可以为查询,更新,删除,存储过程调用等等类型的SQL。

查询

实现数据查询,通过调用query()方法或者queryForList()方法来完成查询并取得返回结果,query()方法用于返回单条数据的的查询,queryForList()用于返回多条记录的查询,函数申明如下:
Query();

public VariantSet query() throws java.lang.Exception
执行一个查询命令并返回第一条记录的值.如果本次查询没有查到任何记录将返回null.

queryForList();

public java.util.List queryForList() throws java.lang.Exception
执行一个查询命令并将结果集以java.util.List的形式返回.其中List中的元素是 com.bstek.dorado.utils.variant.VariantSet对象.
如果本次查询没有查到任何记录将返回一个空的List.

以上两个函数中dorado默认都使用VariantSet对象封装,VariantSet对象的说明请参考常用dorado工具类
范例:根据客户端传入的用户编号查询对应用户的工资

public void getSalary(ParameterSet param, ParameterSet outParam){
DBStatement ds = new DBStatement();
ds.setDataSource("doradosample");
ds.setSql("select employee_name,salary from employee where employee_id='ANLIN'");
try {
VariantSet vs = ds.query();
double salary = vs.getDouble("salary");
} catch (Exception e) {
e.printStackTrace();
} finally{
ds.close();
}
}

根据客户端传入的数值,返回工资大于此数值的用户姓名的集合:

public void getEmployees(ParameterSet param, ParameterSet outParam){
DBStatement ds = new DBStatement();
ds.setDataSource("doradosample");
ds.setSql("select * from employee where salary>:salary");
double salary = param.getDouble("salary");
ds.parameters().setDouble("salary", salary);
try {
StringBuffer sb = new StringBuffer();
List<VariantSet> list = ds.queryForList();
boolean first = true;
for(VariantSet vs:list){
if(first){
sb.append(vs.getString("employee_name"));
first = false;
} else {
sb.append(","+vs.getString("employee_name"));
}
}

outParam.setString("employees", sb.toString());
} catch (Exception e) {
e.printStackTrace();
} finally{
ds.close();
}
}

使用DBStatement进行查询返回的数据类型都为VariantSet,VariantSet是Dorado提供的可以支持多种数据类型的集合类型,其功能类似一个增强类型的Map。

增删改或其他特殊调用

如果是数据的插入、删除、或者更新,调用execute()方法,该方法返回SQL命令执行涉及到的数据条数。
execute方法说明:

public int execute() throws java.lang.Exception
如果此方法执行的SQL是INSERT, UPDATE, 或 DELETE, 将返回该命令执行时涉及到的记录数; 否则将返回0.请参考java.sql.Statement对象的executeUpdate()方法.

例如:为指定的员工增加工资

public void raiseSalary(ParameterSet param, ParameterSet outParam){
DBStatement ds = new DBStatement();
ds.setDataSource("doradosample");
ds.setSql("update employee set salary=salary+:raise where employee_id=:id");
double raise = param.getDouble("raise");
String id = param.getString("employee_id");
ds.parameters().setDouble("salary", raise);
ds.parameters().setString("id", id);
try {
ds.execute();
outParam.setString("result", "success");
} catch (Exception e) {
e.printStackTrace();
} finally{
ds.close();
}
outParam.setString("result", "failure");
}

高级功能

DBStatement的第二种用法,DBStatement除了setSql(String sql)外,DBStatement还提供了另外两个同名的方法:
setSql(String type,String table);
setSql(String type,String table,String keyFields);
其中type在DBStatement中有定义,可以为:
DBStatement.DELETE、DBStatement.INSERT、DBStatement.UPDATE或DBStatement.SELECT。
下面分别说明每一种类型的含义
DBStatement.SELECT:查询类型的SQL命令。最终将生成类似 SELECT * FROM [table] 的SQL命令。对于此种类型的SQL命令,keyFields参数是没有意义的,建议通过setSql(String type, String table) 方法来定义。
代码范例:

statement.setSql(DBStatement.SELECT, "employee");
statement.query();

等同于SQL: select * from employee

statement.setSql(DBStatement.SELECT, "dept");
statement.query();

等同于SQL: select * from dept
DBStatement.DELETE:删除类型的SQL命令。最终将生成类似 DELETE FROM [table] WHERE [field1]=:field1 AND [field2]=:field2 的SQL命令。对于此种类型的SQL命令,如果指定了keyFields参数,那么DBStatement将根据keyFields参数来生成SQL命令的WHERE子片断。如果没有指定keyFields参数,那么DBStatement将根据parameters中的参数来生成SQL命令的WHERE子片断。每一个parameter将最终成为WHERE子片断中的一个条件。
范例代码:

statement.setSql(DBStatement.DELETE, "dept","dept_id");
statement.parameters().setValue("dept_id", "D11");
statement.execute();

等同于:

PreparedStatement pst = conn.preparedStatement("delect from dept where dept_id=?");
pst.setString(1,"D11");
pst.execute();

可以看到其中的差别,DBStatement支持参数名赋值。使得程序代码更为容易理解。
DBStatement.UPDATE:更新类型的SQL命令。最终将生成类似 UPDATE [table] SET [field1]=:field1, [field2]=:field2 WHERE [field3]=:field3 的SQL命令。对于此种类型的SQL命令keyFields是必须指定的参数.DBStatement将根据parameters中的参数配合keyFields来生成SQL命令。利用keyFields用来生成SQL命令的WHERE子片断, 然后利用在parameters中的声明但没有在keyFields中声明的部分参数生成SQL命令的SET子片断。
范例代码:

statement.setSql(DBStatement.UPDATE, "dept","dept_id");
statement.parameters().setValue("dept_id", "D11");
statement.parameters().setValue("dept_name", "北京软件研发部");
statement.execute();

等同于:

PreparedStatement pst = conn.preparedStatement("update dept set dept_name=? where dept_id=?");
pst.setString(1,"北京软件研发部");
pst.setString(2,"D11");
pst.execute();

INSERT:插入类型的SQL命令。最终将生成类似 INSERT INTO [table] SET [field1]=:field1,[field2]=:field2 的SQL命令。对于此种类型的SQL命令。keyFields参数是没有意义的,建议通过setSql(String type, String table) 方法来定义。最终DBStatement将根据parameters中的参数来生成SQL命令的SET子片断。
范例代码:

statement.setSql(DBStatement.INSERT, "dept");
statement.parameters().setValue("dept_id", "D15");
statement.parameters().setValue("dept_name", "北京技术支持部");
statement.parameters().setValue("branch_id", "D1");
statement.execute();

等同于:

PreparedStatement pst = conn.preparedStatement("insert into dept (dept_id, dept_name, branch_id) values(?,?,?)");
pst.setString(1,"D15");
pst.setString(2,"北京技术支持部");
pst.setString(3,"D1");
pst.execute();

关于DBStatement的事务会在下一节"事务管理"中详细论述。