使用Spring的JdbcTemplate实现DAO

本文介绍了如何利用Spring的JdbcTemplate实现DAO操作,减少了使用持久层框架如Hibernate的映射性能损失。JdbcTemplate提供了安全的数据源管理和数据库连接操作,通过模板模式简化了SQL执行流程。文章展示了如何创建Dao父类、定义接口、实现接口以及如何配置和使用DAO,强调了Spring的Ioc功能和数据源配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

直接使用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
<?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>
使用了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方法时,会进行应用上下文的初始化,耗时较多;想改善数据源的管理,比如使用连接池;更进一步,如果大部分的工作都是进行查询,想提高系统的查询效率,该如何呢?
    时间不够,请等待下回分解。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值