Spring JdbcTemplate 简化 JDBC

spring的JdbcTemplate是对jdbc的简单封装,旨在简化jdbc的操作和避免一些jdbc易发的问题,典型使用方式:

因为 JdbcTemplate 类需要一个数据源 DataSource ,可以通过注入或构造方法的方式传入进去,下面是一个完整的spring注入方式实现的JdbcTemplate

spring的配置文件 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@168.1.50.20:1522:orcl"/>
        <property name="username" value="scott"/>
        <property name="password" value="scott"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource">
            <ref bean="myDataSource"/>
        </property>
    </bean>

    <bean id="testDAO" class="com.test.spring.TestJdbcTemplate">
        <property name="jdbcT">
            <ref bean="jdbcTemplate"/>
        </property>
    </bean>

</beans>
里面声明了一个DataSource,声明了一个 JdbcTemplate并引用了数据源,testDAO是自己的业务bean,并且注入进去了一个 JdbcTemplate到jdbcT属性上面,java代码:
package com.test.spring;

import com.test.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class TestJdbcTemplate {

    private JdbcTemplate jdbcT;

    public void setJdbcT(JdbcTemplate jdbcT) {
        this.jdbcT = jdbcT;
    }

    private static ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

    public static Object getBean(String beanName) {
        return ctx.getBean(beanName);
    }

    public static void main(String[] args) {
        TestJdbcTemplate testDAO = (TestJdbcTemplate) getBean("testDAO");
        testDAO.addUser();
        testDAO.findALL();
    }

    public void addUser() {
        String sql = "insert into student VALUES ('userid', 'username')";
        jdbcT.update(sql);
    }

    public void findALL() {
        String sql = "select * from student";
        List list = jdbcT.queryForList(sql);
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Map<String, String> dataMap = (Map) iterator.next();
            User user = new User();
            user.setId(dataMap.get("ID"));
            user.setName(dataMap.get("NAME"));
            System.out.println(user);
        }
    }

    public int delete(int bid) {
        String sql = "delete from DeptInfo where bid =?";
        return jdbcT.update(sql, new Object[]{bid});
    }
}
package com.test;

public class User {
    private String id;
    private String name;

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
上面就完成了,当然我么也可以不需要配置注入的方式直接使用 JdbcTemplate,它其实就是一个普通的类,构造方法可以传入一个数据源,如我们可以这么写
JdbcTemplate jt= new JdbcTemplate(new MyDataSource(xxx,xxx));
然后就可以使用了,如果是spring配置文件了定义了一个的话,就可以直接使用 
JdbcTemplate jt= (JdbcTemplate)ApplicationContext.getBean("jdbcTemplate")
如果spring的配置文件中只有数据源定义的话,也可以先获取注入的数据源在构造JdbcTemplate,如
JdbcTemplate jt= new JdbcTemplate((DataSource)ApplicationContext.getBean("myDataSource"));
方式有很多,其目的就是要获取到一个JdbcTemplate的实例,JdbcTemplate提供了很多方便的操作jdbc的api:如execute、query、queryForObject、queryForXXX等,
其中queryForObject可以自动将sql查询结果转换为对象,上面的java例子我们接收到的是一个Map,然后通过map.get("字段名")的方式手工地赋值到new 出来的User对象里,
而queryForObject可以自动完成这个过程,他默认情况下根据数据库字段名和类的属性的对应关系赋值,如果数据库表的字段名和类的属性不对应,也可以通过 RowMapper 接口定制映射过程。
此接口只有一个抽象方法:Object mapRow(ResultSet rs, int rowNum) throws SQLException;很好理解,实现过程就是new出来一个对象,然后从ResultSet中get出需要的字段赋值到对象里就好了
好上面例子中的Map中获取数据赋值到对象是一样的,只不过spring做了一些抽象而已,我们只需要写一个这样的映射类,所有的映射操作就不用自己写了,查询的时候指定下这个映射类就ok。

虽然JdbcTemplate简化了jdbc的操作,但不是一个orm工具,我们仍然需要自己写sql,当然这也许是他比hibernate更灵活的地方,另外JdbcTemplate只是spring自己搞出来的一套东西,不是jee的标准,它依赖spring的api,这样就不利于我们的程序移植,而hibernate实现了JPA规范,JPA规范可以让我们编写不依赖任何特定实现的程序,这样应用程序可以很容器切换到其他实现技术而不仅限与spring或hibernate,所以我们编程应该遵循规范,尽量避免使用私有的或不规范的API。

Spring 出品的 JdbcTemplate 对于不想使用hibernate或者ibatis那样需要大量学习成本而且还想获得对象化的人来说是很好用的。但是 JdbcTemplate还是有很多不足之处或者说是缺点。比如你没法像hibernate那样直接传一个对象给它让他拆分成sql并保存起来,当然这也是可以理解的,毕竟它并没有要求你去写 hbm.xml 文件所以无法知道你哪些字段要映射,哪些不要等等。又比如JdbcTemplate 可以帮忙把一个查询结果传化为一个对象列表,但是你需要查阅一些资料才知道要用 BeanPropertyRowMapper 。如果下次要用的时候又忘记了这个类,又要查一次或者翻以前的代码来看,其实完全可以提供一个方法直接传一个PO类进去自动创建BeanPropertyRowMapper 。基于以上的一些不足之处,我建立了 JdbcTemplateTool 它有以下特性:把查询结果转换为PO列表,不需要调用BeanPropertyRowMapper传一条统计sql比如 aselect count(1) from table可以直接返回一个数字作为结果,不需要自己实现中间步骤。可以直接把一个PO类存到数据库通过PO类和一个id可以获取到该对象通过PO类可以直接update数据库记录不需要实现 BatchPreparedStatementSetter, 就可以批量update通过一个对PO对象删除对应的数据库记录依然可以使用原始的JdbcTemplate目前只在mysql上测试.Maven 依赖<dependency>   <groupId>org.crazycake</groupId>   <artifactId>jdbctemplatetool</artifactId>   <version>1.0.4-RELEASE</version> </dependency>快速开始STEP 1. 创建一个maven项目    创建一个maven项目叫testjtt. 添加jdbctemplatetool 依赖到pom.xml. 再添加以下依赖到 pom.xml.<dependency>   <groupId>junit</groupId>   <artifactId>junit</artifactId>   <version>4.11</version>   <scope>test</scope> </dependency> <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-context</artifactId>     <version>3.2.2.RELEASE</version>     <scope>test</scope> </dependency> <dependency>     <groupId>com.mchange</groupId>     <artifactId>c3p0</artifactId>     <version>0.9.2.1</version>     <scope>test</scope> </dependency> <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>5.1.19</version>     <scope>test</scope> </dependency> <dependency>     <groupId>org.springframework</groupId>     <artifactId>spring-test</artifactId>     <version>3.2.2.RELEASE</version>     <scope>test</scope> </dependency>最好使用 1.6 jdk. 我并没有在 1.5 下测试STEP 2. 创建测试数据库    创建一个测试的数据库叫jtt_test创建一个用户travis不要分配密码. 赋予jtt_test的权限给travis.CREATE USER 'travis'@'%' IDENTIFIED BY ''; GRANT ALL ON jtt_test.* TO 'travis'@'%'; flush privileges;创建一张表employee插入一些测试数据.DROP TABLE IF EXISTS `employee`; CREATE TABLE `employee` (   `id` int(11) NOT NULL,   `name` varchar(300) NOT NULL,   `join_date` datetime NOT NULL,   `age` int(11) NOT NULL,   PRIMARY KEY  (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `employee` */ insert  into `employee`(`id`,`name`,`join_date`,`age`) values (1,'jack','2014-09-22 00:00:00',23),(2,'ted','2014-08-30 00:00:00',25),(3,'jim','2014-06-22 00:00:00',33);STEP 3. 配置一下spring    在test文件夹下创建resources文件夹. 添加resources到 source folder 修改输出为target/test-classes创建spring.xml在 test/resources 里面<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">     <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">         <property name="jdbcUrl"><value>jdbc:mysql://localhost:3306/jtt_test?characterEncoding=utf8</value></property>         <property name="driverClass"><value>com.mysql.jdbc.Driver</value></property>         <property name="user"><value>travis</value></property>         <property name="password"><value></value></property>     </bean>     <bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate">             <property name = "dataSource" ref="dataSource"/>        </bean>     <bean id="jdbcTemplateTool" class="org.crazycake.jdbcTemplateTool.JdbcTemplateTool">         <property name = "jdbcTemplate" ref="jdbcTemplate" />     </bean> </beans>STEP 4. 创建PO类    创建Employee.javaimport java.sql.Timestamp; import javax.persistence.Id; public class Employee {     private Integer id;     private String name;     private Timestamp joinDate;     private Integer age;     @Id     public Integer getId() {         return id;     }     public void setId(Integer id) {         this.id = id;     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public Timestamp getJoinDate() {         return joinDate;     }     public void setJoinDate(Timestamp joinDate) {         this.joinDate = joinDate;     }     public Integer getAge() {         return age;     }     public void setAge(Integer age) {         this.age = age;     } }STEP 5. 创建测试用例    创建HelloJTTTest.javaimport static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import java.util.List; import org.crazycake.jdbcTemplateTool.JdbcTemplateTool; import org.junit.Test; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; @ContextConfiguration(locations={"classpath:spring.xml"}) public class HelloJTTTest extends AbstractJUnit4SpringContextTests{     @Test     public void testSave(){         JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);         Employee e = new Employee();         e.setId(4);         e.setName("billy");         Date now = new Date();         e.setJoinDate(new Timestamp(now.getTime()));         e.setAge(33);         try {             jtt.save(e);         } catch (Exception e1) {             e1.printStackTrace();         }     } }STEP 6. 启动!    运行测试用例,等待绿色条。然后去数据库看到多了一条记录 :idnamejoin_dateage4billy2014-09-24 22:51:2033高级教程    以下是各个方法的详细介绍list把查询结果转换为PO列表,不需要调用BeanPropertyRowMapper。 自动根据数据库的列将下划线转为驼峰命名规则映射类的属性.@Test public void testList(){     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     List<Employee> es = jtt.list("select * from employee where age < ? order by id desc", new Object[]{30}, Employee.class);     assertThat(new Integer(es.size()),is(2));     assertThat(es.get(1).getName(),is("jack")); }count    传一条统计sql比如 aselect count(1) from table可以直接返回一个数字作为结果,不需要自己实现中间步骤。@Test public void testCount() throws IOException, SQLException {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     int total = jtt.count("select count(1) from employee", null);     assertThat(total,is(4));     }save可以直接把一个PO类存到数据库。如果你不想把某个列映射为数据库字段可以使用 @Trasient 注解在getter上public class Student {     private Integer id;     private String name;     private String nothing;     public Integer getId() {         return id;     }     public void setId(Integer id) {         this.id = id;     }     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     @Transient     public String getNothing() {         return nothing;     }     public void setNothing(String nothing) {         this.nothing = nothing;     } }这个字段被跳过@Test public void testSave() throws Exception {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Student s = new Student();     s.setName("michael");     s.setNothing("nothing");     jtt.save(s); }get    通过PO类和一个id可以获取到该对象。但是前提是需要在主键的getter上标上 @Id 注解@Id public Integer getId() {     return id; }例子@Test public void testGet() throws NoIdAnnotationFoundException, NoColumnAnnotationFoundException, IOException, SQLException {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Employee e = jtt.get(Employee.class, 3);     assertThat(e.getName(),is("jim")); }update    自动根据PO类更数据库. 记得增加@Id.@Test public void testUpdate() throws Exception {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Employee e = jtt.get(Employee.class, 1);     e.setAge(23);     jtt.update(e); }batchUpdate    批量更@Test public void testBatchUpdate() throws SQLException, IOException {     build();     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     List<Object[]> params = new ArrayList<Object[]>();     Object[] p1 = new Object[]{23,"jack"};     params.add(p1);     Object[] p2 = new Object[]{29,"tim"};     params.add(p2);     jtt.batchUpdate("update employee set age = ? where name = ?", params); }delete    删除数据库对象@Test public void testDelete() throws Exception {     JdbcTemplateTool jtt = super.applicationContext.getBean("jdbcTemplateTool",JdbcTemplateTool.class);     Employee e = new Employee();     e.setId(1);     jtt.delete(e); }getJdbcTemplate    你依然可以使用原始的JdbcTemplate. 调用JdbcTemplateTool.getJdbcTemplate()to getJdbcTemplate就可以了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值