`
tan4836128
  • 浏览: 27272 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

钢炮级 持久层 —— 中篇

阅读更多
Title:VO的封装

    我在上一篇博客(http://tan4836128.iteye.com/blog/1152147)介绍了一个小型的持久层处理类,一个可以兼容各类数据操作的方法。其中最主要的方法,就是构建各类数据操作的SQL,和解析查询结果并返回的数据集合。本文主要针对这个解析后返回的数据集合,做实体类与之耦合的需求进行讨论。

    为了实现自动化匹配,我设置几个对VO类编码的基本要求:
1. 数据库表理论上对应一个实体类VO,表中每一个字段都能在VO中找到对应变量,附带表名、字段名、主键名等各返回名称的方法。

2. 实体类VO应针对表中每一个字段,都提供一个返回字段名称的方法,这个用于自动匹配查询返回的数据集合(因为,在返回的数据集中对表字段名做了记录)。

3. 为了方便阅读,VO类中方法、变量应有足够的注释

    为了不再重复对VO进行编码,我设计了一个生成实体类代码的小程序,这个程序辅助我设计实体类VO,它本身并不是持久层的一部分。但是由它(按照一定规范和要求)生成的实体类VO是持久层的重要数据传输对象,由这些VO搭建起跟执行查询后返回的数据集的耦合关系。

    首先看一个生成出来的VO类,Role.java
package com.accout.role.pojo;

/***
 * 角色
 * @author db2admin
 * 2010-12-23
 */
public class Role implements java.io.Serializable {

	/**角色ID*/
	private int RoleId;
	/**角色名称*/
	private String RoleName;
	/**角色等级:1为普通员工、2为经理用户、3为系统管理员*/
	private String RoleLevel;
	/**角色资源,当前角色对应的浏览权限*/
	private String RoleResource;
	/***/
	private String Remark;

	/***
	 * 字段代理方法:role_id
	 * 角色ID
	 * @return
	 */
	public static String RoleId(){
		return "role_id";
	}
	/***
	 * 字段代理方法:role_name
	 * 角色名称
	 * @return
	 */
	public static String RoleName(){
		return "role_name";
	}
	/***
	 * 字段代理方法:role_level
	 * 角色等级:1为普通员工、2为经理用户、3为系统管理员
	 * @return
	 */
	public static String RoleLevel(){
		return "role_level";
	}
	/***
	 * 字段代理方法:role_resource
	 * 角色资源,当前角色对应的浏览权限
	 * @return
	 */
	public static String RoleResource(){
		return "role_resource";
	}
	/***
	 * 字段代理方法:remark
	 * 
	 * @return
	 */
	public static String Remark(){
		return "remark";
	}
	/***
	 * 实体类对应表:role
	 * @return
	 */
	public static String getTableName(){
		return "role";
	}
	/***
	 * 表主键:role_id
	 * @return
	 */
	public String getPrimaryKey(){
		return "role_id";
	}/***
	 * 设置主键值:RoleId
	 * @return
	 */
	public void setPrimaryKeyValue(int value){
		this.RoleId = value;
	}/***
	 * 获取主键值:RoleId
	 * @return
	 */
	public int getPrimaryKeyValue(){
		return this.RoleId;
	}
}

该类包含字段对应的变量、表名和表字段名称以及主键名称的返回方法,这些都是通过读取数据库自动生成的,包括数据类型、字段注释等,再看表结构,如下:

注:没有对get/set方法做自动生成,Eclipse有这功能,so...

    好,现在VO类有了,再看看怎样与查询得到的数据集合自动装配,先看代码:
	public static void main(String[] args) {
		PublicDao dao = new PublicDao();
		Map<Object, String> mk = new HashMap<Object, String>();
		Map<Object, Object> mv = new HashMap<Object, Object>();
		//设置要查询的列
		mk.put(1, Role.RoleId());
		mk.put(2, Role.RoleLevel());
		mk.put(3, Role.RoleName());
		mk.put(4, Role.RoleResource());
		mk.put(5, Role.Remark());
		/**单表查询测试*/
		String sql = dao.createSql(PublicDao.SELECT, Role.getTableName(), mk, mv, "");
		System.out.println(sql);
		List list = dao.executeSql(PublicDao.SELECT, sql);
	}

得到SQL:
select role_id,role_level,role_name,role_resource,remark from role 

我们先到数据库里查询一下看看情况:

//执行查询之后,list中就有3条数据了,接下来遍历list,取出数据
List list = dao.executeSql(PublicDao.SELECT, sql);
//用于封装并返回数据的集合对象
List<Role> list_t = new ArrayList<Role>();
//取出列名Map
Map mk_n = (Map) list.get(0);
//取出每一行数据
List list_mv = (List) list.get(1);
//封装的对象
Role role = null;
for(int i=0;i<list_mv.size();i++){
	Map mv_n = (Map) list_mv.get(i);
	//这里每循环一次代表每一行数据,即一个对象
	role = new Role();
	for(int j=1;j<=mk_n.size();j++){
		Object temp = mv_n.get(mk_n.get(j));
		if(Role.RoleId().equals(mk_n.get(j))){
			role.setRoleId(temp==null?null:(Integer)temp);
		}
		if(Role.RoleName().equals(mk_n.get(j))){
			role.setRoleName(temp==null?"":temp.toString());
		}
		if(Role.RoleResource().equals(mk_n.get(j))){
			role.setRoleResource(temp==null?"":temp.toString());
		}
		if(Role.RoleLevel().equals(mk_n.get(j))){
			role.setRoleLevel(temp==null?"":temp.toString());
		}
	}
	list_t.add(role);
}

有图才有真相:


    到此,就可以返回这个List<Role>对象了,传递到表示层该怎么读取就怎么读,数据从数据库,经持久层封装,再到VO封装出来,这个流程其实很简单,有了固定的持久不变的持久层API,有了可以自动生成VO的小程序,一下子模型层,持久层代码都不用关心,你只需要分析需求、设计好表结构,其他的就剩下表示层的业务逻辑了。

    另外,VO类中还有getPrimaryKey,getPrimaryKeyValue,setPrimaryKeyValue等方法,这些方法用于数据的删除和修改操作,用起来也很简单,比如删除:
/***
 * 如果使用Struts 1.x,这里的keyId可以直接通过request.getParameter()方法获取,不需要传递参数
 * 当然,方法就应该改为
 * public ActionForward deleteRole(ActionMapping mapping, ActionForm form, 
 * 		HttpServletRequest request, HttpServletResponse response){。。。}
 * @param keyId
 */
public void deleteRole(String keyId){
	Map<Object,String> mk = new HashMap<Object,String>();
	Map<Object,Object> mv = new HashMap<Object,Object>();
	//设置主键、主键值
	mk.put(1, Role.getPrimaryKey());
	//request.getParameter("keyId")
	mv.put(mk.get(1), "="+keyId);

	PublicDao dao = new PublicDao();
	String sql = dao.createSql(PublicDao.DELETE, Role.getTableName(), mk, mv, "");
	dao.executeSql(PublicDao.DELETE, sql);
}


新增或修改数据,如下:
/***
 * 这里的type、Role对象封装的值,可以直接通过request.getParameter()方法获取,不需要传递这两个参数
 * 当然,方法就应该改为
 * public ActionForward addAndUpdateRole(ActionMapping mapping, ActionForm form, 
 * 		HttpServletRequest request, HttpServletResponse response){。。。}
 * @param type
 * @param role
 */
public void addAndUpdateRole(String type, Role role){
	Map<Object,String> mk = new HashMap<Object,String>();
	Map<Object,Object> mv = new HashMap<Object,Object>();

	mk.put(1, Role.RoleName());
	mk.put(2, Role.RoleResource());
	mk.put(3, Role.RoleLevel());

	mv.put(mk.get(1), role.getRoleName());
	//request.getParameter("RoleName")
	mv.put(mk.get(2), role.getRoleResource());
	//request.getParameter("RoleResource")
	//request.getParameter("RoleLevel")
	mv.put(mk.get(3), role.getRoleLevel());

	PublicDao dao = new PublicDao();
	String sql = "";
	//request.getParameter("type")
	if("Add".equals(type)){

		sql = dao.createSql(PublicDao.ADD, Role.getTableName(), mk, mv, "");
		dao.executeSql(PublicDao.ADD, sql);

	} else if("Update".equals(type)) {

		//设置条件
		String condition = Role.getPrimaryKey()+"="+role.getPrimaryKeyValue();

		sql = dao.createSql(PublicDao.UPDATE, Role.getTableName(), mk, mv, condition);
		dao.executeSql(PublicDao.UPDATE, sql);
	}
}


    总结,实体类的自动装配跟VO类的映射就需要有这样高耦合度,为满足数据传输,这是必须的。VO类中设置getTableName、getPrimaryKey等方法能够参与业务逻辑,给编码带来的好处还是有的,起码在需要获取主键值得时候,你不再需要关心某张表的主键到底是谁,而直接拿来就用。当然也有问题,这些问题都可以通过建单扩展既可以解决,比如:

1. 多主键的处理,返回数组
2. (多)外键的处理,返回数组
3. VO中加入表索引信息

    同前一篇一样,这样的思路也只是基于一些简单的小型项目,应用到大项目中,需要不停的扩展VO的功能,比如加入索引,在业务逻辑层面,你可以通过指定索引,直接优化一些大型的、复杂的SQL查询,提升效率,当然,这就要求前一篇中PublicDao类的createSql方法更高了,实现也更复杂了。

    最后,附上我自己写的一个VO类的代码生成类。
    文中有任何大小问题,请各位不吝赐教,我会在日后继续改进。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics