• SpringBoot集成H2数据库


    前言

    1、场景

    在写DAO层的单元测试时,我们往往会遇到一个问题,测试用例所依赖的数据库数据被修改或删除了,或者在一个新的环境下所依赖的数据库不存在,导致单元测试无法通过。在这种情况下,使用H2内存数据库来模拟数据库环境是一个很好的解决方案。

    2、H2 特点

    • 只有一个jar文件,适合作为嵌入式数据库使用
    • 支持标准SQL和JDBC
    • 可以用于单元测试,启动很快,每一个用例执行完会自动删除内存中的数据

    上代码

    使用maven工程来搭建测试环境,工程目录如下:

     1、核心依赖

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
        </parent>
    
        <dependencies>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <scope>provided</scope>
            </dependency>
        </dependencies>

    2、配置文件 application.yml

    server:
      port: 18095
      
    spring:
      application:
        name: service-h2
      jpa:
        show-sql: true   #打印sql
      datasource:
        url: jdbc:h2:mem:xwj_db;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE   #mem:连接到内存
        driver-class-name: org.h2.Driver
        username: root
        password: 123456
        data: classpath:db/data.sql    #初始化表数据

    参数说明:

    • jdbc:h2:mem         使用h2的内存数据库,还有file等其它方式
    • xwj_db                   数据库名称
    • MODE=MySQL     以 MySQL 的模式运行

    3、实体类

    @Entity
    @Getter
    @Setter
    @ToString
    @NoArgsConstructor
    public class XwjUser implements Serializable {
    
        private static final long serialVersionUID = -2169427939264532306L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        /** 名称 */
        public String name;
    
        /** 年龄 */
        private Integer age;
    
        private Date createDate;
    
    }

    4、Repository

    public interface UserRepository extends JpaRepository<XwjUser, Long>{
    
    }

    5、Service

    @Service
    public class UserService {
    
        @Autowired
        private UserRepository userRepository;
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        public List<XwjUser> findAll() {
            return userRepository.findAll();
        }
    
        public XwjUser save(XwjUser user) {
            return userRepository.save(user);
        }
    
        /**
         * 通过主键id查询
         */
        public XwjUser findById(Long id) {
            Optional<XwjUser> optional = userRepository.findById(id);
            if (optional.isPresent()) {
                return optional.get();
            }
            return null;
        }
    
        /**
         * 通过名称查询
         */
        public List<XwjUser> findByName(String name) {
            String sql = "select * from xwj_user where name like ?";
    
            Object[] paramArr = new Object[1];
            paramArr[0] = name + "%";
    
            return jdbcTemplate.query(sql, paramArr, new BeanPropertyRowMapper<>(XwjUser.class));
        }
    
    }

    测试

    1、在 src/main/resources 目录下,创建一个目录 /db 和脚本文件 data.sql :

    insert into xwj_user (id, name, age, create_date) values(11,'张三','12','2020-04-17 00:00:00');
    insert into xwj_user (id, name, age, create_date) values(12,'李四','13','2020-04-17 00:00:00');
    insert into xwj_user (id, name, age, create_date) values(13,'王五','25','2020-04-17 00:00:00');
    insert into xwj_user (id, name, age, create_date) values(14,'赵六','17','2020-04-17 00:00:00');
    insert into xwj_user (id, name, age, create_date) values(15,'吉米','30','2020-04-17 00:00:00');

    2、在 src/test/java 目录下,创建一个测试类:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class H2Test {
    
        @Autowired
        private UserService userService;
    
        /**
         * 测试查询所有
         */
        @Test
        public void testFind() {
            List<XwjUser> list = userService.findAll();
            System.out.println("list: " + list);
        }
    
        /**
         * 测试新增+查询
         */
        @Test
        public void testInsertAndFind() {
            // 1、新增
            XwjUser user = new XwjUser();
            user.setAge(19);
            user.setName("张三");
            user.setCreateDate(new Date());
            XwjUser newUser = userService.save(user);
    
            // 2、通过id查询
            Long id = newUser.getId();
            System.out.println("findById: " + userService.findById(id));
    
            // 3、模糊查询(自定义sql)
            String name = "张";
            System.out.println("findByName: " + userService.findByName(name));
        }
    
    }

    3、测试 H2Test#testFind 方法,日志如下:

     4、测试 H2Test#testInsertAndFind 方法,日志如下:

    踩坑

    1、在配置文件不要配置 schema,也不要直接将 schema.sql 脚本直接放在 src/main/resources 目录下,否则初始化数据脚本(即上面的data.sql)不会生效。

         问题现象:执行方法的过程中没有任何报错,schema 和 data 脚本都会被执行(故意写错脚本会抛出异常)

         问题原因:待进一步分析

    知识改变世界
  • 相关阅读:
    计算机网络原理笔记 第一章 概述
    数据结构与算法入门C语言(三)线性结构-离散存储[链表]
    数据结构与算法入门C语言 (二) 线性结构-连续存储[线性表(数组)]
    数据结构与算法入门C语言 (一) 概述
    先画一个圈
    appium 简介和相关名称说明
    appium+python 自动化环境安装
    JDK 1.8 安装
    python安装
    python中的 join()函数
  • 原文地址:https://www.cnblogs.com/xuwenjin/p/14829316.html
Copyright © 2020-2023  润新知