直接使用JDBC操作数据库来实现DAO,相对于使用持久层框架(Hibernate等) ,可以减少映射等带来的性能损失。
一般而言,使用JDBC来操作数据库,无非是以下几个步骤:
获取数据源
取得数据库连接
执行SQL语句
处理执行结果和异常
释放数据库连接
这些步骤是每次进行数据库操作都必须进行的。很显然,可以使用模板模式来简化设计,将执行SQL语句的部分抽象出来,其它的步骤由模板自动完成。
虽然设计这样的模板并不算复杂,但是现在我们完全无需自己来实现,应为Spring已经为我们提供了一个非常实用的模板--JdbcTemplate。它位于Spring包org.springframework.jdbc.core下,是Spring的jdbc工具包的核心类之一。使用JdbcTemplate的前提是必须为其提供数据源(DataSource),并通过实用类DataSourceUtils来安全地获取和释放数据库连接(Connection对象)。可以说已经是一个完美的实现,因此我们只要放心地使用就可以了。
总体思路
(1)数据源通过Spring的容器来提供;
(2)DAO通过静态方式从Spring容器中获取;
(3)针对接口编程;
(4)提供数据操作父类,简化具体DAO实现。
一、DAO地实现
遵循Spring的良好编程风格,针对接口编程。同时,为了简化对接口的实现,还提供了一个所有实现类的父类,提供了具体的数据库操作方法,这些方法当然就是使用JdbcTemplate来实现的了。
1、Dao父类
主要目的是获取数据源,为子类提供具体的数据库操作方法:
public class Dao {
/**
* 日志
*/
protected Log log = LogFactory.getLog(this.getClass().getName());
/**
* 执行查询SQL文
*
* @param strSql
*/
protected void doQuery(String strSql) {

JdbcTemplate jt = new JdbcTemplate(getDataSource()); //使用JdbcTemplate
try {
List result = jt.queryForList(strSql);
this.resultList = result;
this.resultCount = result.size();
log.debug(logHeader + strSql);
} catch (DataAccessException de) {
log.error(logHeader + de);
}
}
/**
* 执行更新SQL文
*
* @param strSql
*/
protected boolean doUpdate(String strSql) {
JdbcTemplate jt = new JdbcTemplate(getDataSource());
try {
this.affectedRows = jt.update(strSql);
log.debug(logHeader + strSql);
return true;
} catch (DataAccessException de) {
log.error(logHeader + de);
return false;
}
}

/**
* 获取执行结果的一行
*
* @return 一行结果用Map保存
*/
protected Object getResult() {
if (this.resultList == null || this.resultList.size() == 0) {
return null;
} else {
return this.resultList.get(0);
}
}
/**
* 获取查询结果
*
* @return 查询结果以List保存
*/
protected List getResultList() {
return this.resultList;
}
/**
* 获取更新所影响的行记录数
*
* @return 整数
*/
protected int getAffectedRows() {
return this.affectedRows;
}
/**
* 获取查询结果总行数
*
* @return 整数
*/
protected long getResultCount() {
return this.resultCount;
}

/** 日志头部 */
protected String logHeader = LogUtil.getLogHeader();
/**
* @return dataSource
*/
public DataSource getDataSource() {
return dataSource;
}

/**
* @param dataSource 设置 dataSource
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource; //获取数据源
}
//-------------------------------------------------------------------------

private List resultList = null;
private long resultCount = 0;
private int affectedRows = 0;
private DataSource dataSource = null;
}
此处为dataSource提供了get/set方法,可以从使用Spring的Ioc中获益,即可以使用配置的方法为之选择数据源(本文的实现方式);同时,也可以通过代码手工提供数据源。
2、UserDao接口定义:
public interface UserDao {
/**
* 根据用户ID,获取User对象
*
* @param 用户ID
* @return User対象
*/
public User getUserByLoginId(String loginId);

}
就一个方法,仅仅是示例而已 ^_^
3、UserDaoImpl实现:
public class UserDaoImpl extends Dao implements UserDao {

/*
* (non-Javadoc)
* @see my.test.dao.UserDao#getUserByLoginId(java.lang.String)
*/
public User getUserByLoginId(String loginId) {
User user = null;
doQuery(Sql.S_M_MEMBER_01(loginId));
if (getResultCount() > 0) {
user = new User();
Map result = (Map) getResult();
user.setMemberId(String.valueOf(result.get("MEMBER_ID")));
//以下省略
}
return user;
}

}
这里只是简单地实现了平面(二维的数据库)和立体(对象)的转换,并没有涉及到对关系数据库中的关系的转化,这些都要靠自己去实现,还是有些不方便。自己实现的麻烦之处就是要手工编写所有的SQL语句...但一切都在自己的掌控制中,也没什么不好,呵呵。
现在看看红色的部分用起来是不是简便了很多了。
罗罗嗦嗦地一堆代码,还不如看图来得清爽:

二、DAO的使用
既然使用了JdbcTemplate,为什么不再多使用一点Spring的功能呢?比如通过配置为DAO提供数据源等。但问题是,整个应用系统如果没有使用Spring的容器来管理,如何才能使用Ioc功能呢?还好,可以将Spring的应用上下文(ApplicationContext)单独地使用。我们可以将DAO作为单独的bean分别定义,然后从ApplicationContext中取得这些bean的实例。Spring会根据定义为我们自动生成所需的DAO的实例。只要在定义的时候,为DAO提供Datasoure即可实现数据源的自动配置了。
1、daoBeans.xml
使用了Spring的数据源管理功能,通过定义的方式为UserDao提供了数据源(在生成UserDao实例的时候,setDataSource方法就会被调用从而将dataSource载入)。
2、DAO获取工具的实现
编写了一个工具类,提供根据DAO名(daoBeans.xml中定义的名字)获取DAO对象的静态方法。
public class DaoBeanFactory {
private static Log log = LogFactory.getLog(DaoBeanFactory.class.getName());
private static final String DAO_BEANS= "/daoBeans.xml";
private static ApplicationContext ctx = null;
static {
ctx = new ClassPathXmlApplicationContext(DAO_BEANS);
log.debug(DAO_BEANS + "被成功载入。");
}
public static Object getDao(String daoName){
return ctx.getBean(daoName);
}
}
这里首先通过读取daoBeans.xml初始化应用上下文(ApplicationContext )。由于是静态方法,只会在第一次被使用时执行一次;然后就可从上下文中获取所需要的指名DAO对象了:
private UserDao userDao = (UserDao) DaoBeanFactory.getDao("userDao");
到此为止,可以说从实现到使用都已经大功告成了,happy一下。
三、进一步改进
并不是说一切都是完美的。比如,第一次执行DaoBeanFactory.getDao方法时,会进行应用上下文的初始化,耗时较多;想改善数据源的管理,比如使用连接池;更进一步,如果大部分的工作都是进行查询,想提高系统的查询效率,该如何呢?
时间不够,请等待下回分解。
一般而言,使用JDBC来操作数据库,无非是以下几个步骤:
获取数据源
取得数据库连接
执行SQL语句
处理执行结果和异常
释放数据库连接
这些步骤是每次进行数据库操作都必须进行的。很显然,可以使用模板模式来简化设计,将执行SQL语句的部分抽象出来,其它的步骤由模板自动完成。
虽然设计这样的模板并不算复杂,但是现在我们完全无需自己来实现,应为Spring已经为我们提供了一个非常实用的模板--JdbcTemplate。它位于Spring包org.springframework.jdbc.core下,是Spring的jdbc工具包的核心类之一。使用JdbcTemplate的前提是必须为其提供数据源(DataSource),并通过实用类DataSourceUtils来安全地获取和释放数据库连接(Connection对象)。可以说已经是一个完美的实现,因此我们只要放心地使用就可以了。
总体思路
(1)数据源通过Spring的容器来提供;
(2)DAO通过静态方式从Spring容器中获取;
(3)针对接口编程;
(4)提供数据操作父类,简化具体DAO实现。
一、DAO地实现
遵循Spring的良好编程风格,针对接口编程。同时,为了简化对接口的实现,还提供了一个所有实现类的父类,提供了具体的数据库操作方法,这些方法当然就是使用JdbcTemplate来实现的了。
1、Dao父类
主要目的是获取数据源,为子类提供具体的数据库操作方法:























































































































2、UserDao接口定义:












3、UserDaoImpl实现:























现在看看红色的部分用起来是不是简便了很多了。
罗罗嗦嗦地一堆代码,还不如看图来得清爽:
二、DAO的使用
既然使用了JdbcTemplate,为什么不再多使用一点Spring的功能呢?比如通过配置为DAO提供数据源等。但问题是,整个应用系统如果没有使用Spring的容器来管理,如何才能使用Ioc功能呢?还好,可以将Spring的应用上下文(ApplicationContext)单独地使用。我们可以将DAO作为单独的bean分别定义,然后从ApplicationContext中取得这些bean的实例。Spring会根据定义为我们自动生成所需的DAO的实例。只要在定义的时候,为DAO提供Datasoure即可实现数据源的自动配置了。
1、daoBeans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@192.168.***.***:1521:***"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
<property name="validationQuery" value="SELECT 1 FROM DUAL"/>
</bean>

<bean id="userDao" class="my.test.dao.impl.UserDaoImpl">
<property name="dataSource"> <--为UserDao设置数据源
<ref bean="dataSource"/>
</property>
</bean>

</beans>





















2、DAO获取工具的实现
编写了一个工具类,提供根据DAO名(daoBeans.xml中定义的名字)获取DAO对象的静态方法。

















到此为止,可以说从实现到使用都已经大功告成了,happy一下。
三、进一步改进
并不是说一切都是完美的。比如,第一次执行DaoBeanFactory.getDao方法时,会进行应用上下文的初始化,耗时较多;想改善数据源的管理,比如使用连接池;更进一步,如果大部分的工作都是进行查询,想提高系统的查询效率,该如何呢?
时间不够,请等待下回分解。