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 脚本都会被执行(故意写错脚本会抛出异常)

     问题原因:待进一步分析

 

posted @ 2021-05-30 22:01  仅此而已-远方  阅读(4660)  评论(0编辑  收藏  举报