跳至主要內容

Spring Boot + Mybatis + H2 database 数据库

Steven2024年4月6日大约 5 分钟示例项目springbootmybatish2database

整合 Spring Boot/Mybatis/H2 database 用来简单开发、测试。

todo mybatis 一级缓存、二级缓存

参考:

H2 介绍

H2 由纯 Java 编写的开源关系数据库,可以直接嵌入到应用程序中,不受平台约束,便于测试。同时提供了 web 界面用于管理数据库。

H2 支持运行三种模式

  • ServerMode(传统模式):需要配置本地(或远程)数据库

    jdbc:h2:tcp://<server>[:<port>]/[<path>]<databaseName>
    jdbc:h2:tcp://localhost/~/test
    jdbc:h2:tcp://dbserv:8084/~/sample
    jdbc:h2:tcp://localhost/mem:test
    jdbc:h2:ssl://<server>[:<port>]/[<path>]<databaseName>
    jdbc:h2:ssl://localhost:8085/~/sample;
    jdbc:h2:tcp://localhost/~/test;AUTO_SERVER=TRUE # 是否允许混合模式,即同时支持多个网络连接
    
  • Embedded(嵌入式):数据库连接关闭时,数据与表结构依然存在

    jdbc:h2:[file:][<path>]<databaseName>
    jdbc:h2:~/test # 示数据库存储在用户主目录中以 “test” 开头的文件中
    jdbc:h2:file:/data/sample # 支持绝对位置
    jdbc:h2:file:C:/data/sample (Windows only)
    jdbc:h2:file:/path/to/your/database;IFEXISTS=TRUE # 如果文件已经存在,则IFEXISTS=TRUE会避免尝试重新创建数据库而引发错误
    
  • In-Memory(内存模式):数据库连接关闭时,数据与表结构删除。多个线程可以访问同一个数据库,但是数据只能在同一个进程中可见。

    jdbc:h2:mem:
    jdbc:h2:mem:<databaseName>
    jdbc:h2:mem:test_mem # 打开一个名为 “test_mem” 的内存数据库
    jdbc:h2:tcp://localhost/mem:db1
    jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 # 最后一个数据库连接关闭后,DB_CLOSE_DELAY=-1 让数据库不会被自动关闭,这样可保持数据在应用重启之间仍然可用
    jdbc:h2:file:/data/mydb;CIPHER=AES # 数据库加密(如果需要的话)
    

相关信息

通过指定 url 方式指定运行模式。 更详细的 url 写法参考官网: https://www.h2database.com/html/features.html#database_url

整合

代码: https://github.com/LawssssCat/blog/tree/master/code/demo-springboot-h2/

项目初始化

导入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>runtime</scope>
</dependency>

配置

server:
  port: 9088

spring:
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:test;mode=mysql #配置 h2 数据库的连接地址
    # schema: # 过时
    # data: # 过时
    username: sa
    password:
  h2:
    console:
      enabled: true #开启 web console 功能。需要 spring-boot-starter-web 依赖
      # path: /h2-console
  sql:
    init:
      schema-locations: classpath:db/schema.sql #,每次启动程序,程序都会运行
      data-locations: classpath:db/data.sql #,每次启动程序,程序都会运行
      # mode: always # 在所有 bean 初始化完成后执行 SQL 脚本
mybatis:
  mapper-locations: /mapper/*.xml

数据库操作

数据库结构
DROP TABLE IF EXISTS employees;

CREATE TABLE employees
(
    id integer not null COMMENT '主键ID',
    first_name varchar(255) not null comment '姓氏',
    last_name varchar(255) null DEFAULT NULL COMMENT '名称',
    age integer NULL DEFAULT 0 COMMENT '年龄',
    email_address varchar(255) NULL DEFAULT NULL COMMENT '邮箱',
    primary key(id)
);

CREATE TABLE events (
    id int primary key COMMENT '主键',
    param json COMMENT '数据'
)

启动后通过 http://localhost:9088/h2-consoleopen in new window 可以进入 web 管理界面。

数据库增删改查

模板类
package org.example.model;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Employee {
    private long id;
    private String firstName;
    private String lastName;
    private int age;
    private String emailId;
}

collection 级联查询

demo 类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Urban {
    private int id;                   //市的编号
    private String cityId;            //省的编号(此博文没用到)
    private String urbanName;         //城市名字
    private List<School> schools;     //对应的所有的学校
    private List<Hospital> hospitals; //对应的所有的医院
}

级联查询

java 级联

在市的 xml 中对学校和医院的 xml 进行一个调用(用 collection 中 select)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yh.mybatis.dao.mapper.UrbanMapper">
	  <resultMap id="findAllUrbanSandH" type="com.yh.mybatis.dao.pojo.Urban">
        <collection property="schools" javaType="java.util.List" ofType="com.yh.mybatis.dao.pojo.School"
                    select="com.yh.mybatis.dao.mapper.SchoolMapper.urbanSchool"
                    column="{urbanId=id}">
        </collection>
        <collection property="hospitals" javaType="java.util.List" ofType="com.yh.mybatis.dao.pojo.Hospital"
                    select="com.yh.mybatis.dao.mapper.HospitalMapper.findAllByUId"
                    column="{urbanId=id}">
        </collection>
    </resultMap>
<!--
		resultMap中的 <id><result>都可以不写,直接写List<School>和List<Hospital>
									type还是sql的返回类型
		collection中  property 是Urban中对应的字段
									javaType 是这个字段的类型
									ofType 是这个字段的泛型  这一项和上一项其实都可以不写,写上了看着更清晰
									select 是子表的按照市的编号查询所有数据的方法 这里要写下全路径
									column 作为select语句的参数传入, 也就是把市的编号id 传给医院和学校xml的urbanId
-->
		<select id="findAllUrbanSandH" resultMap="findAllUrbanSandH">
        select * from urban
    </select>
</mapper>

学校

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yh.mybatis.dao.mapper.SchoolMapper">
    <select id="urbanSchool" resultType="com.yh.mybatis.dao.pojo.School">
        select * from school where urban_id = #{urbanId}
    </select>
</mapper>

医院

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yh.mybatis.dao.mapper.HospitalMapper">
    <select id="findAllByUId" resultType="com.yh.mybatis.dao.pojo.Hospital">
        select * from hospital where urban_id = #{urbanId}
    </select>
<!--实际工作不建议用 *,id就是mapper接口中对应的方法名,resultType就是查询出结果后返回的list的泛型
 urban_id = #{urbanId} 按照urban_id去查找-->
</mapper>