SpringBoot31 整合SpringJDBC、整合MyBatis、利用AOP实现多数据源切换

一、整合SpringJDBC

1  JDBC

  JDBC(Java Data Base Connectivity,Java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数据库提供统一访问,它一组用 Java 语言编写的类和接口组成。JDBC 提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

  1.1 优点

    JDBC 就是一套 Java 访问数据库的 API 规范,利用这套规范屏蔽了各种数据库 API 调用的差异性;

    当 Java 程序需要访问数据库时,直接调用 JDBC API 相关代码进行操作,JDBC 调用各类数据库的驱动包进行交互,最后数据库驱动包和对应的数据库通讯,完成 Java 程序操作数据库。

  1.2 缺点

    直接在 Java 程序中使用 JDBC 比较复杂,需要 7 步才能完成数据库的操作:

      加载数据库驱动 -> 建立数据库连接 -> 创建数据库操作对象 -> 编写SQL语句 -> 利用数据库操作对象执行数据库操作 -> 获取并操作结果集 -> 关闭连接对象和操作对象,回收资源

    利用JDBC操作数据库参考博文

  1.3 新技术

    由于JDBC操作数据库非常复杂,所以牛人们编写了很多ORM框架,其中Hibernate、Mybatis、SpringJDBC最流行;

    时间又过了N年,

    又有牛人在Hibernate的基础上开发了SpringDataJPA,在Mybatis的基础上开发出了MybatisPlus。

2 SpringBoot集成SpringJDBC环境搭建

  2.1 创建一个SpringBoot项目

    引入 spring-boot-starter-web 、spring-boot-starter-jdbc、mysql-connector-java 者三个主要依赖;

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
必要依赖

    再引入 devtools、lombok这两个辅助依赖。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
辅助依赖

    2.1.1 依赖说明   

<?xml version="1.0" encoding="UTF-8"?>
<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.xunyji</groupId>
    <artifactId>spring_jdbc</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring_jdbc</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
pom.xml

      查看pom.xml依赖图可以知道 spring-boot-starter-jdbc 依赖了spring-jdbc、HikariCP;

      spring-jdbc主要提供JDBC操作相关的接口,HikariCP就是传说中最快的连接池。

  2.2 数据库准备

    2.2.1 创建数据表

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `name` varchar(32) DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) DEFAULT NULL COMMENT '密码',
  `age`  int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
users

    2.2.1 配置数据源信息

      坑:Spring Boot 2.1.0 中,com.mysql.jdbc.Driver 已经过期,推荐使用 com.mysql.cj.jdbc.Driver。

      技巧:IDEA是可以连接数据库的哟,而且还可以反向生成对应的实体类哟;IDEA连接数据库并生成实体列参考博文

spring.datasource.url=jdbc:mysql://localhost:3306/testdemo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=****
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

    2.2.3 创建实体类

      版案例使用了lombok进行简化编写

package com.xunyji.spring_jdbc.model.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author 王杨帅
 * @create 2018-11-18 10:43
 * @desc
 **/
@Data // 自动生成get、set、toString、equals、hashCode、canEaual方法 和 显示无参构造器
@Builder // 生成builder方法
@NoArgsConstructor // 生成无参构造器
@AllArgsConstructor // 自动生成所有字段的有参构造器,会覆盖无参构造器
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
User.java

  2.3 编写持久层

    2.3.1 持久层接口

package com.xunyji.spring_jdbc.repository;

import com.xunyji.spring_jdbc.model.entity.User;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author 王杨帅
 * @create 2018-11-18 10:53
 * @desc user表对应的持久层接口
 **/
public interface UserRepository {
    Integer save(User user);
    Integer update(User user);
    Integer delete(Integer id);
    List<User> findAll();
    User findById(Integer id);
}
UserRepository.java

    2.3.2 持久层实现类

      技巧:在实现类中依赖注入 JdbcTemplate,它是Spring提供的用于JDBC操作的工具类。

    @Autowired
    private JdbcTemplate jdbcTemplate;
package com.xunyji.spring_jdbc.repository.impl;

import com.xunyji.spring_jdbc.comm.exception.ExceptionEnum;
import com.xunyji.spring_jdbc.comm.exception.FuryException;
import com.xunyji.spring_jdbc.model.entity.User;
import com.xunyji.spring_jdbc.repository.UserRepository;
import com.xunyji.spring_jdbc.repository.impl.resultmap.UserRowMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @author 王杨帅
 * @create 2018-11-18 10:55
 * @desc user表对应的持久层实现类
 **/
@Repository
public class UserRepositoryImpl implements UserRepository {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Boolean save(User user) {
        Integer saveResult = jdbcTemplate.update(
                "INSERT user (name, age, email) VALUES (?, ?, ?)",
                user.getName(), user.getAge(), user.getEmail()
        );
        if (saveResult.equals(1)) {
            return true;
        }
        return false;
    }

    @Override
    public Boolean update(User user) throws Exception {
        Integer updateResult = jdbcTemplate.update(
                "UPDATE user SET name = ?, age = ?, email = ? WHERE id = ?",
                user.getName(), user.getAge(), user.getEmail(), user.getId()
        );
        if (updateResult.equals(1)) {
            return true;
        }
        return false;
    }

    @Override
    public Boolean delete(Long id) {
        Integer deleteResult = jdbcTemplate.update(
                "DELETE FROM user WHERE id = ?",
                id
        );
        if (deleteResult.equals(1)) {
            return true;
        }
        return false;
    }

    @Override
    public List<User> findAll() {
        return jdbcTemplate.query(
                "SELECT * FROM user",
                new UserRowMapper()
        );
    }

    @Override
    public User findById(Long id) {
        try {
            User user = jdbcTemplate.queryForObject(
                    "SELECT id, name, age, email FROM user WHERE id = ?",
                    new Object[]{id},
                    new BeanPropertyRowMapper<>(User.class)
            );
            return user;
        } catch (EmptyResultDataAccessException e) {
            log.info(e.getMessage());
            throw new FuryException(ExceptionEnum.RESULT_IS_EMPTY);
        }
    }
}
UserRepositoryImpl .java

      技巧:新增、更新、删除都是利用JdbcTemplate的update方法,update方法的返回值是执行成功的记录数(需在实现类中根据结果判断是否操作成功);

      技巧:利用JdbcTemplate的queryForObject方法查询单条记录,利用JdbcTemplate的query查询多条记录;

      技巧:利用JdbcTemplate的queryForObject方法查询单条记录时如果查询不到就会抛出EmptyResultDataAccessException,需要进行捕获。

      技巧:查询记录时需要对结果集进行封装,可以直接利用BeanPropertyRowMapper实例进行封装,或者自定义一个实现了UserRowMapper的实现类

    2.3.3 持久层测试类

package com.xunyji.spring_jdbc.repository.impl;

import com.xunyji.spring_jdbc.model.entity.User;
import com.xunyji.spring_jdbc.repository.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
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;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class UserRepositoryImplTest {


    @Autowired
    private UserRepository userRepository;

    private User user;

    @Before
    public void init() {
        user = User.builder()
                .id(81L)
                .age(33)
                .name("warrior")
                .email("[email protected]")
                .build();
    }

    @Test
    public void save() throws Exception {
        Boolean saveNumber = userRepository.save(user);
        log.info("新增结果为:" + saveNumber);
    }

    @Test
    public void update() throws Exception {
        Boolean updateResult = userRepository.update(user);
        log.info("更新结果为:" + updateResult);
    }

    @Test
    public void delete() throws Exception {
        Boolean delete = userRepository.delete(81L);
        log.info("删除结果为:" + delete);
    }

    @Test
    public void findById() throws Exception {
        User byId = userRepository.findById(8L);
        log.info("获取的数据信息为:" + byId);
    }

    @Test
    public void findAll() throws Exception {
        List<User> all = userRepository.findAll();
        log.info("获取到的列表数据为:" + all);
        all.stream().forEach(System.out::println);
    }

}
UserRepositoryImplTest.java

  2.4 编写服务层

    待更新...

  2.5 编写控制层

    待更新...

3 多数据源

  3.1 硬编码实现【不推荐】

  3.2 AOP实现【推荐】

     

      

二、整合MyBatis

猜你喜欢

转载自www.cnblogs.com/NeverCtrl-C/p/9978406.html
今日推荐