前言
在Java领域,数据持久化有几个常见的方案,有Spring自带的JdbcTemplate、有MyBatis,还有JPA,在这些方案中,最简单的就是Spring自带的JdbcTemplate了,这个东西虽然没有MyBatis那么方便,但是比起最开始的Jdbc已经强了很多了,它没有MyBatis功能那么强大,当然也意味着它的使用比较简单,事实上,JdbcTemplate算是最简单的数据持久化方案了,本文就和大伙来说说这个东西的使用。
基本用法
pom文件、实体类、服务方法
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- mysql数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- jdbc依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--数据库连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!--测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>2.2.4.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.3.RELEASE</version> </dependency> </dependencies>
实体类
public class User { private Long id; private String username; private String address; //省略getter/setter }
服务类
package com.demo.service; import com.demo.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Service; import java.sql.*; import java.util.List; @Service public class UserService { @Autowired JdbcTemplate jdbcTemplate; // 增1 public int addUser(User user){ return jdbcTemplate.update("insert into user (username,address) values (?,?)", user.getUsername(), user.getAddress()); } // 增2 public int addUser2(User user){ KeyHolder keyHolder = new GeneratedKeyHolder(); int update = jdbcTemplate.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { PreparedStatement ps = connection.prepareStatement("insert into user (username,address) values (?,?)", Statement.RETURN_GENERATED_KEYS); ps.setString(1, user.getUsername()); ps.setString(2, user.getAddress()); return ps; } }, keyHolder); user.setId(keyHolder.getKey().longValue()); return update; } //删 public int deleteUserById(Long id) { return jdbcTemplate.update("delete from user where id=?", id); } //改 public int updateUserById(User user) { return jdbcTemplate.update("update user set username=?,address=? where id=?", user.getUsername(), user.getAddress(),user.getId()); } //查1 public List<User> getAllUser(){ return jdbcTemplate.query("select * from user", new RowMapper<User>() { @Override public User mapRow(ResultSet resultSet, int i) throws SQLException { //从查询结果中取出数据 String username = resultSet.getString("username"); String address = resultSet.getString("address"); long id = resultSet.getLong("id"); //新建对象,将取出的数据赋值 User user = new User(); user.setAddress(address); user.setUsername(username); user.setId(id); return user; } }); } //查2 public List<User> getAllUsers2() { return jdbcTemplate.query("select * from user", new BeanPropertyRowMapper<>(User.class)); } }
application.yml配置文件
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource
测试
package com.demo; import com.demo.entity.User; import com.demo.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class JdbcTemplateTest { @Autowired UserService userService;
@Test public void addObj(){ User user = new User(); user.setUsername("毛不易"); user.setAddress("人心"); //增 userService.addUser(user); userService.addUser2(user); } @Test public void delObj(){ userService.deleteUserById(1L); } @Test public void updateObj(){ User user = new User(); user.setId(2L); user.setUsername("薛之谦"); user.setAddress("上海"); userService.updateUserById(user); } @Test public void selectList(){ List<User> userList1 = userService.getAllUser(); System.out.println(userList1); List<User> userList2 = userService.getAllUsers2(); System.out.println(userList2); } }
其他
除了这些基本用法之外,JdbcTemplate也支持其他用法,例如调用存储过程等,这些都比较容易,而且和Jdbc本身都比较相似,这里也就不做介绍了。
原理分析
那么在SpringBoot中,配置完数据库基本信息之后,就有了一个JdbcTemplate了,这个东西是从哪里来的呢?源码在org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
类中,该类源码如下:
@Configuration @ConditionalOnClass({ DataSource.class, JdbcTemplate.class }) @ConditionalOnSingleCandidate(DataSource.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) @EnableConfigurationProperties(JdbcProperties.class) public class JdbcTemplateAutoConfiguration { @Configuration static class JdbcTemplateConfiguration { private final DataSource dataSource; private final JdbcProperties properties; JdbcTemplateConfiguration(DataSource dataSource, JdbcProperties properties) { this.dataSource = dataSource; this.properties = properties; } @Bean @Primary @ConditionalOnMissingBean(JdbcOperations.class) public JdbcTemplate jdbcTemplate() { JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource); JdbcProperties.Template template = this.properties.getTemplate(); jdbcTemplate.setFetchSize(template.getFetchSize()); jdbcTemplate.setMaxRows(template.getMaxRows()); if (template.getQueryTimeout() != null) { jdbcTemplate .setQueryTimeout((int) template.getQueryTimeout().getSeconds()); } return jdbcTemplate; } } @Configuration @Import(JdbcTemplateConfiguration.class) static class NamedParameterJdbcTemplateConfiguration { @Bean @Primary @ConditionalOnSingleCandidate(JdbcTemplate.class) @ConditionalOnMissingBean(NamedParameterJdbcOperations.class) public NamedParameterJdbcTemplate namedParameterJdbcTemplate( JdbcTemplate jdbcTemplate) { return new NamedParameterJdbcTemplate(jdbcTemplate); } } }
从这个类中,大致可以看出,当当前类路径下存在DataSource和JdbcTemplate时,该类就会被自动配置,jdbcTemplate方法则表示,如果开发者没有自己提供一个JdbcOperations的实例的话,系统就自动配置一个JdbcTemplate Bean(JdbcTemplate是JdbcOperations接口的一个实现)。
end