Spring JdbcTemplate详解
一.简介
1.Spring JdbcTemplate简介
- Spring对数据库的操作在jdbc上面做了深层次的封装,spring框架的ioc帮我们创建JdbcTemplate对象,使用spring的di帮我们完成属性注入,可以把DataSource注册到JdbcTemplate之中。
- JdbcTemplate位于spring-jdbc-4.2.4.RELEASE.jar中。其全限定命名为org.springframework.jdbc.core.JdbcTemplate。
- JdbcTemlate还需一个这个包spring-tx-4.2.4.RELEASE.jar,包含了一下事务和异常控制
2.Spring JdbcTemplate主要方法
- execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
- update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;
- batchUpdate方法用于执行批处理相关语句;
- query方法及queryForXXX方法:用于执行查询相关语句;
- call方法:用于执行存储过程、函数相关语句。
3.Spring JdbcTemplate作用
- JdbcUtil工具类:自己封装的
好处是方便对数据库进行增删查改操作,模板化编程(sql+参数) - JdbcTemplate作用:spring框架为我们写好的
好处是模板化编程(sql+参数)
4.Spring RowMapper封装结果集接口
- spring 中的 RowMapper
- spring中的RowMapper接口可以将查询结果集中的每一行数据封装成实体类
- RowMapper接口中包含方法mapRow(ResultSet rs, int rowNum);
- JdbcTemplate执行query方法或者调用存储过程时,需要写一个实体实现类UserRowMapper来实现RowMapper接口,重写mapRow方法来映射的每一行结果集的数据
5.NamedParameterJdbcTemplate支持具名参数
- 在经典的 JDBC 用法中,SQL 参数是用占位符 ? 表示,并且受到位置的限制.
定位参数的问题在于,一旦参数的顺序发生变化,就必须改变参数绑定 - 在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数
具名参数: SQL 按名称(以冒号开头)而不是按位置进行指定.
具名参数更易于维护, 也提升了可读性
具名参数由框架类在运行时用占位符取代
具名参数只在 NamedParameterJdbcTemplate 中得到支持。
NamedParameterJdbcTemplate可以使用全部jdbcTemplate方法
二.普通方法使用JdbcTemplate
package com.jp.jdbc;
import java.beans.PropertyVetoException;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class Demo {
@Test
public void testJdbcTemplate() throws PropertyVetoException{
//创建连接池对象
ComboPooledDataSource ds=new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/mybase1");
ds.setUser("root");
ds.setPassword("root123");
//JdbcTemplate jt=new JdbcTemplate(ds);
JdbcTemplate jdbcTemplate=new JdbcTemplate();
jdbcTemplate.setDataSource(ds);
String sql="insert into user values(null,?,?);";
int lines = jdbcTemplate.update(sql,"李四",18);
System.out.println(lines);
}
}
三.Spring集成JdbcTemplate
- 将JdbcTemplate注入到UserDaoImpl里面并提供set方法,以便使用JdbcTemplate工具类的方法
- 将UserDao注入到UserServiceImpl里面,并且提供set方法,以便使用UserDaoImpl的方法
1.applicationContext.xml文件
- 要写到src根目录下,才能被读到
- spring框架的ioc帮我们创建JdbcTemplate对象和DataSource对象
- spring框架的di帮我们完成属性注入
将driverClass,jdbcUrl,user,password注入到DataSource中
将DataSource注入到JdbcTemplate中
<?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/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 name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybase1"/>
<property name="user" value="root"/>
<property name="password" value="root123"/>
</bean>
<!-- JdbcTemplate模板对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- dao切面 -->
<bean id="userDao" class="com.jp.dao.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- service切面 -->
<bean id="userService" class="com.jp.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
2.测试JdbcTemplate工具类
package com.jp.jdbc;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
public class Demo {
@Test
public void testSpringJdbcTemplate(){
//加载spring的xml配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate jdbcTemplate=(JdbcTemplate)ac.getBean("jdbcTemplate");
String sql="insert into user values(null,?,?);";
int lines = jdbcTemplate.update(sql,"小龙人",28);
System.out.println(lines);
}
}
3.创建数据库
create table user(
id int(10) primary key not null auto_increment,
name varchar(20),
age int(10)
);
insert into user values(null,'zs',18);
update user set name='小花花',age=28 where id=1;
delete from user where id=1;
select * from user where id=1;
select * from user;
select * from user where id in(1,2);
select * from user where id=1 or id=2;
4.数据库对应实体类
package com.jp.domain;
import java.io.Serializable;
public class User implements Serializable{
//生成序列号,方便对象序列化,方便传输
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public User(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
5.UserRowMapper封装查询结果集
实现RowMapper接口,重写mapRow方法
package com.jp.rowmapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.jp.domain.User;
public class UserRowMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(rs.getInt(1));
user.setName(rs.getString(2));
user.setAge(rs.getInt(3));
return user;
}
}
6.dao数据库访问层接口
com.jp.dao.UserDao
package com.jp.dao;
import java.util.List;
import com.jp.domain.User;
public interface UserDao {
//保存用户
public void save(User user);
//根据主键修改
public void update(int id,User user);
//根据主键删除
public void delete(int id);
//根据一个主键查询一个User
public User getUser(int id);
//根据多个主键查询多个User
public List<User> getUserList(int[] ids);
//查询所有的用户
public List<User> getUserList();
}
7.dao数据库访问层实现类
com.jp.dao.UserDaoImpl
package com.jp.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import com.jp.domain.User;
import com.jp.rowmapper.UserRowMapper;
public class UserDaoImpl implements UserDao {
//实现面向接口编程,进行数据的查询
//使用配置文件中的JDBC模板
private JdbcTemplate jdbcTemplate;
//提供JdbcTemplate的set方法,方便以后注入JdbcTemplate
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void save(User user) {
String sql="insert into user values(null,?,?)";
jdbcTemplate.update(sql,user.getName(),user.getAge());
}
@Override
public void update(int id, User user) {
String sql="update user set name=?,age=? where id=?";
jdbcTemplate.update(sql,user.getName(),user.getAge(),id);
}
@Override
public void delete(int id) {
String sql="delete from user where id=?";
jdbcTemplate.update(sql,id);
}
@Override
public User getUser(int id) {
String sql="select * from user where id=?";
//RowMapper中就只有一个mapRow方法,可以使用匿名内部类
User user = jdbcTemplate.queryForObject(sql, new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(rs.getInt(1));
user.setName(rs.getString(2));
user.setAge(rs.getInt(3));
return user;
}
}, id);
return user;
}
@Override
public List<User> getUserList(int[] ids) {
String sql="select * from user where id in(:ids)";//使用in,而且不需要占位符,以冒号:开头
Map<String,Object> paramMap=new HashMap<String,Object>();
//将ids数组转变成一个集合
List list=new ArrayList();
for(int i=0;i<ids.length;i++){
list.add(ids[i]);
}
paramMap.put("ids", list);
NamedParameterJdbcTemplate npj=new NamedParameterJdbcTemplate(jdbcTemplate.getDataSource());
//npj.query(sql, paramMap, rowMapper);
List<User> userList = npj.query(sql, paramMap, new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(rs.getInt(1));
user.setName(rs.getString(2));
user.setAge(rs.getInt(3));
return user;
}
});
return userList;
}
/*@Override
public List<User> getUserList(int[] ids) {
//String sql="select * from user where id=? or id=?";
//由于id值不确定,所以sql语句要进行拼接,由于第一个id已经拼接了,所以ids.length-1
StringBuilder sb=new StringBuilder();
sb.append("select * from user where id=?");
for(int i=0;i<ids.length-1;i++){
sb.append(" or id=?");
}
//ids是int类型的数组,而mapRow需要传的是Object类型的数组参数
Integer[] in=new Integer[ids.length];
for(int i=0;i<ids.length;i++){
in[i]=ids[i];
}
Object[] args=in;
List<User> userList = jdbcTemplate.query(sb.toString(),args, new RowMapper<User>(){
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user=new User();
user.setId(rs.getInt(1));
user.setName(rs.getString(2));
user.setAge(rs.getInt(3));
return user;
}
});
return userList;
}*/
@Override
public List<User> getUserList() {
//在开发中*最好不用,有几列就写几列
String sql="select * from user";
return jdbcTemplate.query(sql, new UserRowMapper());
}
}
8.service逻辑处理层接口
com.jp.service.UserService
package com.jp.service;
import java.util.List;
import com.jp.domain.User;
public interface UserService {
//保存用户
public void save(User user);
//根据主键修改
public void update(int id,User user);
//根据主键删除
public void delete(int id);
//根据一个主键查询一个User
public User getUser(int id);
//根据多个主键查询多个User
public List<User> getUserList(int[] ids);
//查询所有的用户
public List<User> getUserList();
}
9.service逻辑处理层接口实现类
com.jp.service.UserServiceImpl
package com.jp.service;
import java.util.List;
import com.jp.dao.UserDao;
import com.jp.domain.User;
public class UserServiceImpl implements UserService {
//实现面向接口编程,进行数据的校验
//service层面向接口,将来注入哪个实现类就用哪个实现类
private UserDao userDao;
//提供userDao的set方法,以便以后注入userDao
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save(User user) {
userDao.save(user);
}
@Override
public void update(int id, User user) {
userDao.update(id, user);
}
@Override
public void delete(int id) {
userDao.delete(id);
}
@Override
public User getUser(int id) {
return userDao.getUser(id);
}
@Override
public List<User> getUserList(int[] ids) {
return userDao.getUserList(ids);
}
@Override
public List<User> getUserList() {
return userDao.getUserList();
}
}
10.测试类
package com.jp.jdbc;
import java.util.List;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.jp.domain.User;
import com.jp.service.UserService;
public class UserServiceTest {
@Test
public void tsetSave(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)ac.getBean("userService");
//模拟数据
User user=new User();
user.setName("张安");
user.setAge(18);
userService.save(user);
}
@Test
public void testUpdate(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)ac.getBean("userService");
//模拟数据
User user=new User();
user.setName("咔咔");
user.setAge(20);
int id=3;
userService.update(id,user);
}
@Test
public void testDelete(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)ac.getBean("userService");
//模拟数据
int id=3;
userService.delete(id);
}
@Test
public void testGetUserById(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)ac.getBean("userService");
//模拟数据
int id=1;
User user = userService.getUser(id);
System.out.println(user.getName());
}
@Test
public void testGetUserListByIds(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)ac.getBean("userService");
//模拟数据
int[] ids={1,2};
List<User> userList= userService.getUserList(ids);
System.out.println(userList.size());
}
@Test
public void testGetUserList(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService=(UserService)ac.getBean("userService");
//模拟数据
List<User> userList = userService.getUserList();
System.out.println(userList.size());
}
}