当前位置: 首页 > 图灵资讯 > 技术篇> mybatis的缓存

mybatis的缓存

来源:图灵教育
时间:2023-06-09 10:14:47

1.什么是缓存113?

mybatis的缓存_二级缓存

缓存:cache

1.1缓存的作⽤:113

通过减少IO⽅式,来提⾼程序的执⾏效率。

1.2mybatis缓存:113

将select语句的查询结果放入缓存(内存)中⼀第二个是这个select语句,直接从缓存中取出,不再检查数据库。⼀⽅⾯IO减少了。另一个⼀⽅⾯不再执⾏繁琐的搜索算法。效率高⼤⼤提升。

1.3mybatis缓存包括:114

⼀级缓存:将查询到的数据存储在SqlSesion中。

⼆级缓存:将查询到的数据存储在SqlSessionFactory中。

或者集成其他第三个⽅的缓存:⽐如Ehcache[Java语言⾔开发的】、Memcache【C语⾔开发的】

等。

缓存仅针对DQL语句,即缓存机制仅对应select语句。

2.一级缓存113

⼀默认情况下,级缓存是开放的。不需要任何配置。

原理:只要使用⽤同⼀SqlSession对象执行⾏同⼀条SQL语句,就会⾛缓存。

<select id="selectById" resultType="Car">        select * from t_car where id = #{id}    </select>
@Test    public void testSelectById(){        SqlSession sqlSession = SqlSessionUtil.openSession();        CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);        Car car1 = mapper1.selectById(43L);        System.out.println(car1);        CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);        Car car2 = mapper2.selectById(43L);        System.out.println(car2);        //sqlSession.commit();        sqlSession.close();    }

mybatis的缓存_二级缓存_02

2.1什么情况下不行?⾛缓存?1152.1.1第⼀种类:不同的SqlSession对象。115
 ///不要走缓存    // 如需获取不同的SqlSession对象,则不能使用以下代码。  115    @Test    public void testSelectById() throws Exception{        //SqlSession sqlSession = SqlSessionUtil.openSession();        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));        SqlSession sqlsession = sqlSessionFactory.openSession();        SqlSession sqlsession2sion = sqlSessionFactory.openSession();        CarMapper mapper1 = sqlsession.getMapper(CarMapper.class);        Car car1 = mapper1.selectById(43L);        System.out.println(car1);        CarMapper mapper2 = sqlsession2sion.getMapper(CarMapper.class);        Car car2 = mapper2.selectById(43L);        System.out.println(car2);        sqlsession.close();        sqlsession2sion.close();    }

 

mybatis的缓存_缓存_03

2.1.2第⼆种类:查询条件发生变化。1162.1.3⼀有两种类型的缓存失效:116

你在第一次DQL和第二次DQL之间做了以下两件事中的任何一件,都会清空一级缓存:

1.实施了sqlsession的clearcache()方法,即手动清空缓存。

2.执行INSERT或DELETE或UPDATE语句。无论操作哪个表,都会清空一级缓存。

第⼀种:第⼀次查询和第⼆二次查询之间,⼿动清空了⼀级缓存。

@Test    public void testSelectById(){        SqlSession sqlSession = SqlSessionUtil.openSession();        CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);        Car car1 = mapper1.selectById(43L);        System.out.println(car1);        // 手动清空一级缓存  116A        sqlSession.clearCache();                CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);        Car car2 = mapper2.selectById(43L);        System.out.println(car2);        //sqlSession.commit();        sqlSession.close();    }

mybatis的缓存_缓存_04

第⼆种:第⼀次查询和第⼆二次查询之间,执行⾏增加或删除操作。[这个增加或删除与哪个表格无关,只要有insertdeleteupdate操作,⼀等级缓存失效。

@Test    public void testSelectById(){        SqlSession sqlSession = SqlSessionUtil.openSession();        CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);        Car car1 = mapper1.selectById(43L);        System.out.println(car1);        // 手动清空一级缓存  116A        //sqlSession.clearCache();        // INSERT在这里实施 DELETE UPDATE中的任何句子。而且与表无关。116        CarMapper mapper = sqlSession.getMapper(CarMapper.class);        mapper.insertClazz(2000, “高三三班”;        CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);        Car car2 = mapper2.selectById(43L);        System.out.println(car2);        sqlSession.commit();        sqlSession.close();    }

mybatis的缓存_缓存_05

3.二级缓存117

⼆SqlSessionFactory是级缓存的范围。

3.1使⽤⼆等级缓存需要具备以下几点⼏个条件:117

1.全局打开或关闭所有映射器配置⽂已配置在件中的任何缓存。默认为true,⽆需设置。

2.在需要使⽤⼆Sqlmaper级缓存.xml⽂零件中添加配置:

3.使⽤⼆级缓存的物理对象必须是可序列化的,即java必须实现.io.Serializable⼝

4.SqlSession对象关闭或提交后,⼀级缓存中的数据将被写入⼊到⼆在等级缓存中。此时⼆级缓存才可⽤。

<!--二次缓存试验   117-->    <select id=“selectbyId2” resultType="Car">        select * from t_car where id = #{id}    </select>
//测试二级缓存   117    @Test    public void testselectbyid2() throws Exception{        // 这里只有一个SqlSessionFactory对象。SqlSessionFactory对应于二级缓存。        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));        SqlSession sqlsession = sqlSessionFactory.openSession();        SqlSession sqlsession2sion = sqlSessionFactory.openSession();        CarMapper mapper1 = sqlsession.getMapper(CarMapper.class);        CarMapper mapper2 = sqlsession2sion.getMapper(CarMapper.class);        // 本行代码执行完成后,事实上,数据是缓存到一级缓存。(sqlsession1是一级缓存。(sqlsession1是一级缓存。)        Car car1 = mapper1.selectByID2(43L);        System.out.println(car1);        // 如果SqlSession1对象在这里不关闭,二次缓存中仍然没有数据。        // 如果执行此行代码,sqlsession1的一级缓存中的数据将放入二级缓存中。        sqlsession.close();        // 代码执行完成后,数据实际上会缓存到一级缓存中。(sqlsession2是一级缓存。)        Car car2 = mapper2.selectByID2(43L);        System.out.println(car2);        // 在此执行程序时,sqlsession1的一级缓存中的数据将被写入二级缓存中。        //sqlSesion.close();        // 在此执行程序时,sqlsession2的一级缓存数据将写入二级缓存。        sqlsession2sion.close();    }

mybatis的缓存_sql_06

3.2⼆级缓存失效:118

只要增删操作发生在两次查询之间。⼆等级缓存会失效。【⼀等级缓存也会失效]

3.3⼆级缓存相关配置:118

mybatis的缓存_二级缓存_07

1.eviction:指定从缓存中删除对象的淘汰算法。默认采集⽤LRU策略。

a.LRU:LeastRecentlyUsed。最近最少使⽤。优先在间隔时间内淘汰⽤频率最低的对象。(其实也有。⼀淘汰算法LFU最不常见⽤。)

b.FIFO:FirstInFirstOut。⼀先进先出的数据缓存器。先进⼊⼆级缓存的对象首先被淘汰。

c.SOFT:软引⽤。淘汰软引⽤指向对象。具体算法与JVM垃圾回收算法有关。

d.WEAK:弱引⽤。淘汰弱引⽤指向对象。具体算法与JVM垃圾回收算法有关。

2.flushInterval:

a.⼆等级缓存的刷新时间间隔。单位毫秒。如果没有设置。这意味着缓存没有刷新,只要内存⾜够⼤,⼀直会向⼆缓存数据在等级缓存中。去除⾮执⾏了增删改。

3.readOnly:

a.true:多个相同的sql语句执行⾏返回的对象是共享的⼀性能好。但多线程并发可能存在安全问题。

b.false:多个相同的sql语句执行⾏之后返回的对象是副本,调整⽤clone⽅法。性能⼀一般。但是安全。

4.size:

a.设置⼆java对象最多可存储在等级缓存中。默认值1024。

4.集成Ehcache(集成第三方缓存机制)119

集成Ehcache取代mybatiss⾃带的⼆级缓存。⼀级缓存是⽆法替代的。

mybatis提供外部接收⼝,也可以集成第三⽅缓存组件。⽐比如EhCache、Memcache等。都可以。Ehcache是Java写的。Memcache是C语⾔所以mybatis集成EhCache比较常见⻅,集成可以按照以下步骤完成:

第⼀步:引⼊整合ehcache对mybatis的依赖。

pom.xml

<!--集成ehcache的mybatis组件-->        <dependency>            <groupId>org.mybatis.caches</groupId>            <artifactId>mybatis-ehcache</artifactId>            <version>1.2.2</version>        </dependency>

第⼆步骤:在类的根路径下新建echcache.xml⽂并提供以下配置信息。

echcache.xml

<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"         updateCheck="false">    <!--磁盘存储:将暂时不使用缓存的对象转移到类似Windows系统的硬盘上的虚拟内存-->    <diskStore path="e:/ehcache"/>    <!--磁盘存储:将暂时不使用缓存的对象转移到类似Windows系统的硬盘上的虚拟内存-->    <diskStore path="e:/ehcache"/>    <!--defaultCache:默认管理策略-->    <!--eternal:elements设置缓存是否永远不会过期。如果是true,缓存的数据总是有效的。如果是false,则根据timetoidleseconds和timetoliveseconds判断-->    <!--maxElementsInMemory:element在内存中缓存的最大数量-->    <!--overflowToDisk:如果内存中的数据超过内存限制,是否应该缓存到磁盘上-->    <!--diskPersistent:磁盘上是否持久。数据重启jvm后是否有效。默认为false-->    <!--timeToIdleSeconds:对象的空闲时间(单位:秒)是指对象在没有被访问的情况下失败的时间。只有eternal对false有效。默认值0表示可以一直访问-->    <!--timeToLiveSeconds:对象存活时间(单位:秒)是指对象从创建到失效所需的时间。只有eternal对false有效。默认值0表示可以一直访问-->    <!--memoryStoreEvictionPolicy:缓存的3 种清空策略-->    <!--FIFO:first in first out (先进先出)-->    <!--LFU:Less Frequently Used (至少使用).这意味着它一直至少被使用。缓存元素有hittt 属性,hit 最小值将被清除缓存-->    <!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存元素有时间戳,当缓存容量满了,又需要腾出空间来缓存新元素时,现有缓存元素中时间戳离当前时间最远的元素将被清除-->    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/></ehcache>

第三步:修改Sqlmaper.xml⽂添加type属性的件中标签。

CarMapper.xml

<!--集成Ehcache组件-->    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

第四步:编写测试程序⽤。

//测试二级缓存   117    @Test    public void testselectbyid2() throws Exception{        // 这里只有一个SqlSessionFactory对象。SqlSessionFactory对应于二级缓存。        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));        SqlSession sqlsession = sqlSessionFactory.openSession();        SqlSession sqlsession2sion = sqlSessionFactory.openSession();        CarMapper mapper1 = sqlsession.getMapper(CarMapper.class);        CarMapper mapper2 = sqlsession2sion.getMapper(CarMapper.class);        // 本行代码执行完成后,事实上,数据是缓存到一级缓存。(sqlsession1是一级缓存。(sqlsession1是一级缓存。)        Car car1 = mapper1.selectByID2(43L);        System.out.println(car1);        // 如果SqlSession1对象在这里不关闭,二次缓存中仍然没有数据。        // 如果执行此行代码,sqlsession1的一级缓存中的数据将放入二级缓存中。        sqlsession.close();        // 代码执行完成后,数据实际上会缓存到一级缓存中。(sqlsession2是一级缓存。)        Car car2 = mapper2.selectByID2(43L);        System.out.println(car2);        // 在此执行程序时,sqlsession1的一级缓存中的数据将被写入二级缓存中。        //sqlSesion.close();        // 在此执行程序时,sqlsession2的一级缓存数据将写入二级缓存。        sqlsession2sion.close();    }

mybatis的缓存_缓存_08

5.代码汇总main中com.powernode.mybatis.mapperCarMapper
package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Car;import org.apache.ibatis.annotations.Param;//演示缓存机制  115public interface CarMapper {    /**     * 二次缓存试验   117     * @param id     * @return     */    Car selectById2(Long id);    /**     * 保存班级信息   116     * @param cid     * @param cname     * @return     */    int insertClazz(@Param("cid") Integer cid, @Param("cname") String cname);    /**     * 根据id获取Car信息。115     * @param id     * @return     */    Car selectById(Long id);}
CarMapper.xml
<?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.powernode.mybatis.mapper.CarMapper">    <!--        二级缓存机制在默认情况下是开放的。--        二级缓存机制在默认情况下是开放的。        只需在相应的Sqlmaper中使用.以下标签添加到xml文件中。用来表示“我”使用二次缓存。    -->   <!-- <cache/>-->    <!--集成Ehcache组件  119-->    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>    <insert id="insertClazz">        insert into t_clazz values(#{cid},#{cname})    </insert>    <!--测试一级缓存   116-->    <select id="selectById" resultType="Car">        select * from t_car where id = #{id}    </select>    <!--二次缓存试验   117-->    <select id=“selectbyId2” resultType="Car">        select * from t_car where id = #{id}    </select></mapper>
test中com.powernode.mybatis.testCarMapperTest
package com.powernode.mybatis.test;import com.powernode.mybatis.mapper.CarMapper;import com.powernode.mybatis.pojo.Car;import com.powernode.mybatis.utils.SqlSessionUtil;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Test;//研究缓存机制  115public class CarMapperTest {    //测试二级缓存   117    @Test    public void testselectbyid2() throws Exception{        // 这里只有一个SqlSessionFactory对象。SqlSessionFactory对应于二级缓存。        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));        SqlSession sqlsession = sqlSessionFactory.openSession();        SqlSession sqlsession2sion = sqlSessionFactory.openSession();        CarMapper mapper1 = sqlsession.getMapper(CarMapper.class);        CarMapper mapper2 = sqlsession2sion.getMapper(CarMapper.class);        // 本行代码执行完成后,事实上,数据是缓存到一级缓存。(sqlsession1是一级缓存。(sqlsession1是一级缓存。)        Car car1 = mapper1.selectByID2(43L);        System.out.println(car1);        // 如果SqlSession1对象在这里不关闭,二次缓存中仍然没有数据。        // 如果执行此行代码,sqlsession1的一级缓存中的数据将放入二级缓存中。        sqlsession.close();        // 代码执行完成后,数据实际上会缓存到一级缓存中。(sqlsession2是一级缓存。)        Car car2 = mapper2.selectByID2(43L);        System.out.println(car2);        // 在此执行程序时,sqlsession1的一级缓存中的数据将被写入二级缓存中。        //sqlSesion.close();        // 在此执行程序时,sqlsession2的一级缓存数据将写入二级缓存。        sqlsession2sion.close();    }    ///不要走缓存    // 如需获取不同的SqlSession对象,则不能使用以下代码。  115   /* @Test    public void testSelectById() throws Exception{        //SqlSession sqlSession = SqlSessionUtil.openSession();        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));        SqlSession sqlsession = sqlSessionFactory.openSession();        SqlSession sqlsession2sion = sqlSessionFactory.openSession();        CarMapper mapper1 = sqlsession.getMapper(CarMapper.class);        Car car1 = mapper1.selectById(43L);        System.out.println(car1);        CarMapper mapper2 = sqlsession2sion.getMapper(CarMapper.class);        Car car2 = mapper2.selectById(43L);        System.out.println(car2);        sqlsession.close();        sqlsession2sion.close();    }*/    // 思考:什么时候不走缓存?    // SqlSession对象不一样,肯定不会缓存。    // SqlSession对象不一样,肯定不会缓存。    // 查询条件不同,肯定不要缓存。    // 思考:什么时候一级缓存失效?    // 你在第一次DQL和第二次DQL之间做了以下两件事中的任何一件,都会清空一级缓存:    //     1. 实施了sqlsessionclearcache()方法,即手动清空缓存。    //     2. 执行INSERT或DELETE或UPDATE语句。无论操作哪张表,都会清空一级缓存。    ///根据id获取Car信息。115    @Test    public void testSelectById(){        SqlSession sqlSession = SqlSessionUtil.openSession();        CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);        Car car1 = mapper1.selectById(43L);        System.out.println(car1);        // 手动清空一级缓存  116A        //sqlSession.clearCache();        // INSERT在这里实施 DELETE UPDATE中的任何句子。而且与表无关。116        /*CarMapper mapper = sqlSession.getMapper(CarMapper.class);        mapper.insertClazz(2000, “高三三班”;*/        CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);        Car car2 = mapper2.selectById(43L);        System.out.println(car2);        sqlSession.commit();        sqlSession.close();    }}
com.powernode.mybatis.pojoCar
package com.powernode.mybatis.pojo;import java.io.Serializable;/** * Pojo类包装汽车相关信息。普通java类。 * @author 动力节点 * @version 1.0 * @since 1.0 */public class Car implements Serializable {    // 数据库表中的字段应与pojo属性一一对应。    // 建议使用包装类,以防止null问题。    private Long id;    private String carNum;    private String brand;    private Double guidePrice;    private String produceTime;    private String carType;    @Override    public String toString() {        return "Car{" +                "id=" + id +                ", carNum='" + carNum + '\'' +                ", brand='" + brand + '\'' +                ", guidePrice=" + guidePrice +                ", produceTime='" + produceTime + '\'' +                ", carType='" + carType + '\'' +                '}';    }    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getCarNum() {        return carNum;    }    /*public String getXyz() {        return carNum;    }*/    public void setCarNum(String carNum) {        this.carNum = carNum;    }    public String getBrand() {        return brand;    }    public void setBrand(String brand) {        this.brand = brand;    }    public Double getGuidePrice() {        return guidePrice;    }    public void setGuidePrice(Double guidePrice) {        this.guidePrice = guidePrice;    }    public String getProduceTime() {        return produceTime;    }    public void setProduceTime(String produceTime) {        this.produceTime = produceTime;    }    public String getCarType() {        return carType;    }    public void setCarType(String carType) {        this.carType = carType;    }    public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {        this.id = id;        this.carNum = carNum;        this.brand = brand;        this.guidePrice = guidePrice;        this.produceTime = produceTime;        this.carType = carType;    }    public Car() {    }}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <properties resource="jdbc.properties"/>    <!--mapunderscoretocamelcase开始驼峰命名自动映射-->    <settings>        <setting name="mapUnderscoreToCamelCase" value="true"/>    </settings>    <typeAliases>        <package name="com.powernode.mybatis.pojo"/>    </typeAliases>    <environments default="dev">        <environment id="dev">            <transactionManager type="JDBC"/>            <dataSource type="POOLED">                <property name="driver" value="${jdbc.driver}"/>                <property name="url" value="${jdbc.url}"/>                <property name="username" value="${jdbc.username}"/>                <property name="password" value="${jdbc.password}"/>            </dataSource>        </environment>    </environments>    <mappers>        <package name="com.powernode.mybatis.mapper"/>    </mappers></configuration>
echcache.xml
<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"         updateCheck="false">    <!--磁盘存储:将暂时不使用缓存的对象转移到类似Windows系统的硬盘上的虚拟内存-->    <diskStore path="e:/ehcache"/>    <!--磁盘存储:将暂时不使用缓存的对象转移到类似Windows系统的硬盘上的虚拟内存-->    <diskStore path="e:/ehcache"/>    <!--defaultCache:默认管理策略-->    <!--eternal:elements设置缓存是否永远不会过期。如果是true,缓存的数据总是有效的。如果是false,则根据timetoidleseconds和timetoliveseconds判断-->    <!--maxElementsInMemory:element在内存中缓存的最大数量-->    <!--overflowToDisk:如果内存中的数据超过内存限制,是否应该缓存到磁盘上-->    <!--diskPersistent:磁盘上是否持久。数据重启jvm后是否有效。默认为false-->    <!--timeToIdleSeconds:对象的空闲时间(单位:秒)是指对象在没有被访问的情况下失败的时间。只有eternal对false有效。默认值0表示可以一直访问-->    <!--timeToLiveSeconds:对象存活时间(单位:秒)是指对象从创建到失效所需的时间。只有eternal对false有效。默认值0表示可以一直访问-->    <!--memoryStoreEvictionPolicy:缓存的3 种清空策略-->    <!--FIFO:first in first out (先进先出)-->    <!--LFU:Less Frequently Used (至少使用).这意味着它一直至少被使用。缓存元素有hittt 属性,hit 最小值将被清除缓存-->    <!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存元素有时间戳,当缓存容量满了,又需要腾出空间来缓存新元素时,现有缓存元素中时间戳离当前时间最远的元素将被清除-->    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/></ehcache>
pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.powernode</groupId>    <artifactId>course22</artifactId>    <version>1.0-SNAPSHOT</version>    <packaging>jar</packaging>    <dependencies>        <!--集成ehcache的mybatis组件-->        <dependency>            <groupId>org.mybatis.caches</groupId>            <artifactId>mybatis-ehcache</artifactId>            <version>1.2.2</version>        </dependency>        <dependency>            <groupId>org.mybatis</groupId>            <artifactId>mybatis</artifactId>            <version>3.5.10</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>8.0.30</version>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.13.2</version>            <scope>test</scope>        </dependency>        <dependency>            <groupId>ch.qos.logback</groupId>            <artifactId>logback-classic</artifactId>            <version>1.2.11</version>        </dependency>    </dependencies>    <properties>        <!--    jdk版本用于编译代码-->        <maven.compiler.source>1.8</maven.compiler.source>        <!--    使用jdk版本的操作程序-->        <maven.compiler.target>1.8</maven.compiler.target>    </properties></project>

剩余的

utils

logback.xml

jdbc.properties

不做赘述