`
z2009zxiaolong
  • 浏览: 77123 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论
阅读更多

本文介绍的是在不使用持久层框架的情况下,用Java反射写的BaseDao,简化Dao层的操作,让Dao的实现层每个方法体只有一行。所有的Dao的实现类继承BaseDao。 下面具体讲如何使用BaseDao

  1. BaseDao代码如下:
    package dao;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import utils.DbHelper;
    
    public class BaseDao {
    	private Connection conn = null;
    	private PreparedStatement ps = null;
    	private ResultSet rs = null;
    
    	/**
    	 * 查询符合条件的记录数
    	 * 
    	 * @param sql
    	 *            要执行的sql语句
    	 * @param args
    	 *            给sql语句中的?赋值的参数列表
    	 * @return 符合条件的记录数
    	 */
    	public long getCount(String sql, Object... args) {
    		conn = DbHelper.getConn();
    		try {
    			ps = conn.prepareStatement(sql);
    			for (int i = 0; i < args.length; i++) {
    				ps.setObject(i + 1, args[i]);
    			}
    			rs = ps.executeQuery();
    			if (rs.next()) {
    				return rs.getLong(1);
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			DbHelper.closeConn(conn, ps, rs);
    		}
    		return 0L;
    	}
    
    	/**
    	 * 查询实体对象的,并封装到一个集合
    	 * 
    	 * @param <T>
    	 *            要查询的对象的集合
    	 * @param sql
    	 *            要执行的sql语句
    	 * @param clazz
    	 *            要查询的对象的类型
    	 * @param args
    	 *            给sql语句中的?赋值的参数列表
    	 * @return 要查询的类的集合,无结果时返回null
    	 */
    	public <T> List<T> executeQuery(String sql, Class<T> clazz, Object... args) {
    		conn = DbHelper.getConn();
    		List list = new ArrayList();
    		try {
    			ps = conn.prepareStatement(sql);
    			for (int i = 0; i < args.length; i++) {
    				ps.setObject(i + 1, args[i]);
    			}
    			rs = ps.executeQuery();
    			Field[] fs = clazz.getDeclaredFields();
    			String[] colNames = new String[fs.length];
    			String[] rTypes = new String[fs.length];
    			Method[] methods = clazz.getMethods();
    			while (rs.next()) {
    				for (int i = 0; i < fs.length; i++) {
    					Field f = fs[i];
    					String colName = f.getName().substring(0, 1).toUpperCase()
    							+ f.getName().substring(1);
    					colNames[i] = colName;
    					String rType = f.getType().getSimpleName();
    					rTypes[i] = rType;
    				}
    
    				Object object = (T) clazz.newInstance();
    				for (int i = 0; i < colNames.length; i++) {
    					String colName = colNames[i];
    					String methodName = "set" + colName;
    					// 查找并调用对应的setter方法赋
    					for (Method m : methods) {
    						if (methodName.equals((m.getName()))) {
    							// 如果抛了参数不匹配异常,检查JavaBean中该属性类型,并添加else分支进行处理
    							if ("int".equals(rTypes[i])
    									|| "Integer".equals(rTypes[i])) {
    								m.invoke(object, rs.getInt(colName));
    							} else if ("Date".equals(rTypes[i])) {
    								m.invoke(object, rs.getDate(colName));
    							} else if ("Timestamp".equals(rTypes[i])) {
    								m.invoke(object, rs.getTimestamp(colName));
    							} else {
    								m.invoke(object, rs.getObject(colName));
    							}
    							break;
    						}
    					}
    				}
    				list.add(object);
    			}
    			return list;
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			DbHelper.closeConn(conn, ps, rs);
    		}
    		return null;
    	}
    
    	/**
    	 * 以对象的形式保存或更新一个实体
    	 * 
    	 * @param sql
    	 *            要执行的sql语句
    	 * @param object
    	 *            要保存或更新的实体对象
    	 * @param args
    	 *            不需要赋值的列标组成的数组,例如sql语句
    	 *            "insert into tbl_user values(seq_user.nextval,?,?,?)"应为1
    	 * @return 操作结果,1 成功,0 失败
    	 */
    	public int saveEntity(String sql, Object object, int... args) {
    		conn = DbHelper.getConn();
    		try {
    			ps = conn.prepareStatement(sql);
    			Class c = object.getClass();
    			Field[] fields = object.getClass().getDeclaredFields();
    			int temp = 1;// 正赋值的?的下标,最大下标为args的长度
    			int colIndex = 1;// SQL语句中的当前字段下标
    			int t = 0;// args数组的下标
    			for (int j = 0; j < fields.length; j++) {
    				Field field = fields[j];// 得到某个声明属性
    				String methodName = "get"
    						+ field.getName().substring(0, 1).toUpperCase()
    						+ field.getName().substring(1);
    				Method method = c.getMethod(methodName);// 得到了当前类中的一个method
    				String rType = field.getType().getSimpleName().toString();
    				if (t < args.length && colIndex == args[t]) {
    					t++;
    				} else if ("int".equals(rType) || "INTEGER".equals(rType)) {
    					ps.setInt(temp++, (Integer) method.invoke(object));
    				} else {
    					ps.setObject(temp++, method.invoke(object));
    				}
    				colIndex++;// 更新索引下标
    			}
    			return ps.executeUpdate();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			DbHelper.closeConn(conn, ps, null);
    		}
    		return 0;
    	}
    
    	/**
    	 * 执行可变参数的SQL语句,进行保存、删除或更新操作
    	 * 
    	 * @param sql
    	 *            要执行的sql语句,?的赋值顺序必须与args数组的顺序相同
    	 * @param args
    	 *            要赋值的参数列表
    	 * @return 操作结果,正数 成功,0 失败
    	 */
    	public int saveOrUpdate(String sql, Object... args) {
    		conn = DbHelper.getConn();
    		try {
    			ps = conn.prepareStatement(sql);
    			for (int j = 0; j < args.length; j++) {
    				ps.setObject(j + 1, args[j]);
    			}
    			return ps.executeUpdate();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			DbHelper.closeConn(conn, ps, null);
    		}
    		return 0;
    	}
    }
    
    
    
    
     
  2. 连接数据库的DbHelper工具类
    package utils;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    
    /**
     * 数据库工具类
     * 
     * @author Jzl
     * 
     */
    public class DbHelper {
    
    	/**
    	 * 获得一个数据库连接
    	 * 
    	 * @return
    	 */
    	public static Connection getConn() {
    		Connection conn = null;
    		try {
    			Class.forName("oracle.jdbc.driver.OracleDriver");
    			String url = "jdbc:oracle:thin:@localhost:1521:orcl";
    			conn = DriverManager.getConnection(url, "scott", "tiger");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return conn;
    	}
    
    	/**
    	 * 关闭数据库连接资源
    	 * 
    	 * @param conn
    	 * @param ps
    	 * @param rs
    	 */
    	public static void closeConn(Connection conn, Statement ps, ResultSet rs) {
    		try {
    			if (rs != null) {
    				rs.close();
    				rs = null;
    			}
    			if (ps != null) {
    				ps.close();
    				ps = null;
    			}
    			if (conn != null) {
    				conn.close();
    				conn = null;
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    
    
    
    
     
  3. 接下来就可以测试BaseDao了。用于测试的User实体类:
    package entity;
    
    import java.sql.Date;
    
    /**
     * 用于测试的JavaBean,符合JavaBea命名规范
     * @author Jzl
     *
     */
    public class User {
    	private int userId;
    	private String userName;
    	private String userPass;
    	private Date lastDate;
    
    	/**
    	 * 无参构造函数,用于反射new一个实例(必须有)
    	 */
    	public User() {
    	}
    
    	public User(String userName, String userPass, Date lastDate) {
    		super();
    		this.userName = userName;
    		this.userPass = userPass;
    		this.lastDate = lastDate;
    	}
    
    	public int getUserId() {
    		return userId;
    	}
    
    	public void setUserId(int userId) {
    		this.userId = userId;
    	}
    
    	public String getUserName() {
    		return userName;
    	}
    
    	public void setUserName(String userName) {
    		this.userName = userName;
    	}
    
    	public String getUserPass() {
    		return userPass;
    	}
    
    	public void setUserPass(String userPass) {
    		this.userPass = userPass;
    	}
    
    	public Date getLastDate() {
    		return lastDate;
    	}
    
    	public void setLastDate(Date lastDate) {
    		this.lastDate = lastDate;
    	}
    
    }
    
    
    
    
     
  4. 用于测试的UserDao:
    package dao;
    
    import java.util.List;
    
    import entity.User;
    
    /**
     * 用于测试的UserDao
     * @author Jzl
     *
     */
    public class UserDao extends BaseDao {
    	public int addUser1(User user) {
    		return super.saveEntity(
    				"insert into tbl_user values(seq_user.nextval,?,?,?)", user, 1);
    	}
    
    	public int addUser2(User user) {
    		return super.saveOrUpdate(
    				"insert into tbl_user values(seq_user.nextval,?,?,?)",
    				user.getUserName(), user.getUserPass(), user.getLastDate());
    	}
    
    	public int deleteUserById(int userId) {
    		return super
    				.saveOrUpdate("delete from tbl_user where userId=?", userId);
    	}
    
    	public int modUserById(int userId, User user) {
    		return super
    				.saveOrUpdate(
    						"update tbl_user set userName=?,userPass=?,lastDate=? where userId=?",
    						user.getUserName(), user.getUserPass(),
    						user.getLastDate(), userId);
    	}
    
    	public User getUser(int userId) {
    		return super.executeQuery("select * from tbl_user where userId=?",
    				User.class, userId).get(0);
    	}
    
    	public List<User> getUserList() {
    		return super.executeQuery("select * from tbl_user", User.class);
    	}
    	
    	public long getUserCount(){
    		return super.getCount("select count(*) from tbl_user");
    	}
    }
    
    
    
    
     
  5. 用于测试UserDao的测试类:
    package test;
    
    import java.sql.Date;
    import java.util.List;
    
    import org.junit.Test;
    
    import dao.UserDao;
    import entity.User;
    
    public class UserDaoTest {
    	private UserDao userDao = new UserDao();
    
    	@Test
    	public void testUserDao() {
    		testAdd1();
    		testAdd2();
    		testDeleteById();
    		testModById();
    		System.out.println(testGetById().getUserName());
    		List<User> users = testGetList();
    		for (User user : users) {
    			System.out.println(user.getUserId() + "==" + user.getUserName());
    		}
    		System.out.println(testGetCount());
    	}
    
    	public int testAdd1() {
    		User user = new User("zs", "zs", new Date(System.currentTimeMillis()));
    		return userDao.addUser1(user);
    	}
    
    	public int testAdd2() {
    		User user = new User("zs", "zs", new Date(System.currentTimeMillis()));
    		return userDao.addUser2(user);
    	}
    
    	public int testDeleteById() {
    		return userDao.deleteUserById(104);
    	}
    
    	public User testGetById() {
    		return userDao.getUser(104);
    	}
    
    	public int testModById() {
    		User user = new User("ls", "ls", new Date(System.currentTimeMillis()));
    		return userDao.modUserById(104, user);
    	}
    
    	public List<User> testGetList() {
    		return userDao.getUserList();
    	}
    
    	public long testGetCount() {
    		return userDao.getUserCount();
    	}
    }
    
    
    
    
     
  6. 创建用于测试的数据库表:

这里用Oracle数据库作测试,建表语句如下,

--创建测试表
create table tbl_user
(
  userId   number(8) primary key not null,
  userName varchar2(20),
  userPass varchar2(20),
  lastDate Date
);

create sequence seq_user;
 

 


分享到:
评论
2 楼 z2009zxiaolong 2012-12-17  
liuwei0376 写道
不错,如果没有用ORM框架,而直接用jdbc操作数据库,此方法很灵巧,值得推广啊。

谢谢你的关注,认真看的人不多。
1 楼 liuwei0376 2012-11-23  
不错,如果没有用ORM框架,而直接用jdbc操作数据库,此方法很灵巧,值得推广啊。

相关推荐

    Java面向对象程序设计-分层(分层开发的优缺点).pptx

    Java面向对象程序设计-分层开发的优缺点 Java面向对象程序设计中,分层开发是一种常用的设计方法,指的是将整个系统分成多个层次,每个层次负责不同的功能。这种设计方法可以带来很多优点,但同时也存在一些缺点。 ...

    Java入门级项目云日记(3.29G)

    02_002_云R记_项目开发流程.mp4 03_003_云R记_项目演示.mp4 04_004_云R记_需求分析.mp4 05_005_云R记_数据库设计.mp4 06_006_云R记_环境搭建.mp4 07_007_云R记_分层思想.mp4 08_008_云R记_获取数据库连接.mp4 09_009...

    Java控制台项目V.编程资料

    本项目旨在使用Java控制台开发一个简单的小型银行管理系统。该系统包括两个主要功能部分:管理员功能和顾客功能。通过Java控制台应用程序实现这些功能,不仅能够帮助理解基本的Java编程概念,还能够学习如何使用...

    Java控制台项目V2.0.docx

    - 使用MyEclipse 2014集成开发环境,这是一个集成了开发工具、版本控制、项目管理等功能的IDE,特别适合Java和Web项目的开发。 - JDK 7.0是Java Development Kit的第7个主要版本,提供了新的语法特性如try-with-...

    java javascript

    在Java Web开发中,通常采用分层架构来组织应用程序,如描述中所示,主要分为四层:Action层、Service层、DAO层以及Domain层。这种结构有助于提高代码的可维护性和可扩展性。 1. **Action层**: Action层是业务...

    Java控制台项目V2.01

    Java控制台项目V2.01是一个基于Java编程语言的小型银行管理系统的实现,它运行在MyEclipse2014开发环境中,依赖于JDK7.0和MySQL数据库。这个系统分为两个主要角色:管理员和顾客,每个角色都有特定的功能。 对于...

    车辆管理信息系统Java课程设计.docx

    车辆管理信息系统是一个基于Java语言的课程设计项目,旨在模拟日常...这个Java课程设计项目不仅锻炼了学生对Java编程语言的理解,还涉及到了数据库设计、用户界面交互和信息管理等多个方面,是一个全面的软件开发实践。

    SSH框架开发起步的最好例子.doc

    整个流程体现了SSH框架的分层设计思想,每一层都有明确的职责,通过松耦合的方式紧密协作,共同实现了复杂功能的开发与维护。对于初学者而言,深入理解并实践SSH框架的开发流程,将有助于掌握企业级应用的开发技巧,...

    springmvc+spring4+hibernate5

    Spring MVC、Spring 4 和 Hibernate 5 是三个在Java Web开发中非常重要的开源框架,它们分别负责不同的职责:Spring MVC 用于构建Web应用程序的模型-视图-控制器(MVC)架构,Spring 4 提供了全面的服务层支持,包括...

    通讯录系统文档(初期设计)

    - 开发语言: JAVA - 开发框架: Struts 2.1 + Hibernate 3.2 + Spring 2.5 + Dao 模式 - 开发工具: myEclipse 7.5 版本 - 数据库: MySQL #### 四、系统开发计划 - **集中讨论**: - 确定项目的主题、功能需求...

    基于EJB架构的论坛系统设计PPT课件.pptx

    综上所述,这个基于EJB架构的论坛系统设计课程全面覆盖了从需求分析到系统实现的各个环节,深入讲解了EJB、Hibernate JPA、JSF等技术在实际项目中的应用,是学习企业级Java应用开发的宝贵教材。

    车辆管理信息

    【车辆管理信息系统】是一款基于JAVA语言开发的办公软件,主要用于管理日常生活中的车辆及相关信息,如司机信息、车辆信息、运营信息、车辆维修信息和事故信息。该系统旨在提供信息的新增、修改和查询功能,以方便...

    SSH项目1

    SSH(Struts、Spring、Hibernate)是Java Web开发中的经典三剑客,分别负责MVC模式中的视图、控制和模型层。在这个名为"SSH项目1"的项目中,我们将探讨这三个框架的主要功能和在实际开发中的应用。 Struts框架是MVC...

    Myeclipse-ssh整合

    SSH(Struts + Spring + Hibernate)是Java Web开发中常见的三大框架集成,用于构建高效、可维护性高的企业级应用。MyEclipse作为一款强大的集成开发环境,提供了便捷的SSH整合支持。以下将详细介绍如何在MyEclipse...

    Spring MVC4+Hibernate4整合

    Spring MVC和Hibernate的整合提供了强大的Web应用开发能力,结合了MVC的分层架构和ORM的便捷性。通过XML配置,我们可以精细控制事务行为,实现数据持久化的高效管理。同时,通用DAO的设计模式提高了代码复用性,...

    架构脑图.pdf

    - **MVC分层开发**:Model-View-Controller,一种常见的软件架构模式。 - **使用properties文件抽取连接参数**:将数据库连接参数存储在.properties文件中。 - **DAO层开发**:Data Access Object,用于处理数据访问...

    留言板Struts2 代码

    Struts2是Struts1的下一代版本,它是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架。Struts2通过一系列的拦截器、配置文件以及对其他技术(如Spring、Hibernate)的良好集成来实现业务逻辑与...

    通用后台管理系统(ExtJS 5.1 + Hibernate 4.1.7 + Spring MVC 3.2.8).docx

    在代码结构上,系统采用了分层设计,包括BaseParameter、ExtJSBaseController、BaseService和BaseDao,封装了模型层、控制层、业务逻辑层和数据持久层的通用操作。ListView、PageView和QueryResult用于后台分页处理...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    4、一次编写,处处运行:作为JAVA开发平台的一部分,JSP具有JAVA的所有优点,包括Write once , Run everywhere. 3.2. 数据库的选择 3.2.1. Web应用程序开发环境—SQLserver数据库 SQL Server是由Microsoft开发和...

Global site tag (gtag.js) - Google Analytics