BSTEK Development Framework2(BDF2) : 2.5. 使用JdbcDao

1.1. 准备

         在com.bstek.demo.dao包中添加一个继承com.bstek.bdf2.core.orm.jdbc.JdbcDao类的子类JdbcDaoTest,其代码如下:

JdbcDaoTest类代码
package com.bstek.demo.dao;
import com.bstek.bdf2.core.orm.jdbc.JdbcDao;
public class JdbcDaoTest extends JdbcDao {
 
} 

         创建一个视图文件JdbcDaoTest.view.xml。并在JdbcDaoTest.view.xml文件中添加一个name为dataTypeDemoUser的DataType,设置creationType属性为com.bstek.demo.model.DemoUser。接着在视图view节点下添加一个id为dataSetDemoUser的DataSet,并设置dataType属性为我们刚才添加的name为dataTypeDemoUser的DataType,选择DataType时,勾选Collection选项。然后,在视图view节点下添加一个id为gridDemoUser的DataGrid。最后,在JdbcDaoTest.java中添加一个DemoUserRowMapper类,其代码如下:

class  DemoUserRowMapper implements RowMapper<DemoUser>{
	public DemoUser mapRow(ResultSet rs, int rowNum) throws SQLException {
		DemoUser d=new DemoUser();
		d.setUsername(rs.getString("USERNAME_"));
		d.setMale(rs.getBoolean("MALE_"));
		d.setBirthday(rs.getDate("BIRTHDAY_"));
		d.setMobile(rs.getString("MOBILE_"));
		d.setAddress(rs.getString("ADDRESS_"));
		d.setEmail(rs.getString("EMAIL_"));
		return d;
	}
}

          在dorado-home文件夹下,找到context.xml,添加如下配置:

<bean id="jdbcDaoTest" class="com.bstek.demo.dao.JdbcDaoTest"></bean>

1.2. 使用JdbcDao实现增、删、改

         首先,在视图文件的view节点添加id为updateActionDemoUser的UpdateAction,将其dataResolver属性设为hibernateDaoTest#saveDemoUser,并将为其添加一个属性dataSet为dataSetDemoUser的UpdateItem子项。然后,在view节点添加一个ToolBar,并为其添加三个按钮ToolBarBotton,分别是添加按钮、删除按钮和保存按钮,其中,在添加按钮的onClick事件中添加如下代码:

var data=view.get("#dataSetDemoUser.data");
data.insert();

         在删除按钮的onClick事件中添加如下代码:

var entity=view.get("#dataSetDemoUser.data:#");
var updateActionDemoUser=view.get("#updateActionDemoUser");
if(entity){
	entity.remove();
}else{
	dorado.MessageBox.alert("必须选中一行记录!");
}

         在保存按钮的onClick事件中添加如下代码:

var updateActionDemoUser=view.get("#updateActionDemoUser");
updateActionDemoUser.execute();

         接着完成后台服务方法的编写,在HibernateDaoTest类中添加如下方法:

@DataResolver
public void saveDemoUsers(Collection<DemoUser> users){
	for (DemoUser user : users) {
    	SqlParameterSource paramSource =new BeanPropertySqlParameterSource(user);
		EntityState state = EntityUtils.getState(user);
		if (state.equals(EntityState.NEW)) {
			this.getNamedParameterJdbcTemplate().update("INSERT INTO Demo_USER 					(USERNAME_,MALE_,BIRTHDAY_,MOBILE_,ADDRESS_,EMAIL_)VALUES(:username,:male,:birthday,:mobile,:address,:email)", paramSource);
		} else if (state.equals(EntityState.MODIFIED)) {
				this.getNamedParameterJdbcTemplate().update("UPDATE Demo_USER SET MALE_=:male,BIRTHDAY_=:birthday,MOBILE_=:mobile,ADDRESS_=:address,EMAIL_=:email WHERE USERNAME_=:username", paramSource);
		} else if (state.equals(EntityState.DELETED)) {
				this.getNamedParameterJdbcTemplate().update("DELETE FROM Demo_USER WHERE USERNAME_=:username", paramSource);
		}
	}
}

         这样就完成了对数据的增删改了。

1.3. 使用JdbcDao实现各种查询

1.3.1. 无查询条件的查询

         将dataSetDemoUser的dataProvider属性设置为jdbcDaoTest#query10。并在 JdbcDaoTest类里添加如下方法:

@DataProvider
public Collection<DemoUser> query10(){
	String sql="SELECT D.USERNAME_,D.MALE_,D.BIRTHDAY_,D.MOBILE_,D.ADDRESS_,D.EMAIL_ FROM Demo_USER D";
	return this.getJdbcTemplate().query(sql, new DemoUserRowMapper());
}

1.3.2. 带Map参数的NamedParameterJdbcTemplate条件查询

         在 JdbcDaoTest.view.xml视图中,添加一个id为将textUsername的TextEditor和一个查询按钮,并在查询按钮的onClick事件中添加如下代码:

var username=view.get("#textUsername.value");
var dataSetDemoUser=view.get("#dataSetDemoUser");
if(username){
	dataSetDemoUser.set("parameter",{username:username}).flushAsync();
}

         dataSetDemoUser的dataProvider属性设置为jdbcDaoTest#query11。并在 JdbcDaoTest类里添加如下方法:

@DataProvider
public Collection<DomeUser> query11(String username){
	Map<String,Object> map =new HashMap<String,Object>();
	String sql="SELECT D.USERNAME_,D.MALE_,D.BIRTHDAY_,D.MOBILE_,D.ADDRESS_,D.EMAIL_ FROM DOME_USER D ";
	if(username!=null&&!"".equals(username)){
		map.put("username", "%"+username+"%");
		sql+="WHERE D.USERNAME_ LIKE :username";
	}
	return this.getNamedParameterJdbcTemplate().query(sql, map, new DomeUserRowMapper());
}

1.3.3. 无查询条件的分页查询

         将dataSetDemoUser的dataProvider属性设置为jdbcDaoTest#query12,并将dataSetDemoUser的pageSize设置为10,再添加一个分页工具DataPilot,并设置dataSet属性为dataSetDemoUser,接下来,在 JdbcDaoTest类里添加如下方法:

@DataProvider
public Collection<DemoUser> query12(){
	String sql="SELECT D.USERNAME_,D.MALE_,D.BIRTHDAY_,D.MOBILE_,D.ADDRESS_,D.EMAIL_ FROM Demo_USER D";
	return this.getJdbcTemplate().query(sql, new DemoUserRowMapper());
}

1.3.4. 带Map参数的条件分页查询

         dataSetDemoUser的dataProvider属性设置为jdbcDaoTest#query13。接下来,在 JdbcDaoTest类里添加如下方法:

@DataProvider
public void query13(Page<DemoUser> page,String username){
	Map<String,Object> map =new HashMap<String,Object>();
	String sql="SELECT  D.USERNAME_,D.MALE_,D.BIRTHDAY_,D.MOBILE_,D.ADDRESS_,D.EMAIL_ FROM DOME_USER D ";
	if(username!=null&&!"".equals(username)){
		map.put("username", username);
		sql+=" WHERE D.USERNAME_=:username";
	}
	this.pagingQuery(page, sql, new DomeUserRowMapper(),map);
}

         代码说明:JdbcDao对象的pagingQuery(Page<?> page,String sql,RowMapper<?> mapper,Map<String,Object> parameters)方法,可以实现带参数的查询,参数放到Map集合当中,可以放入多查询参数。

1.3.5. 带数组参数的条件分页查询

         将dataSetDemoUser的dataProvider属性设置为jdbcDaoTest#query14。并在 JdbcDaoTest类里添加如下方法:

@DataProvider
public void query14(Page<DemoUser> page,String username){
	String sql="SELECT  D.USERNAME_,D.MALE_,D.BIRTHDAY_,D.MOBILE_,D.ADDRESS_,D.EMAIL_ FROM DOME_USER D ";
	if(username!=null&&!"".equals(username)){
		sql+=" WHERE D.USERNAME_=?";
		this.pagingQuery(page, sql,new Object[]{username},new DomeUserRowMapper());
	}else{
		this.pagingQuery(page, sql,new DomeUserRowMapper());
	}
}

         代码说明:此段代码的功能和上一节代码的功能是一样的,只是这里传递查询参数是通过Object数组来实现。但是这种方式对查询参数的顺序有严格的要求,不推荐使用。

1.3.6. 结合DataGrid的过滤工具栏实现分页查询

         将dataSetDemoUser的dataProvider属性设置为jdbcDaoTest#query15,并将gridDemoUser的filterMode和showFilterBar属性分别设置为serverSide和true。接着在 JdbcDaoTest类里添加如下方法:

@DataProvider
public void query15(Page<DemoUser> page,Criteria criteria){
	String sql="SELECT  D.USERNAME_,D.MALE_,D.BIRTHDAY_,D.MOBILE_,D.ADDRESS_,D.EMAIL_ FROM Demo_USER D ";
	ParseResult result=this.parseCriteria(criteria,false,"D");
	if(result!=null){
		StringBuffer sb=result.getAssemblySql();
		Map<String,Object> valueMap=result.getValueMap();
		sql+=" WHERE "+sb.toString();
		this.pagingQuery(page,sql,valueMap.values().toArray(),new DemoUserRowMapper());
	}else{
		this.pagingQuery(page,sql,new DemoUserRowMapper());			
	}
}
	
@Override
protected String buildFieldName(String name) {
	if(name==null)return name;
	StringBuffer sb=new StringBuffer();
	for(char ch:name.toCharArray()){
		boolean upper=Character.isUpperCase(ch);
		sb.append(Character.toUpperCase(ch));
		if(upper){
			sb.append("_");
		}
	}
	sb.append("_");
	return sb.toString();
}

         代码说明:parseCriteria方法的作用是将Criteria对象的相应成分映射到ParseResult的assemblySql和valueMap属性中,以方便我们使用JdbcDao的相关API,其中assemblySql属性是查询语句的where子句部分,且不包括where关键字。而valueMap则是对应的查询参数buildFieldName方法是对父类AbstractDao中的buildFieldName模板方法的重写,此模板方法是parseCriteria方法内部在拼凑查询语句的where子句时调用的,作用是根据实体类的属性名生成对应的数据库字段名,默认实现是生成的数据库字段名和属性名相同,通过在子类对其重写,可以实现自定义的从实体属性名到数据库字段名的映射。