前两天在学习spring框架时,了解到spring框架可以对其他数据访问框架进行整合,今天学习了利用spring框架对JDBC技术的整合应用的基本操作,为了日后复习查看方便,所以在此做以总结,同时也希望对和我一样的初学者能有所帮助。
首先介绍一下spring整合JDBC时操作的基本步骤,如下:
1.首先,新建一个工程,引入Spring框架相关的开发包和主配置文件,我这里新建了一个web工程,名为SpringJdbc 。
2.然后引入JDBC的驱动包
3.这些基本操作完成后,下来先根据数据库中要操作的数据表,编写相关的实体类,如下,与数据库中的COST表相对应,我写了一个Cost实体类:
package com.jeason.entity;
public class Cost {
private Integer cost_id;
private String name;
private Integer base_duration;
private Double base_cost;
private Double unit_cost;
private String status;
private String descr;
private Date creatime;
private Date startime;
private String cost_type;
//这里需要添加上述属性的get()和set()方法
............
}
4.编写DAO接口和实现类 (这里的实现类继承自spring为JDBC技术提供的JdbcDAOSupport类,使用其中提供的Template对象对数据库进行增删改查操作),如下几个方法是JdbcTemplate类中的几个常用的方法
update() ---> 实现增删改操作
query() ----> 实现查询多行记录
queryForObject() ----> 实现查询一行记录
queryForInt() -----> 实现查询一个int值
我这里写了一个CostDAO接口和JdbcCostDAO实现类,如下是CostDAO类:
package com.jeason.dao;
public interface CostDAO {
public List<Cost> findAll();
public Cost findByID(int costID);
public void save(Cost cost);
public void modify(Cost cost);
public void delete(int id);
}JdbcCostDAO.java类如下:
package com.jeason.dao.impl;
public class JdbcCostDAO extends JdbcDaoSupport implements CostDAO {
@Override
public List<Cost> findAll() {
String findAll = "select * from COST";
RowMapper rm = new CostRowMapper();
List<Cost> list = getJdbcTemplate().query(findAll, rm);
return list;
}
@Override
public Cost findByID(int costID) {
String findById = "select * from COST where COST_ID=?";
Object[] params = {costID};
RowMapper rm = new CostRowMapper();
Cost cost = (Cost)getJdbcTemplate().queryForObject(findById, params, rm);
return cost;
}
@Override
public void save(Cost cost) {
String save = "insert into COST(COST_ID,NAME,BASE_DURATION," +
"BASE_COST,UNIT_COST,STATUS," +
"DESCR,CREATIME,COST_TYPE) " +
"values(COST_SEQ.nextval,?,?,?,?,?,?,?,?)";
Object[] params = {cost.getName(),cost.getBase_duration(),
cost.getBase_cost(),cost.getUnit_cost(),cost.getStatus(),
cost.getDescr(),cost.getCreatime(),cost.getStartime(),
cost.getCost_type()};
getJdbcTemplate().update(save, params);
}
@Override
public void modify(Cost cost) {
String modify = "update COST set NAME=?,BASE_DURATION=?," +
"BASE_COST=?,UNIT_COST=?,STATUS=?" +
"DESCR=?,CREATIME=?,STARTIME=?,COST_TYPE=?" +
"where COST_ID=?";
Object[] params = new Object[]{cost.getName(),cost.getBase_duration(),
cost.getBase_cost(),cost.getUnit_cost(),
cost.getDescr(),cost.getCreatime(),cost.getStartime(),
cost.getCost_type(),
cost.getCost_id()};
getJdbcTemplate().update(modify);
}
@Override
public void delete(int id) {
String delete="delete from COST where COST_ID=?";
Object[] params = {id};
getJdbcTemplate().update(delete);
}
}
注意:上面的程序在查找的时候需要传入一个RowMapper类型的参数,在这里我们需要重新定义一个类,继承自RowMapper类,然后重写mapRow()方法,主要作用是将从数据库中取出的数据对应的放入实体类对象中,我重写了Cost类对应的RowMapper类下:
package com.jeason.mappers;
public class CostRowMapper implements RowMapper {
@Override
public Object mapRow(ResultSet rs, int index) throws SQLException {
Cost cost = new Cost();
try {
cost.setCost_id(rs.getInt("cost_id"));
cost.setName(rs.getString("name"));
cost.setBase_duration(rs.getInt("base_duration"));
cost.setBase_cost(rs.getDouble("base_cost"));
cost.setUnit_cost(rs.getDouble("unit_cost"));
cost.setDescr(rs.getString("descr"));
cost.setStatus(rs.getString("status"));
cost.setCost_type(rs.getString("cost_type"));
cost.setCreatime(rs.getDate("creatime"));
cost.setStartime(rs.getDate("startime"));
} catch (SQLException e) {
e.printStackTrace();
}
return cost;
}
}
5.最后将DAO组件交给Spring容器,进行相关配置,这是最后一步,也是最关键的一步,配置时主要有以下几步:
---a.定义DAO组件的<bean>元素
---b.需要给DAO的bean注入一个dataSource对象
---c.dataSource对象采用一个连接池构建(我才用的是dbcp连接池),先引入dbcp连接池开发包,再定义dataSource对象<bean>
采用连接池有以下几个优点=====================
a.增强数据访问的稳定性
b.连接池可以将连接数控制在一定范围内
c.连接池中的对象使用完了之后会重新放回连接池内,避免了频繁的新建和释放连接操作,连接对象始终与数据库保持连通状态
如下,就是applicationContext.xml 文件中的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- 定义连接池组件 -->
<bean id="MyDataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<!-- 注入连接参数 -->
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="username" value="system" />
<property name="password" value="zx123456" />
<!-- 设置连接对象最大数 -->
<property name="maxActive" value="20" />
<property name="initialSize" value="2" />
</bean>
<bean id="costDao" class="com.jeason.dao.impl.JdbcCostDAO">
<!-- 为DAO组件注入连接池对象 -->
<property name="dataSource" ref="MyDataSource"/>
</bean>
</beans>
到此,就可以编写测试类来测试Spring+JDBC项目是否能正常运行,我的测试类如下:
package com.jeason.test;
public class TestSpringJdbc {
//测试查询
@Test
public void test1(){
String cfg = "/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(cfg);
CostDAO cd = (CostDAO)ac.getBean("costDao");
List<Cost> list = cd.findAll();
for(Cost c: list){
System.out.println(c.getCost_id()+"----->"+c.getName());
}
}
}
以上是采用xml文件配置的方式利用Spring容器进行管理,我们也可以采用注解的方式将上面的JdbcCostDAO组件交给Spring容器管理,以下简单说一下采用注解方式的操作:
首先在applicationContext.xml配置中开启组件扫描,加入以下配置:
<context:component-scan base-package="com.jeason" />
然后在JdbcCostDAO类中进行注解配置,在该类的声明前加上@Repository("jdbcCostDAO"),指明采用prototype方式实例化还可以加上 @Scope("prototype")
注意:由于这里要用到Spring提供的JdbcDaoSupport类,所以要将上面的连接池组件给该DAO组件注入,但是这里的DAO组件是继承自JdbcDAOSupport类,无法直接注入,可以在该类中定义一个方法,这里采用以下方法:
@Resource("dataSource")
public void setMyDataSource(DataSource ds){
super.setDataSource(ds);
}
这个方法名自己定义,不过注意不要与父类JdbcDaoSupport中的方法名重名,然后在该set方法声明注解,将声明的dataSource组件注入。
然后就可以在applicationContext.xml配置中删除该DAO组件的配置了,但是别把连接池的配置也删了哦。这样就OK咯。