为了使 JDBC 更加易于使用, Spring 在 JDBC API 上定义了一个抽象层, 以此创建一个 JDBC 存取框架.java
做为 Spring JDBC 框架的核心, JDBC 模板的设计目的是为不一样类型的 JDBC 操做提供模板方法. 每一个模板方法都能控制整个过程, 并容许覆盖过程当中的特定任务. 经过这种方式, 能够在尽量保留灵活性的状况下, 将数据库存取的工做量降到最低.mysql
如今咱们来介绍一下,各类CRUD可能用到的Spring JDBC的API:web
使用 JdbcTemplate 更新数据库spring
用 sql 语句和参数更新数据库:sql
public int update(String sql, Object... args) throws DataAccessException
批量更新数据库: 数据库
public int[] batchUpdate(String sql, List<Object[]> batchArgs) throws DataAccessException
使用 JdbcTemplate 查询数据库apache
查询单行: 安全
public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException
查询多行:mvc
public <T> List<T> query(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException
单值查询:
app
public <T> T queryForObject(String sql, Class<T> requiredType) throws DataAccessException
使用Spring JDBC的好处——简化 JDBC 模板查询
每次使用都建立一个 JdbcTemplate 的新实例, 这种作法效率很低下.
JdbcTemplate 类被设计成为线程安全的, 因此能够再 IOC 容器中声明它的单个实例, 并将这个实例注入到全部的 DAO 实例中.
JdbcTemplate 也利用了 Java 1.5 的特定(自动装箱, 泛型, 可变长度等)来简化开发
Spring JDBC 框架还提供了一个 JdbcDaoSupport 类来简化 DAO 实现. 该类声明了 jdbcTemplate 属性, 它能够从 IOC 容器中注入, 或者自动从数据源中建立.
好咱们仍是给出例子吧。
一开始,咱们给出全部咱们须要的spring jdbc所须要的jar的pom,宁多勿少。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.happBKs.spring</groupId> <artifactId>jdbcSpring</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>jdbcSpring</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.1.7.RELEASE</version> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.36</version> </dependency> </dependencies> </project>
首先咱们须要创建一个数据库springjdbc。而后建立两张表employee和department。
而后,咱们插入几组数据:
department:
employee:
以后,咱们定义相关的bean类:
package com.happBKs.spring.jdbcSpring; public class DepartmentBean { String id; String departmentName; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } public DepartmentBean(String id, String departmentName) { super(); this.id = id; this.departmentName = departmentName; } public DepartmentBean() { super(); // TODO Auto-generated constructor stub } @Override public String toString() { return "DepartmentBean [id=" + id + ", departmentName=" + departmentName + "]"; } }
package com.happBKs.spring.jdbcSpring; public class EmployeeBean { Integer id; String lastName; String email; DepartmentBean department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public DepartmentBean getDepartment() { return department; } public void setDepartment(DepartmentBean department) { this.department = department; } public EmployeeBean(Integer id, String lastName, String email, DepartmentBean department) { super(); this.id = id; this.lastName = lastName; this.email = email; this.department = department; } public EmployeeBean() { super(); // TODO Auto-generated constructor stub } @Override public String toString() { return "EmployeeBean [id=" + id + ", lastName=" + lastName + ", email=" + email + ", department=" + department + "]"; } }
注意,这里咱们预想把dept_id对应改为一个成员DepartmentBean类型的对象。看看是否能够用Spring Jdbc实现。
而后,咱们来定义Spring IOC容器配置文件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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd 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-4.1.xsd"> <!-- 自动扫描的包 --> <context:component-scan base-package="com.happBKs.spring.jdbcSpring"></context:component-scan> <!-- 导入资源文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置c3p0数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 配置jdbc模板类 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
以及db.properties:
jdbc.user=root jdbc.password= jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql:///springjdbc?useUnicode=true&characterEncoding=utf8 jdbc.initPoolSize=5 jdbc.maxPoolSize=10
好,下面咱们尝试更新操做和查询操做:
package com.happBKs.spring.jdbcSpring; import static org.junit.Assert.*; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; public class JDBCTest { ApplicationContext ctx=null; JdbcTemplate jdbcTemplate; { ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); jdbcTemplate=(JdbcTemplate)ctx.getBean("jdbcTemplate"); } @Test public void test() throws SQLException { DataSource dataSource=ctx.getBean(DataSource.class); //DataSource dataSource=(DataSource)ctx.getBean("dataSource"); System.out.println(dataSource.getConnection()); } /* * 执行update、 insert、delete */ @Test public void testUpdate(){ String sql="Update employee set last_name=? where id=?"; jdbcTemplate.update(sql,"姚鼓励",5); } /* * 执行批量更新、插入、删除 */ @Test public void testBatchUpdate() { String sql="insert employee(last_name,email,dept_id) values(?,?,?)"; List<Object[]> batchArgs=new ArrayList<Object[]>(); batchArgs.add(new Object[]{"临时工1","1@qq.com",4}); batchArgs.add(new Object[]{"临时工2","2@qq.com",4}); batchArgs.add(new Object[]{"临时工3","3@qq.com",4}); jdbcTemplate.batchUpdate(sql, batchArgs); } /* * 从数据库中得到一条记录,实际获得对应的一个对象 * 注意:应该用的方法是<EmployeeBean> EmployeeBean org.springframework.jdbc.core.JdbcTemplate.queryForObject(String sql, RowMapper<EmployeeBean> rowMapper, Object... args) throws DataAccessException * 而不是<EmployeeBean> EmployeeBean org.springframework.jdbc.core.JdbcTemplate.queryForObject(String sql, Class<EmployeeBean> requiredType, Object... args) throws DataAccessException * * 1. 其中RowMapper指定如何映射结果集的行,经常使用的实现类为BeanPropertyRowMapper * 这里插一句,当之后应用某个类的方法中有参数是接口类型时,咱们须要建立一个该接口的实现类对象,可是不知道具体的实现类有哪些,这时候能够用Ctrl+T来查看该接口的实现类的树状图 * 2. 使用SQL语句中查询字段的别名来完成数据库表的字段名与类对象的属性名之间的映射,例如这里的last_name lastName * 3. 不支持级联属性。即不支持String sql="select id,last_name lastName, email, dept_id as \"department.id\" from employee where id=?"; * 由于JdbcTemplate到底只是一个jdbc工具,而不是一个ORM框架 */ @Test public void testQueryForObject(){ String sql="select id,last_name lastName, email from employee where id=?"; RowMapper<EmployeeBean> rowMapper=new BeanPropertyRowMapper<EmployeeBean>(EmployeeBean.class); EmployeeBean employee=jdbcTemplate.queryForObject(sql, rowMapper,1); System.out.println(employee); } @Test public void testQueryForList(){ String sql="select id,last_name lastName, email from employee where id>?"; RowMapper<EmployeeBean> rowMapper=new BeanPropertyRowMapper<EmployeeBean>(EmployeeBean.class); List<EmployeeBean> employeeList=jdbcTemplate.query(sql, rowMapper,5); System.out.println(employeeList); } /* * 获取单个列的值,能够用SQL中的sum、count、avg函数 */ @Test public void testQueryForObjectField(){ String sql="select count(id) from employee"; int count=jdbcTemplate.queryForObject(sql,Integer.class); System.out.println(count); } }
这里,输出的结果,我就不一一罗列,只挑几个吧:
void testBatchUpdate() 的结果:
void testQueryForObject()的结果:
EmployeeBean [id=1, lastName=王会计, email=wangkuaiji@126.com, department=null]
好吧,spring jdbc毕竟仍是jdbc不是orm,因此级联对象时空的。
那么,咱们在实际开发时应该如何使用Spring JDBC编写DAO模块呢?
直接给代码吧。
package com.happBKs.spring.jdbcSpring; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; @Repository public class EmployeeDAO { @Autowired private JdbcTemplate jdbcTemplate; public EmployeeBean get(int id) { String sql="select id,last_name lastName, email from employee where id=?"; RowMapper<EmployeeBean> rowMapper=new BeanPropertyRowMapper<EmployeeBean>(EmployeeBean.class); EmployeeBean employee=jdbcTemplate.queryForObject(sql, rowMapper,id); return employee; } }
测试代码:
EmployeeDAO employeeDAO; { employeeDAO=ctx.getBean(EmployeeDAO.class); } @Test public void testEmployeeDAO(){ System.out.println(employeeDAO.get(1)); }
以上咱们介绍的都是应用的JdbcTemplate类的对象建立,来帮助咱们完成JDBC的各个功能。正如本文副标题所提到的,还有另外一个类和另外一种用法能够帮助咱们实现这样的功能,那就是JdbcDaoSupport。
这里,咱们定义DepartmentDAO类用这种方式实现,来看看吧:
package com.happBKs.spring.jdbcSpring; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.stereotype.Repository; /* * 不推荐使用JdbcDaoSupport,而推荐直接使用JdbcTemplate做为DAO类成员变量的方式 */ @Repository public class DepartmentDAO extends JdbcDaoSupport { @Autowired public void setDataSource2(DataSource dataSource){ setDataSource(dataSource);//public final void setDataSource(DataSource dataSource) { } //注意:由于JdbcDaoSupport的setDataSource方法是final的因此不能重写, //这里采用了一种变通的方法,新设立了一个域dataSource2,实际用到了JdbcDaoSupport的setDataSource方法 public DepartmentBean get(Integer id) { String sql = ""; RowMapper<DepartmentBean> rowMapper = new BeanPropertyRowMapper<DepartmentBean>( DepartmentBean.class); DepartmentBean department = getJdbcTemplate().queryForObject(sql, rowMapper, id); return department; } }
测试代码:
DepartmentDAO departmentDAO; { departmentDAO = ctx.getBean(DepartmentDAO.class); } @Test public void testDepartmentDAO(){ System.out.println(departmentDAO.get(1)); }