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 腳本都會被執行(故意寫錯腳本會拋出異常)

     問題原因:待進一步分析

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM