第四篇:SpringBoot 数据持久化之JdbcTemplate

前言

  在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

上一篇:JdbcTemplate(三)


下一篇:Spring Boot 2.x基础教程:使用JdbcTemplate访问MySQL数据库