玩转JdbcTemplate

2021/06/07 DB/JDBC/事务 共 19959 字,约 58 分钟
闷骚的程序员

1. 什么是JdbcTemplate?

前面学习了Commons DbUtils,是用来简化jdbc传统的操作步骤的。
实际上spring针对原生jdbc也封装了一个模板对象,就是JdbcTemplate。
java中操作db最原始的方式就是纯jdbc了,每次操作db都需要加载数据库驱动、获取连接、获取PreparedStatement、执行sql、关闭PreparedStatement、关闭连接等,操作还是比较繁琐的,spring中提供了一个模块,对jdbc操作进行了封装,使其更简单。
这个模块的核心对象就是JdbcTemplate,JdbcTemplate是spring对jdbc的封装,目的是使jdbc更加易于使用。

2. JdbcTemplate源码解析

  1. 类定义
    public class JdbcTemplate extends JdbcAccessor implements JdbcOperations
    
  2. 属性字段
    private static final String RETURN_RESULT_SET_PREFIX = "#result-set-";
    private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";
    private NativeJdbcExtractor nativeJdbcExtractor;
    private boolean ignoreWarnings = true;
    private int fetchSize = 0;
    private int maxRows = 0;
    private int queryTimeout = 0;
    private boolean skipResultsProcessing = false;
    private boolean skipUndeclaredResults = false;
    private boolean resultsMapCaseInsensitive = false;
    
  3. 构造方法
    public JdbcTemplate() {
    }
    public JdbcTemplate(DataSource dataSource) {
    this.setDataSource(dataSource);
    this.afterPropertiesSet();
    }
    public JdbcTemplate(DataSource dataSource, boolean lazyInit) {
    this.setDataSource(dataSource);
    this.setLazyInit(lazyInit);
    this.afterPropertiesSet();
    }
    
  4. setter/getter
    public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) {
    this.nativeJdbcExtractor = extractor;
    }
    public NativeJdbcExtractor getNativeJdbcExtractor() {
    return this.nativeJdbcExtractor;
    }
    public void setIgnoreWarnings(boolean ignoreWarnings) {
    this.ignoreWarnings = ignoreWarnings;
    }
    public boolean isIgnoreWarnings() {
    return this.ignoreWarnings;
    }
    public void setFetchSize(int fetchSize) {
    this.fetchSize = fetchSize;
    }
    public int getFetchSize() {
    return this.fetchSize;
    }
    public void setMaxRows(int maxRows) {
    this.maxRows = maxRows;
    }
    public int getMaxRows() {
    return this.maxRows;
    }
    public void setQueryTimeout(int queryTimeout) {
    this.queryTimeout = queryTimeout;
    }
    public int getQueryTimeout() {
    return this.queryTimeout;
    }
    public void setSkipResultsProcessing(boolean skipResultsProcessing) {
    this.skipResultsProcessing = skipResultsProcessing;
    }
    public boolean isSkipResultsProcessing() {
    return this.skipResultsProcessing;
    }
    public void setSkipUndeclaredResults(boolean skipUndeclaredResults) {
    this.skipUndeclaredResults = skipUndeclaredResults;
    }
    public boolean isSkipUndeclaredResults() {
    return this.skipUndeclaredResults;
    }
    public void setResultsMapCaseInsensitive(boolean resultsMapCaseInsensitive) {
    this.resultsMapCaseInsensitive = resultsMapCaseInsensitive;
    }
    public boolean isResultsMapCaseInsensitive() {
    return this.resultsMapCaseInsensitive;
    }
    

3. 如何使用JdbcTemplate?

  1. 使用JdbcTemplate需要DataSource数据源的支持。
    spring提供的jdbcTemplate对象是对jdbc技术的封装,通过该对象可以更加方便的操作数据库,相当于DBUtils里面的QueryRunner对象。
    使用JdbcTemplate对象,需要数据源的支持。
    通过JdbcTemplate源码可以知道,构造方法总共有3个:
    public JdbcTemplate() {
    }
    public JdbcTemplate(DataSource dataSource) {
    this.setDataSource(dataSource);
    this.afterPropertiesSet();
    }
    public JdbcTemplate(DataSource dataSource, boolean lazyInit) {
    this.setDataSource(dataSource);
    this.setLazyInit(lazyInit);
    this.afterPropertiesSet();
    }
    

    第1个是空构造方法;
    第2个是有一个DataSource参数的构造方法;
    第3个是有两个参数的构造方法,分别是DataSource和lazyInit。
    除了第1个空构造方法外,剩下两个构造方法都需要传入DataSource对象。
    也就是说,我们在实例化JdbcTemplate对象时,并不一定非得传入DataSource对象。
    但实际上,JdbcTemplate方法里面去绑定数据源的方式,只提供了一种,如下:

    public void setDataSource(DataSource dataSource)
    
而并没有提供其他类似jdbc之类的单独去绑定driverClassName、url、username、password之类的方法。由此可见,使用JdbcTemplate是离不开DataSource数据源的支持的。这也侧面验证了遵守jdbc2.0规范的重要性。
  1. 使用JdbcTemplate的方式
    (1)直接硬编码,即直接new,此时的JdbcTemplate对象并没有交给Spring管理。
    public class JdbcTemplateTest {
        public static void main(String[] args) {
       // 硬编码方式1
       JdbcTemplate jdbcTemplate = new JdbcTemplate();
       jdbcTemplate.setDataSource(new BasicDataSource());
       // 硬编码方式2
       JdbcTemplate jdbcTemplate1 = new JdbcTemplate(new BasicDataSource());
       // 硬编码方式3
       JdbcTemplate jdbcTemplate2 = new JdbcTemplate(new BasicDataSource(),Boolean.FALSE);
        }
    }
    

(2)spring和jdbcTemplate整合,交给spring管理,通过注解或者xml配置进行注入。
依赖关系是:业务Dao对象依赖JdbcTemplate,JdbcTemplate依赖DataSource。
业务Dao需要自己手动定义jdbcTemplate作为成员和对应的setter方法,如下:

public class PersonDaoImpl implements PersonDao{
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

通过xml配置依赖关系如下:

<!-- 配置dbcp数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <!-- 通过property属性注入依赖成员 -->
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url">
        <value>jdbc:oracle:thin:@localhost:1521:orcl</value>
    </property>
    <property name="username" value="oracle" />
    <property name="password" value="oracle" />
</bean>
<!-- 配置jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置dao -->
<bean id="personDao" class="demo08.myspring.model.jdbc.dao.impl.PersonDaoImpl"
      depends-on="jdbcTemplate" init-method="initDatabase">
    <property name="jdbcTemplate">
        <ref bean="jdbcTemplate" />
    </property>
</bean>

(3)spring和jdbcTemplate整合,交给spring管理,引入JdbcDaoSupport更加方便的直接管理JdbcTemplate对象。
通过(2)可以看出,自己编写一个业务Dao,交给Spring管理,需要有如下依赖关系:

业务Dao依赖JdbcTemplate对象; JdbcTemplate对象依赖DataSource对象。

这种依赖层次有点多,如果能够直接在业务Dao中注入DataSource对象就很方便了。
spring提供了一个Support类来实现这种便捷,这个类是 JdbcDaoSupport
业务Dao必须继承JdbcDaoSupport类,才能持有JdbcTemplate对象,这样就不用自己在Dao类中添加JdbcTemplate变量了:

public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao

通过xml配置依赖关系如下:

<!-- 配置dbcp数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <!-- 通过property属性注入依赖成员 -->
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url">
        <value>jdbc:oracle:thin:@localhost:1521:orcl</value>
    </property>
    <property name="username" value="oracle" />
    <property name="password" value="oracle" />
</bean>
<!-- 配置dao -->
<bean id="personDao" class="demo08.myspring.model.jdbc.dao.impl.PersonDaoImpl"
      depends-on="dataSource" init-method="initDatabase">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
</bean>

4. 通过硬编码操作JdbcTemplate的API

我们直接通过硬编码的方式去构建JdbcTemplate。
## 4.1 JdbcTemplate使用步骤

  1. 创建数据源DataSource。
  2. 创建JdbcTemplate对象,new JdbcTemplate(dataSource);
  3. 调用JdbcTemplate的方法操作db,如增删改查。
    package lurenjia_jdbcTemplate.study01;
    import org.apache.commons.dbcp.BasicDataSource;
    import javax.sql.DataSource;
    /**
     * @Date 2021/9/23 19:25
     */
    public class DataSourceBuild {
        public static DataSource getDataSource() {
       BasicDataSource dataSource = new BasicDataSource();
       dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
       dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");
       dataSource.setUsername("oracle");
       dataSource.setPassword("oracle123");
       return dataSource;
        }
    }
    
    package lurenjia_jdbcTemplate.study01;
    import org.junit.Test;
    import org.springframework.jdbc.core.JdbcTemplate;
    import javax.sql.DataSource;
    import java.util.List;
    import java.util.Map;
    /**
     * @Date 2021/9/23 18:59
     */
    public class JdbcTemplateTest {
        @Test
        public void test() {
       // 1.创建数据源DataSource
       DataSource dataSource = DataSourceBuild.getDataSource();
       // 2.创建jdbcTemplate对象,new JdbcTemplate(dataSource)
       JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
       // 3.调用JdbcTemplate的方法操作db,如增删改查
       List<Map<String, Object>> allMaps = jdbcTemplate.queryForList("select * from users");
       System.out.println(allMaps);
        }
    }
    

    输出:

    [{ID=12345, NAME=TestInsert, AGE=19, SEX=男, HOBBY=编程}, {ID=12333, NAME=Mybatis, AGE=19, SEX=男, HOBBY=Mybatis系列}, {ID=12334, NAME=mySql, AGE=21, SEX=女, HOBBY=唱歌,跳舞}]
    

    上面查询返回了oracle中person表中所有的记录数据,返回了一个集合List列表,集合中每一个元素是一个Map,Map表示一行记录,key为列名,value为列对应的值。
    是不是觉得特别的方便,只需要jdbcTemplate.queryForList("select * from person");这么简单的一行代码,数据就被获取到了。
    下面继续探索更强大更好用的功能。

4.2 增加、删除、修改操作

JdbcTemplate中以update开头的方法,用来执行增、删、改操作

,下面看几个常用的。</br>

无参情况

Api

public int update(final String sql)

案例

@Test
public void test1() {
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    int updateRows = jdbcTemplate.update("insert into users(id,name,age,sex,hobby) values ('12345','TestInsert',19,'男','编程')");
    System.out.println("影响行数:" + updateRows);
}

运行

影响行数:1
有参情况1

Api

public int update(String sql, Object... args)  

案例

sql中使用?作为占位符
@Test
public void test2() {
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    int updateRows = jdbcTemplate.update("insert into users(id,name,age,sex,hobby) values (?,?,?,?,?)", "12333", "Mybatis", 19, "男", "Mybatis系列");
    System.out.println("影响行数:" + updateRows);
}

运行

影响行数:1
有参情况2

Api

public int update(String sql, PreparedStatementSetter pss)

通过PreparedStatementSetter来设置参数,是一个函数式接口,内部有个setValues方法会传递一个PreparedStatement参数,我们可以通过这个参数手动的设置参数的值。
案例

@Test
public void test3(){
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    int updateRows = jdbcTemplate.update("insert into users(id,name,age,sex,hobby) values (?,?,?,?,?)", new PreparedStatementSetter() {
        @Override
        public void setValues(PreparedStatement preparedStatement) throws SQLException {
            preparedStatement.setString(1,"12334");
            preparedStatement.setString(2,"mySql");
            preparedStatement.setInt(3,21);
            preparedStatement.setString(4,"女");
            preparedStatement.setString(5,"唱歌,跳舞");
        }
    });
    System.out.println("影响行数:" + updateRows);
}

运行

影响行数:1

4.3 获取自增列的值

Api

public int update(PreparedStatementCreator psc, final KeyHolder generatedKeyHolder)

案例

@Test
public void test4() {
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    final String sql = "insert into users(id,name,age,sex,hobby) values (?,?,?,?,?)";
    KeyHolder keyHolder = new GeneratedKeyHolder();
    int rowCount = jdbcTemplate.update(new PreparedStatementCreator() {
        @Override
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            // 手动创建PreparedStatement,注意第二个参数:Statement.RETURN_GENERATED_KEYS
            PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            preparedStatement.setString(1, "12335");
            preparedStatement.setString(2, "mySql");
            preparedStatement.setInt(3, 21);
            preparedStatement.setString(4, "女");
            preparedStatement.setString(5, "唱歌,跳舞");
            return preparedStatement;
        }
    }, keyHolder);
    System.out.println("新记录id:" + keyHolder.getKey().intValue());
}

4.4 批量增删改操作

Api

public int[] batchUpdate(final String[] sql)
public int[] batchUpdate(String sql, List<Object[]> batchArgs)
public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes)

案例

@Test
public void test5() {
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    final String sql = "insert into users(id,name,age,sex,hobby) values (?,?,?,?,?)";
    List<Object[]> list = Arrays.asList(
            new Object[]{"13001","Mybatis", 19, "1", "Mybatis系列"},
            new Object[]{"13002","Mybatis", 19, "1", "Mybatis系列"},
            new Object[]{"13003","Mybatis", 19, "1", "Mybatis系列"},
            new Object[]{"13004","Mybatis", 19, "1", "Mybatis系列"}
    );
    int[] updateRows = jdbcTemplate.batchUpdate("insert into users(id,name,age,sex,hobby) values (?,?,?,?,?)", list);
    for(int updateRow : updateRows){
        System.out.println(updateRow);
    }
}

4.4 查询操作

查询一列单行

Api

// sql:执行的sql,如果有参数,使用参数占位符?
// requiredType:返回的一列数据对应的java类型,比如String
// args:?占位符对应的参数列表
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args)

案例

@Test
public void test6() {
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    String name = jdbcTemplate.queryForObject("select name from users where id = ?", String.class, "13001");
    System.out.println(name);
}

运行

Mybatis

使用注意:

如果queryForObject中sql查询无结果时,会报错

比如id=0的记录不存在

@Test
public void test7() {
    DataSource dataSource = DataSourceBuild.getDataSource();
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    String name = jdbcTemplate.queryForObject("select name from users where id = ?", String.class, "0");
    System.out.println(name);
}

运行,会弹出一个异常 EmptyResultDataAccessException,期望返回一条记录,但实际上却没有找到记录,和期望结果不符,所以报错了。

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
    at org.springframework.dao.support.DataAccessUtils.requiredSingleResult(DataAccessUtils.java:71)
    at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:730)
    at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:749)

这种如何解决呢,需要用到查询多行的方式来解决了,即下面要说到的queryForList相关的方法,无结果的时候返回一个空的List,我们可以在这个空的list上面做文章。

查询一列多行

Api

5. 通过spring整合JdbcTemplate去操作API

我们通过业务Dao继承JdbcDaoSupport类的方式,直接将JdbcTemplate交给Spring管理。
代码结构:
resource资源配置文件:

定义pojo Person类:
package demo08.myspring.model.jdbc.pojo;
import java.util.Date;
// POJO对象实体-属于Model层,也是DAO层。简单的Person bean。
// 一般自定义的bean如果是有状态的bean,则不要交给spring容器负责实例化,因为默认实例化的对象是单例,存在非线程安全。
// 建议:自定义的bean作为方法变量进行传递,这种bean尤其见于这些用来保存状态并传输的pojo对象。
public class Person {
    private int id;
    private String name;
    private String sex;
    private int age;
    private Date birthday;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
定义Service接口:
package demo08.myspring.model.jdbc.service;
import demo08.myspring.model.jdbc.pojo.Person;
import java.util.List;
public interface PersonService {
    public abstract String name(Integer id);
    public abstract void insert(Person per);
    public abstract int count();
    public abstract List<Person> list();
}
Service接口实现类:
package demo08.myspring.model.jdbc.service.impl;
import java.util.List;
import demo08.myspring.model.jdbc.dao.PersonDao;
import demo08.myspring.model.jdbc.pojo.Person;
import demo08.myspring.model.jdbc.service.PersonService;
// Service层除了保存dao对象和无状态的bean对象外,不要保存有状态的bean。
public class PersonServiceImpl implements PersonService {
    private PersonDao personDao;
    public PersonDao getPersonDao() {
        return personDao;
    }
    public void setPersonDao(PersonDao personDao) {
        this.personDao = personDao;
    }
    @Override
    public String name(Integer id) {
        return personDao.getPersonName(id);
    }
    @Override
    public void insert(Person per) {
        this.personDao.insertPerson(per);
    }
    @Override
    public int count() {
        return this.personDao.getPersonCount();
    }
    @Override
    public List<Person> list() {
        return this.personDao.listPersons();
    }
}
定义Dao接口:
package demo08.myspring.model.jdbc.dao;
import java.util.List;
import demo08.myspring.model.jdbc.pojo.Person;
// 定义DAO层接口,DAO层主要负责处理数据。
public interface PersonDao {
    // 根据id获得person的姓名
    public abstract String getPersonName(int id);
    // 添加Person对象
    public abstract void insertPerson(Person per);
    // 返回person的总数目
    public abstract int getPersonCount();
    // 返回所有的person对象
    public abstract List<Person> listPersons();
}
定义Dao实现类:通过继承JdbcDaoSupport的方式整个JdbcTemplate
package demo08.myspring.model.jdbc.dao.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import demo08.myspring.model.jdbc.dao.PersonDao;
import demo08.myspring.model.jdbc.pojo.Person;
// spring整合JDBC。
// DAO层接口的实现类:定义的dao实现必须继承JdbcDaoSupport,因为要获取JdbcTemplate模板。
// spring管理jdbc后一切操作通过jdbcTemplate去操作。
// 注意:spring创建的JdbcTemplate模板对象每次返回的都是单例对象,但是使用ThreadLocal来保证Connection对象的线程安全。
// spring整合mybatis或者hibernate后将不再使用JdbcTemplate对象,而是直接使用对mybatis和hibernate的封装对象。
// 在spring中,所有的bean都是默认单例的,不要在service和dao中定义成员变量,避免非线程安全。
public class PersonDaoImpl extends JdbcDaoSupport implements PersonDao {
    // 扩展一个初始化方法,用于创建数据表。
    // spring将jdbc的操作封装成了jdbcTemplate模板对象。
    // 该方法在将当前Dao交给spring容器管理时,通过在配置文件中指定init-method="initDatabase"进行初始化调用。
    public void initDatabase() {
        // 拼接sql语句
        String createTableSql = "create table table_person(id number(12),name varchar(21),age number(12),sex varchar(12),birthday Date)";
        try {
            this.getJdbcTemplate().execute(createTableSql);
        } catch (Exception e) {
            // 一旦抛出异常直接忽略,一般是因为数据表已将存在了。
            ;
        }
    }
    // 插入一条记录
    public void insertPerson(Person per) {
        String sql = "insert into table_person(id,name,sex,age,birthday) values(?,?,?,?,?)";
        this.getJdbcTemplate().update(
                sql,
                new Object[]{per.getId(), per.getName(), per.getSex(),
                        per.getAge(), per.getBirthday()});
    }
    // 根据id号查询姓名。
    public String getPersonName(int id) {
        String sql = "select name from table_person where id = " + id;
        return (String) this.getJdbcTemplate()
                .queryForObject(sql, String.class);
    }
    // 查询总数。
    public int getPersonCount() {
        String sql = "SELECT COUNT(1) FROM TABLE_PERSON";
        return this.getJdbcTemplate().queryForInt(sql);
    }
    public List<Person> listPersons() {
        String sql = "select id,name,sex,age,birthday from table_person";
        List<Map<String, Object>> list = this.getJdbcTemplate().queryForList(
                sql);
        List<Person> personList = new ArrayList<Person>();// 实例化list容器
        for (Map<String, Object> row : list) {
            // 封装成person对象
            Person per = new Person();
            per.setId((Integer) row.get("id"));
            per.setName((String) row.get("name"));
            per.setAge((Integer) row.get("age"));
            per.setSex((String) row.get("sex"));
            per.setBirthday((Date) row.get("birthday"));
            personList.add(per);
        }
        // 返回person的list集合
        return personList;
    }
}
配置如下:
<?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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:redis="http://www.springframework.org/schema/redis"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
        http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis-1.0.xsd">
    <!-- spring整合jdbc,一切操作通过spring的JdbcTemplate对象操作 -->
    <!-- 配置dbcp数据源,此处配置的是dbcp数据源的实现,通过Spring自带的beanFactory进行bean的实例化 -->
    <!-- 执行完bean dataSource的所有方法后执行destroy-method属性指定的方法 -->
    <!-- 此处实例化的是dbcp这个数据源对象 -->
    <!-- 销毁连接池对象时执行close关闭方法 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <!-- 通过property属性注入依赖成员 -->
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url">
            <value>jdbc:oracle:thin:@localhost:1521:orcl</value>
        </property>
        <property name="username" value="oracle" />
        <property name="password" value="oracle" />
    </bean>
    <!-- 一般对于dao对象的实例化采用xml配置的方式 -->
    <!-- 实例化PersonDaoImpl这个bean时,必须先实例化dataSource数据源这个bean,PersonDaoImpl对象实例化好后首先执行的方法是initDatabase() -->
    <bean id="personDaoImpl" class="demo08.myspring.model.jdbc.dao.impl.PersonDaoImpl"
        depends-on="dataSource" init-method="initDatabase">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
    </bean>
    <!-- 实例化service对象 -->
    <bean id="personServiceImpl"
        class="demo08.myspring.model.jdbc.service.impl.PersonServiceImpl">
        <property name="personDao" ref="personDaoImpl" />
    </bean>
</beans>
测试运行:
package demo08.myspring.model.jdbc.run;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import demo00.myspring.common.initconfig.LoadSpringConfigFactory;
import demo08.myspring.model.jdbc.pojo.Person;
import demo08.myspring.model.jdbc.service.PersonService;
public class PersonServiceJunit {
    private ApplicationContext applicationContext;
    private PersonService personService;
    @Before
    public void loadApplicationContext() {
        // 加载spring配置
        applicationContext = LoadSpringConfigFactory.getApplicationContext("spring/demo08-applicationContext-dao.xml");
        // 参数1: bean name/bean id
        // 参数2(可选): 可以指定生成对象类型,如果不填此参数,需进行强转 两种方式都可以获取!
        // PersonDao personDao = applicationContext.getBean("personDaoImpl", PersonDao.class);
        // 不指定参数2则需要强制转换
        personService = (PersonService) applicationContext.getBean("personServiceImpl");
    }
    // 通过JdbcTemplate对象插入数据成功。
    @Test
    public void testInsert() {
        Person per = new Person();
        per.setId(12);
        per.setName("赵二虎");
        per.setSex("男");
        per.setAge(25);
        per.setBirthday(new Date());
        personService.insert(per);
        System.out.println("插入表数据成功...");
    }
    // 查询数据表的总条数。
    @Test
    public void testCount() {
        Integer count = this.personService.count();
        System.out.println("总数为:" + count);
    }
    // 根据id查询目标姓名。
    @Test
    public void queryName() {
        String name = this.personService.name(12);
        if (name == null) {
            System.out.println("目标任务不存在...");
        } else {
            System.out.println("查询到的姓名是:" + name);
        }
    }
}

文档信息

Search

    Table of Contents