Spring JdbcTemplate增强:JdbcTemplateTool

jopen 10年前

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.java

import 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.java

import 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. 启动!

    运行测试用例,等待绿色条。然后去数据库会看到多了一条记录 :

id name join_date age
4 billy 2014-09-24 22:51:20 33

高级教程

    以下是各个方法的详细介绍

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就可以了。

项目主页:http://www.open-open.com/lib/view/home/1411716502234