Spring学习目录
下一篇:(十四)Spring之回顾代理模式
JdbcTemplate是Spring提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码。
当然,也可以不用,可以让Spring集成其它的ORM框架,例如:MyBatis、Hibernate等。
先使用JdbcTemplate完成增删改查。
环境
数据库表:t_user
初始数据:
spring6里程碑版本的仓库
依赖:spring context依赖、junit依赖、log4j2依赖
log4j2.xml文件放到类路径下。
使用JdbcTemplate需要再引入spring-jdbc依赖,以及mysql驱动:
<!--spring jdbc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.0-M2</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
准备实体类User:
public class User {
private Integer id;
private String loginName;
private String loginPwd;
public User() {
}
public User(Integer id, String loginName, String loginPwd) {
this.id = id;
this.loginName = loginName;
this.loginPwd = loginPwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", loginName='" + loginName + '\'' +
", loginPwd='" + loginPwd + '\'' +
'}';
}
public void setId(Integer id) {
this.id = id;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public void setLoginPwd(String loginPwd) {
this.loginPwd = loginPwd;
}
}
编写Spring配置文件:创建spring.xml
JdbcTemplate是Spring提供好的类,这类的完整类名是:org.springframework.jdbc.core.JdbcTemplate
直接将这个类配置到Spring配置文件中,纳入Bean管理即可。
<?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.xsd">
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"></bean>
</beans>
通过源码我们可以看到,JdbcTemplate是继承jdbcAccessor,而jdbcAccessor有一个DataSource属性,这个属性是数据源,连接数据库需要Connection对象,而生成Connection对象是数据源负责的。所以我们需要给JdbcTemplate设置数据源属性。
所有的数据源都是要实现javax.sql.DataSource接口的。这个数据源可以自己写一个,也可以用写好的,比如:阿里巴巴的德鲁伊连接池,c3p0,dbcp等。我们这里自己先手写一个数据源。
创建数据源MyDataSource,实现DataSource接口,默认实现里面的方法:
public class MyDataSource implements DataSource {
private String driver;
private String url;
private String username;
private String password;
public void setDriver(String driver) {
this.driver = driver;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public Connection getConnection() throws SQLException {
Connection connection = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url,username,password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
写完数据源,我们需要把这个数据源传递给JdbcTemplate。因为JdbcTemplate中有一个DataSource属性:
<?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.xsd">
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--这里需要数据源,也可以集成其他数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean>
<!--配置自己的数据源-->
<bean id="myDataSource" class="com.jdbctemplate.bean.MyDataSource">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydbtest"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
测试JdbcTemplate是否已设置好:
@Test
public void testJdbc(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
System.out.println(jdbcTemplate);
System.out.println(jdbcTemplate.getDataSource());
}
环境准备完成
新增、删除与修改数据
在JdbcTemplate当中,insert,delete,update语句,都是调用update方法。
update方法两个参数
- 第一个参数是传sql语句
- 第二个参数args是可变长参数,有几个问号,传几个值
新增
测试程序:
@Test
public void testInsert(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "insert into t_user(loginName,loginPwd) values(?,?)";
int count = jdbcTemplate.update(sql, "张三", "123456");
System.out.println(count);
}
新增成功,数据改变:
修改
测试程序:
@Test
public void testUpdate(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "update t_user set loginName = ? , loginPwd = ? where id = ?";
int count = jdbcTemplate.update(sql, "李四", "654321",7);
System.out.println(count);
}
修改成功,数据改变:
删除
测试程序:
@Test
public void testDelete(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "delete from t_user where id = ?";
int count = jdbcTemplate.update(sql, 7);
System.out.println(count);
}
删除成功。数据改变:
查询一个
查询一个使用queryForObject方法,三个参数:
- 第一个参数:sql语句
- 第二个参数:映射器对象,在构造方法中指定映射的对象类型。
- 第三个参数:可变长参数,给sql语句的占位符问号传值。
查询一个对象
测试程序:
@Test
public void testSelectOne(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "select * from t_user where id = ?";
User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), 2);
System.out.println(user);
}
查询一个值
有时候查询是一个值,例如总记录条数:
测试程序:
@Test
public void testSelectOneValue(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行select
String sql = "select count(1) from t_user";
Integer count = jdbcTemplate.queryForObject(sql, int.class); // 这里用Integer.class也可以
System.out.println("总记录条数:" + count);
}
查询多个对象
查询结构返回多个对象,使用query方法,与queryForObject方法用法差不多,只是query方法的返回值是一个List集合
测试程序:
@Test
public void testSelectAll(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 执行select
String sql = "select * from t_user";
//查询多个是调用query方法。
List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
System.out.println(users);
}
批量操作
批量添加、批量修改、批量删除都是使用batchUpdate方法,该方法返回值是一个int集合,表示操作的数据成功与否,有两个参数:
- 第一个参数:sql语句
- 第二个参数:需要操作的list集合,主要给问号赋值
批量添加
测试程序:
@Test
public void testAddBatch(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 批量添加
String sql = "insert into t_user(id,loginName,loginPwd) values(?,?,?)";
//这里需要注意的是问号顺序
Object[] objs1 = {null, "张三", "123"};
Object[] objs2 = {null, "李四", "321"};
Object[] objs3 = {null, "王五", "231"};
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);
int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));
}
运行成功,数据改变:
批量修改
测试程序:
@Test
public void testUpdateBatch(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 批量修改
String sql = "update t_user set loginName = ?, loginPwd = ? where id = ?";
//这里需要注意的是问号顺序
Object[] objs1 = {"张三11", "546", 8};
Object[] objs2 = {"李四22", "654", 9};
Object[] objs3 = {"王五33", "456", 10};
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);
int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));
}
运行成功,数据改变:
批量删除
测试程序:
@Test
public void testDeleteBatch(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
// 批量删除
String sql = "delete from t_user where id = ?";
Object[] objs1 = {8};
Object[] objs2 = {9};
Object[] objs3 = {10};
List<Object[]> list = new ArrayList<>();
list.add(objs1);
list.add(objs2);
list.add(objs3);
int[] count = jdbcTemplate.batchUpdate(sql, list);
System.out.println(Arrays.toString(count));
}
运行成功,数据改变:
使用回调函数
如果想参与更加细节的jdbc代码可以使用回调函数
execute方法,两个参数:
- 第一个:sql语句
- 第二个:回调接口PreparedStatementCallback,需实现doInPreparedStatement方法
测试成功:
@Test
public void testCallback(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "select * from t_user where id = ?";
User user = jdbcTemplate.execute(sql, new PreparedStatementCallback<User>() {
@Override
public User doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
User user = null;
ps.setInt(1, 1);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setLoginName(rs.getString("loginName"));
user.setLoginPwd(rs.getString("loginPwd"));
}
return user;
}
});
System.out.println(user);
}
使用德鲁伊连接池
之前数据源是用我们自己写的。也可以使用别人写好的。例如比较牛的德鲁伊连接池。
第一步:引入德鲁伊连接池的依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
第二步:将德鲁伊中的数据源配置到spring配置文件中。和配置我们自己写的一样。
创建一个新的配置文件spring2.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.xsd">
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--这里需要数据源,也可以集成其他数据源-->
<property name="dataSource" ref="druidDataSource"/>
</bean>
<!--配置德鲁伊数据源-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydbtest"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
测试程序:
@Test
public void testSelectAllForDruid(){
// 获取JdbcTemplate对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring2.xml");
JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class);
String sql = "select * from t_user";
List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
System.out.println(users);
}
运行可以发现使用了INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited(德鲁伊连接池)