欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

钢炮级 持久层 —— 中篇 博客分类: 持久层 javaVO实体类代码自动生成 

程序员文章站 2024-02-12 15:47:10
...
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;
	}
}

该类包含字段对应的变量、表名和表字段名称以及主键名称的返回方法,这些都是通过读取数据库自动生成的,包括数据类型、字段注释等,再看表结构,如下:
钢炮级 持久层 —— 中篇
            
    
    博客分类: 持久层 javaVO实体类代码自动生成 
注:没有对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 

我们先到数据库里查询一下看看情况:
钢炮级 持久层 —— 中篇
            
    
    博客分类: 持久层 javaVO实体类代码自动生成 
//执行查询之后,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);
}

有图才有真相:
钢炮级 持久层 —— 中篇
            
    
    博客分类: 持久层 javaVO实体类代码自动生成 

    到此,就可以返回这个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类的代码生成类。
    文中有任何大小问题,请各位不吝赐教,我会在日后继续改进。