Spring核心技术详解(六)

Spring JDBC

一、Spring JDBC简介

  我们早期都有过直接使用JDBC访问数据库的经历,开发者需要编写获取数据库连接处理异常释放资源数据操作等代码。即使很简单的数据库操作,都需要很繁琐的编写。Spring JDBC通过模板和回调机制大大降低了JDBC的繁琐程度,我们仅需编写那些必不可少的数据操作代码就可以完成操作。


二、Spring模板和回调机制

  在直接使用JDBC时。我们需要处理获取连接,处理异常、释放资源等整个流程。Spring为支持的持久化技术提供了模板访问的方式,我们只需要提供具体的操作数据代码即可,可以大幅度提高开发效率。

  Spring将相同的数据访问流程固定到模板类中,例如,获取连接、释放资源等等。将数据库操作中固定和变化的部分分开,同时保证模板类线程安全,以便多个线程共享同一模块实例。固定的部分在模板类中已经写好,变化的部分通过回调接口开放出来,用于具体的数据访问和结果处理操作。

  Spring为各种支持的持久化技术都提供了简化操作的模板和回调。例如为传统的JDBC提供了JdbcTemplate模块类,为Hibernate提供了HibernateTemplate模板类等等很多。我们直接使用即可。


三、Spring JDBC入门例子

  不论使用任何持久化技术,都必须拥有数据库连接。在Spring中,我们需要配置数据库连接池来获取连接。我们的代码中都统一使用c3p0连接池。

  首先我们要先导包,我们需要导入spring的核心四个包jdbc包tx包(事务操作),然后还需要导入c3p0包数据库驱动等。

我们创建一个数据库和数据表来进行演示 
CREATE DATABASE springdb;
USE springdb;
CREATE TABLE USER(
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50),
    PASSWORD VARCHAR(50)        
); 

INSERT INTO USER(username,PASSWORD) VALUES('张三','123456');
我们来演示一下怎么使用JdbcTemplate 
public class TestJdbc { 
    @Test
    public void test() throws Exception{ 
        //创建c3p0连接池,并设置相应的数据库参数
        ComboPooledDataSource datasource=new ComboPooledDataSource();
        datasource.setDriverClass("com.mysql.jdbc.Driver"); 
        datasource.setJdbcUrl("jdbc:mysql://localhost:3306/springdb");
        datasource.setUser("root");
        datasource.setPassword("123456");

        //创建JdbcTemplate对数据库进行操作
        JdbcTemplate template=new JdbcTemplate(datasource);
        String sql="insert into user(username,password) values(?,?)";
        template.update(sql, "李四","456789");
    }

}

这里写图片描述

四、详解JdbcTemplate

  JdbcTemplate模板类几乎可以完成任何数据访问的操作,并且非常方便简介。我们上面的例子都是手动通过API 来创建连接池,来创建JdbcTemplate,我们完全可以使用我们学习的IoC来使用配置文件来替代那些操作,这也是我们所提倡的。


使用配置文件

  我们在Dao中使用Jdbctemplate,JdbcTemplate直接在配置文件中配置好,直接在Dao中注入即可。

//我们先创建一个实体类
public class User {
    private int id;
    private String username;
    private String password;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
    }

}
//创建Dao来对数据进行操作
public class UserDao { 
    //提供JdbcTemplate和set方法来进行注入
    private JdbcTemplate template;

    public void setTemplate(JdbcTemplate template) {
        this.template = template;
    }

    //更新方法
    public void update(User user){
        String sql="update  user set username=?,password=?  where id=?";
        Object []params={user.getUsername(),user.getPassword(),user.getId()};
        template.update(sql, params);
    }
}
<!--编写配置文件-->
<?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:context="http://www.springframework.org/schema/context"  
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> 

<!--配置连接池-->
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springdb"></property>
    <property name="user" value="root"></property>
    <property name="password" value="123456"></property>
</bean>  

<!--实例JdbcTemplate,并且通过dataSource属性注入连接池-->
<bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="datasource"></property>
</bean> 

<!--实例化Dao,并注入JdbcTemplate-->
<bean id="userdao" class="com.spring.jdbc.UserDao">
    <property name="template" ref="jdbctemplate"></property>
</bean>
</beans>     
//我们来测试一下
public class TestJdbc {     
    @Test
    public void test() throws Exception{
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        UserDao userdao=(UserDao) ac.getBean("userdao");
        User user=new User();
        user.setId(1);
        user.setUsername("王五");
        user.setPassword("888888");
        userdao.update(user);
    }
}

这里写图片描述


使用属性文件配置数据库信息

  数据库的配置信息有可能需要经常改动,所以一般将数据库配置信息放在属性文件中。

//创建一个属性文件,名为jdbc.properties 

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/springdb
user=root
password=123456
<!--引入属性文件,以${xxx}的方式引入属性-->
<context:property-placeholder location="jdbc.properties"/>
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${driverClass}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
    <property name="user" value="${user}"></property>
    <property name="password" value="${password}"></property>
</bean> 

JdbcDaoSupport

  我们的Dao层使用JdbcTemplate都需要提供一个JdbcTemplate属性和set方法来进行注入,而Spring为我们提供了一个父类JdbcDaoSupport,已经帮我们做好了这些操作。

//我们的Dao继承JdbcDaoSupport
public class UserDao extends JdbcDaoSupport{

    public void update(User user){
        String sql="update  user set username=?,password=?  where id=?";
        Object []params={user.getUsername(),user.getPassword(),user.getId()};
        this.getJdbcTemplate().update(sql, params);
    }
}   
//更改配置文件
<?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:context="http://www.springframework.org/schema/context"  
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springdb"></property>
    <property name="user" value="root"></property>
    <property name="password" value="123456"></property>
</bean> 

<!--只需要将连接池给它,父类会自动帮我们创建JdbcTemplate-->
<bean id="userdao" class="com.spring.jdbc.UserDao">
    <property name="dataSource" ref="datasource"></property>
</bean>
</beans>   

批量更改数据

如果需要一次性插入或更新多条记录,我们可以使用JdbcTemplate提供的批量操作的方法。

  • int[] batchUpdate(String []sql):多条不带参数的sql语句组成一个数组,该方法以批量方式执行这些sql语句,底层使用JDBC提供的批量操作的API。

  • int[] batchUpdate(String sql,BatchPreparedStatementSetter pss):使用本方法对带参sql语句进行多次数据更新操作,通过BatchPreparedStatementSetter回调接口进行批量参数的绑定工作。该接口定义了两个方法:

int  getBatchSize():指定本批次的大小
void setValues(PreparedStatement ps,int i):为给定的PreparedStatement设置参数 
//我们为我们的Dao添加一个添加班级的操作,一次性插入多个User
public void addClass(final List<User> l){
        String sql="insert into user(username,password) values(?,?)"; 
        //执行批量操作
        template.batchUpdate(sql, new BatchPreparedStatementSetter() {

            //绑定插入的参数
            public void setValues(PreparedStatement ps, int index) throws SQLException {
                User user=l.get(index);
                ps.setString(1, user.getUsername());
                ps.setString(2, user.getPassword());
            }

            public int getBatchSize() {
                return l.size();
            }
        });
    }
//我们来进行测试一下
public class TestJdbc {     
    @Test
    public void test() throws Exception{
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        UserDao userdao=(UserDao) ac.getBean("userdao");
        List<User> list=new ArrayList<User>();
        User user1=new User();
        user1.setUsername("孙悟空");
        user1.setPassword("123");
        User user2=new User();
        user2.setUsername("猪八戒");
        user2.setPassword("456");
        list.add(user1);
        list.add(user2);
        userdao.addClass(list);
    }
}

这里写图片描述


查询所有数据

    //Spring提供了RowMapper<T>接口来处理结果集,有很多实现类,我们使用BeanPropertyRowMapper
    public List<User> selectAll(){
        String sql="select * from user";
        return template.query(sql,BeanPropertyRowMapper.newInstance(User.class));
    }
//我们测试一下
public class TestJdbc {     
    @Test
    public void test() throws Exception{
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        UserDao userdao=(UserDao) ac.getBean("userdao");
        List<User> list=userdao.selectAll();
        for(User u:list){
            System.out.println(u);
        }
    }
}

这里写图片描述


五、NamedParameterJdbcTemplate

  在JdbcTemplate中,我们只能使用?占位符来声明sql语句参数,使用索引来绑定参数,如果我们uyao新增一个占位符,可能会导致很多问题。这种编程模式被认为是弱稳定的。

  NamedParameterJdbcTemplate模板类支持命名参数绑定的功能。

  SqlParameterSource接口用来提供参数 ,有两个实现类:

  • BeanPropertySqlParameterSource:该类将JavaBean对象封装成参数,以便通过javaBean属性名和SQL语句中命名参数匹配的方式绑定参数。
  • MapSqlParameterSource:该实现类内部通过一个Map存储参数。
//我们创建一个Dao类
public class StudentDao { 
    //提供NamedParameterJdbcTemplate,以便注入
    private NamedParameterJdbcTemplate template; 

    public void setTemplate(NamedParameterJdbcTemplate template) {
        this.template = template;
    }

    public void addStudent(User user){
        //使用命名参数,格式是:javaBean属性名 
        String sql="insert into user(username,password) values(:username,:password)"; 
        //提供参数
        SqlParameterSource sps=new BeanPropertySqlParameterSource(user);
        template.update(sql, sps);
    }
}
<!--配置文件-->
<?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:context="http://www.springframework.org/schema/context"  
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<context:property-placeholder location="jdbc.properties"/>
<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${driverClass}"></property>
    <property name="jdbcUrl" value="${jdbcUrl}"></property>
    <property name="user" value="${user}"></property>
    <property name="password" value="${password}"></property>
</bean> 

<bean id="template" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
    <constructor-arg ref="datasource"></constructor-arg>
</bean>
<bean id="studentdao" class="com.spring.jdbc.StudentDao">
    <property name="template" ref="template"></property>
</bean>
</beans>     
//我们测试一下 
public class TestJdbc {

    @Test
    public void test() throws Exception{
        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        StudentDao studentdao=(StudentDao) ac.getBean("studentdao"); 
        User user=new User();
        user.setUsername("天蓬元帅");
        user.setPassword("123456");
        studentdao.addStudent(user);
    }

}

这里写图片描述

Spring在org.springframework.jdbc.object包中提供了若干个类,试图以更面向对象过的方式访问数据库,但从操作难易度和使用效果上看,我们看不到它的优势,基本算是很鸡肋的功能。Spring的Jdbc只要能用上述的一些基本操作即可,毕竟有许多专业的orm框架,例如HibernateMybatis等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值