SpringBoot整合H2数据库
作者:mmseoamin日期:2023-12-18

1、H2数据库概述


H2官网:http://www.h2database.com/

H2是一个Java语言编写的嵌入式数据库,它不受平台的限制,同时H2提供了一个十分方便的web控制台,用于操作和管理数据库内容。H2还提供兼容模式,可以兼容一些主流的数据库,也可以为缓存数据库使用,它具有比较完备的数据库特性,如支client/server连接,能够支持标准的SQL语句,支持存储过程等。因此采用H2作为开发期、测试期和演示的数据库非常方便,它不太适合作为大规模生产数据库。

H2数据库的前身是 HypersonicSQL,它的名字的含义是 Hypersonic2,但是它的代码是从头开始编写的,没有使用HypersonicSQL或者HSQLDB的代码。

H2特点:

  • 运行很快,开源,支持 JDBC API;
  • 支持嵌入模式和服务器模式;
  • 基于磁盘或内存中的数据库;
  • 基于浏览器控制台应用程序;
  • 文件很小,jar文件约 1.5 MB
  • 加密数据库;
  • ODBC 驱动程序;

    H2控制台应用程序

    通过控制台应用程序,我们就可以使用浏览器访问H2数据库了,数据库管理界面类似phpmyadmin。

    SpringBoot整合H2数据库,在这里插入图片描述,第1张

    H2文档地址:http://www.h2database.com/html/quickstart.html

    使用方式:

    集成h2也很简单,直接将jar包导入项目中即可。

    
    
        com.h2database
        h2
        1.4.199
        test
    
    

    2、SpringBoot整合H2

    1、创建一个SpringBoot工程

    SpringBoot整合H2数据库,在这里插入图片描述,第2张

    2、导入mp和h2相关依赖:

    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
    
        com.h2database
        h2
        
        compile
    
    
    
        com.baomidou
        mybatis-plus-boot-starter
        3.4.2
    
    
    
        mysql
        mysql-connector-java
        5.1.47
    
    
    
        org.springframework.boot
        spring-boot-starter-test
    
    
    
        org.projectlombok
        lombok
    
    

    3、向application.yml文件中添加配置:

    server:
      port: 8888 # 端口号
    spring:
      datasource:
        url: jdbc:h2:~/mydb  # 数据库
        driver-class-name: org.h2.Driver
        username: root  
        password: test
      h2:
        console:
          path: /h2-console  #h2嵌入式数据库控制台,可以通过浏览器访问
          enabled: true
    mybatis-plus:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启sql日志
        map-underscore-to-case: true # 开启驼峰映射(mp默认开启)
    
    • username和 password 是H2数据库的用户名和密码,自己定义即可。

    • /h2-console 是自定义的控制台地址,用户可以打开浏览器,进入这个地址管理数据库,使用上面配置的username和password登录。

      4、编写业务代码:

      实体类:

      package com.baidou.entity;
      import com.baomidou.mybatisplus.annotation.TableField;
      import com.baomidou.mybatisplus.annotation.TableName;
      import lombok.Data;
      /**
       * 实体类
       *
       * @author 白豆五
       * @version 2023/04/4
       * @since JDK8
       */
      @Data
      @TableName(value = "tb_user")
      public class User {
          private Integer id;
          private String username;
          private String pwd;
          private Integer salary;//以分为单位,避免浮点运算精度丢失问题
          // 封装数据
          public void setSalary(Integer salary) {
              this.salary = salary * 100;
          }
      }
      

      mapper接口:

      package com.baidou.mapper;
      import com.baidou.entity.User;
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import org.apache.ibatis.annotations.Mapper;
      //mapper接口
      @Mapper
      public interface UserMapper extends BaseMapper {
      }
      

      service接口:

      package com.baidou.service;
      import com.baidou.entity.User;
      import com.baomidou.mybatisplus.extension.service.IService;
      // service接口
      public interface UserService extends IService {
      }
      

      service接口实现类:

      package com.baidou.service.impl;
      import com.baidou.entity.User;
      import com.baidou.mapper.UserMapper;
      import com.baidou.service.UserService;
      import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import org.springframework.stereotype.Service;
      /**
       * service接口实现类
       *
       * @author 白豆五
       * @version 2023/04/4
       * @since JDK8
       */
      @Service
      public class UserServiceImpl extends ServiceImpl implements UserService {
      }
      

      5、在resources目录下,创建一个db/schema-h2.sql文件:

      DROP TABLE IF EXISTS tb_user;
      CREATE TABLE tb_user(
          id INT(11) PRIMARY KEY  AUTO_INCREMENT COMMENT 'id',
          username VARCHAR(30) NOT NULL UNIQUE COMMENT '用户名',
          pwd VARCHAR(10) NOT NULL COMMENT '密码',
          salary  INT  NULL DEFAULT 0 COMMENT '薪资'
      );
      

      SpringBoot整合H2数据库,在这里插入图片描述,第3张

      6、实现让服务启动时自动执行DDL语句,并且只让它第一次启动时自动创建数据库,后续项目启动都不会重新创建(避免数据丢失)

      ① 定义一个类去实现ApplicationContextAware接口,然后在类上添加@Component注解,代表当前类是spring的bean。

      package com.baidou.config;
      import org.springframework.beans.BeansException;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.ApplicationContextAware;
      import org.springframework.core.io.Resource;
      import org.springframework.stereotype.Component;
      /**
       * 定义一个注册器策略类,方便后续加载资源文件
       *
       * ApplicationContextAware是Spring框架提供的接口,也叫做spring上下文的增强器,在项目启动时执行,会被spring处理
       * 当一个bean实现了该接口,通过setApplicationContext方法可以直接获取spring容器中的所有bean
       */
      @Component
      public class ApplicationContextRegister implements ApplicationContextAware {
          private ApplicationContext applicationContext = null;
          /**
           * Spring容器启动时,会回调setApplicationContext方法,并传入ApplicationContext对象,之后就可对该对象进行操作。(例如获取spring容器中的所有bean)
           *
           * @throws BeansException
           */
          @Override
          public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
              this.applicationContext = applicationContext;
          }
          /**
           * 提供一个方法,用于加载sql脚本文件
           *
           * @param url sql文件位置
           * @return
           */
          public Resource getResource(String url) {
              return this.applicationContext.getResource(url);
          }
      }
      

      ApplicationContextAware接口详解:https://www.cnblogs.com/loongk/p/12375708.html

      ② 编写初始化数据库代码:

      package com.baidou.config;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.autoconfigure.AutoConfigureAfter;
      import org.springframework.core.io.Resource;
      import org.springframework.jdbc.datasource.init.ScriptUtils;
      import org.springframework.stereotype.Service;
      import javax.annotation.PostConstruct;
      import javax.sql.DataSource;
      import java.io.File;
      /**
       * 初始化h2数据库
       */
      @Slf4j
      @Service
      @AutoConfigureAfter(DataSource.class) //DataSource创建完后才初始化此类
      public class H2DataSourceConfig {
          //初始化sql
          private static final String schema="classpath:db/schema-h2.sql";
          @Autowired
          DataSource dataSource;
          @Autowired
          ApplicationContextRegister applicationContextRegister; //自定义注册器
          // JDK提供的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法
          @PostConstruct
          public  void init() throws Exception {
              //初始化本地数据库
              String userHome= System.getProperty("user.home");//获取系统用户目录
              // 创建一个标识文件,只有在第一次初始化数据库时会创建,如果系统用户目录下有这个文件,就不会重新执行sql脚本
              File f = new File(userHome+ File.separator+"my.lock");
              if(!f.exists()){
                  log.info("--------------初始化h2数据----------------------");
                  f.createNewFile();
                  // 加载资源文件
                  Resource resource= (Resource) applicationContextRegister.getResource(schema);
                  // 手动执行SQL语句
                  ScriptUtils.executeSqlScript(dataSource.getConnection(),resource);
              }
          }
      }
      

      7、启动项目,然后浏览器访问:http://localhost:8888/h2-console

      输入之前在application.yml中h2的相关配置;如用户名、密码、数据库名

      SpringBoot整合H2数据库,在这里插入图片描述,第4张

      SpringBoot整合H2数据库,在这里插入图片描述,第5张

      8、创建一个测试类,然后使用MP操作H2数据库

      执行单元测试的时候先将项目停止,不然汇报H2数据库文件锁定问题。(默认单线程模式)

      package com.baidou.test;
      import com.baidou.entity.User;
      import com.baidou.service.UserService;
      import org.junit.jupiter.api.Test;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.test.context.SpringBootTest;
      import java.util.List;
      /**
       * 使用MP操作H2数据库
       *
       * @author 白豆五
       * @version 2023/04/4
       * @since JDK8
       */
      @SpringBootTest
      public class H2Test {
          @Autowired
          private UserService userService;
          @Test
          public void test1() {
              User user = new User();
              user.setId(1);
              user.setUsername("张三");
              user.setPwd("123456e");
              user.setSalary(10000); //10k
              boolean flag = userService.save(user);
              System.out.println(flag ? "插入成功" : "插入失败");
          }
          @Test
          public void test2() {
              List list = userService.list();
              System.out.println(list);
          }
      }
      

      运行结果:

      SpringBoot整合H2数据库,在这里插入图片描述,第6张

      重新启动项目,再次通过浏览器访问h2控制台:

      SpringBoot整合H2数据库,在这里插入图片描述,第7张


      3、 扩展 :基于文件模式将H2数据库持久化

      SpringBoot整合H2数据库,在这里插入图片描述,第8张

      H2数据库在文件模式下会生成: xxx.mv.db和xxx.trace.db文件。

      • xxx.mv.db是H2数据库的主文件,用于保存数据表的结构和数据。
      • xxx.trace.db是H2数据库的跟踪文件,用于记录数据库的操作和日志信息。

        SpringBoot整合H2数据库,在这里插入图片描述,第9张