Mybatis 框架实战(下)

时间:2022-06-19
本文章向大家介绍Mybatis 框架实战(下),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

21.sql片段

<!--sql片段-->
<sql id="columnBase">
      `id`,
      `name`,
      `age`,
      `title`,
      `author_id`,
      `featured`,
      `state`,
      `style`
</sql>

<!--通过id查询博客-->
<select id="selectBlog" parameterType="Integer" resultType="Blog">
    select
    <include refid="columnBase"/>
    from blog where id = #{id}
</select>

22 23.逆向功工程-代码的生成

使用 Mybatis 官方工具直接生成对应的mapper文件

全部生成 - 无实际意义,具体项目中不适用

24.缓存 - mybatis的一级缓存

一级缓存:

是session级别的缓存,一级缓存默认存在。

当在同一个session范围内执行查询的时候,如果执行相同的查询,那么第二次查询会从缓存中获取数据。

/**
 * mybatis的一级缓存
 */
@Test
public void testSelectBlogCacheOne1() {
    SqlSession session = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper = session.getMapper(BlogMapper.class);

    Blog blog1 = blogMapper.selectBlog(3);
    System.out.println("结果已查询" + blog1);
    Blog blog2 = blogMapper.selectBlog(3);
    System.out.println("结果已查询:从缓存中获取数据" + blog2);

    session.close();

    System.out.println("session关闭");
}

25.缓存 - 一级缓存被刷新的情况

如果两次查询中间有增删改操作,sql session缓存区会被自动清空,说明下一次查询会重新执行sql语句。

/**
 * mybatis的一级缓存,中间有增删改会刷新
 */
@Test
public void testSelectBlogCacheOne2() {
    SqlSession session = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper = session.getMapper(BlogMapper.class);

    Blog blog1 = blogMapper.selectBlog(3);
    System.out.println("结果已查询" + blog1);
    blog1.setFeatured(true);
    blogMapper.updateBlog(blog1);

    Blog blog2 = blogMapper.selectBlog(3);
    System.out.println("结果已查询:从新执行查询" + blog2);

    session.commit();
    session.close();

    System.out.println("session关闭");
}

26.缓存 - 开启二级缓存

默认不开启。如果在不同的session范围内执行相同的数据查询,那么每次查询将会执行独立的数据库检索过程。

/**
 * mybatis的二级缓存
 */
@Test
public void testSelectBlogCacheLevelTwo1() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    Blog blog1 = blogMapper1.selectBlog(3);
    System.out.println("结果已查询" + blog1);
    session1.close();

    SqlSession session2 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper2 = session2.getMapper(BlogMapper.class);
    Blog blog2 = blogMapper2.selectBlog(3);
    System.out.println("结果已查询:从缓存中获取数据" + blog2);
    session2.close();

    System.out.println("session关闭");
}

**开启二级缓存

1.在mapper文件中设置 <cache/>

2.在实体类中实现序列化接口**

public class Blog implements Serializable {
     private static final long serialVersionUID = 1L;
}
    
/**
 * mybatis的二级缓存
 */
@Test
public void testSelectBlogCacheLevelTwo1() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    Blog blog1 = blogMapper1.selectBlog(3);
    System.out.println("结果已查询" + blog1);
    session1.close();

    // Cache Hit Ratio [mapper.BlogMapper]: 0.5
    SqlSession session2 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper2 = session2.getMapper(BlogMapper.class);
    Blog blog2 = blogMapper2.selectBlog(3);
    System.out.println("结果已查询:从缓存中获取数据" + blog2);
    session2.close();

    System.out.println("session关闭");
}

27.缓存 - 二级缓存被刷新的情况

和一级缓存相同,中间有增删改则二级缓存会被清空

/**
 * mybatis的二级缓存 缓存被刷新
 */
@Test
public void testSelectBlogCacheLevelTwo2() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    Blog blog1 = blogMapper1.selectBlog(3);
    blog1.setFeatured(true);
    blogMapper1.updateBlog(blog1);
    System.out.println("结果已查询" + blog1);
    session1.close();

    SqlSession session2 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper2 = session2.getMapper(BlogMapper.class);
    Blog blog2 = blogMapper2.selectBlog(3);
    System.out.println("缓存被刷新,重新查询" + blog2);
    session2.close();

    System.out.println("session关闭");
}

28.嵌套查询 - 一对一和多对一

高级结果映射

一、关联映射(适用于一对一和多对一的情况)

1).创建pojo

(1)在Blog中创建Author对象

private Author author;

(2)创建Author的pojo

2).配置mapper

BlogMapper.java

<resultMap type="Blog" id="blogResultMap">
    <id column="id" property="id" jdbcType="INTEGER"></id>
    <association property="author" column="author_id" javaType="Author"
                 select="me.jing.mapper.AuthorMapper.selectAuthorById">
    </association>
</resultMap>
<select id="selectBlogById" parameterType="int" resultMap="blogResultMap">
    select * from blog where id = #{id}
</select>

AuthorMapper.java

<resultMap type="Author" id="authorResultMap">
    <id column="id" property="id" jdbcType="INTEGER"/>
    <result column="favourite_section" property="favouriteSection" jdbcType="VARCHAR"/>

</resultMap>

<select id="selectAuthorById" parameterType="int" resultMap="authorResultMap">
  select * from author where id = #{id}
</select>

3) 接口

(1) Blog

Blog selectBlogById(Integer id);

(2) Author

Author selectAuthorById(Integer id);

4) 测试

查询Blog列表时,执行的sql语句是 1+n,但是如果blog关联的author有重复的数据,那么从一级缓存中查询。

 /**
 * 通过id查具体的博客,查询时 再拿到作者id 去作者表查具体的作者信息
 */
@Test
public void testSelectBlogById() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    Blog blog = blogMapper1.selectBlogById(3);

    session1.close();

    System.out.println("结果已查询" + blog);
}

29.嵌套查询 - 显示信息列表

<select id="selectBlogList" resultMap="blogResultMap">
    select * from blog
</select>

List<Blog> selectBlogList();

@Test
public void testSelectBlogList() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    List<Blog> blogs = blogMapper1.selectBlogList();

    session1.close();

    System.out.println("结果已查询" + blogs);
}

30.嵌套查询-一对多的配置 31.嵌套查询-一对多的查询配置

执行流程:1.先执行单表查询,2.再利用单表查询的结果继续执行其他单表查询,3.最后组装结果映射。

通过post的id 查询post表的内容,同时通过此id查询评论表 comment 里的数据列表,即这篇文章的评论列表

sql:

create table post(id int,blog_id int,author_id int,
section varchar(20),subject varchar(20),draft varchar(20));

insert into post(id,blog_id,author_id,section,subject,draft) 
values('1','3','15','section','subject','draft');

create table comment(id int,
name varchar(20),comment varchar(20));

insert into comment(id,name,comment,post_id) 
values('1','评论name','我觉得很棒 评论','1');

PostMapper.xml

<resultMap type="Post" id="postResultMap">
    <id column="id" property="id" jdbcType="INTEGER"></id>
    <collection property="commentList" column="id" javaType="ArrayList" ofType="Comment"
                select="me.jing.mapper.CommentMapper.selectCommentListByPostId"></collection>
</resultMap>


<select id="selectPostById" parameterType="int" resultMap="postResultMap">
    select * from post where id = #{id}
</select>

CommentMapper.xml

<resultMap type="Comment" id="commentResultMap">
    <id column="id" property="id" jdbcType="INTEGER"></id>
</resultMap>

<!--通过post_id查询评论列表-->
<select id="selectCommentListByPostId"  parameterType="int" resultMap="commentResultMap">
    select * from comment where post_id = #{postId}
</select>

<select id="selectCommentById" parameterType="int" resultMap="commentResultMap">
    select * from comment where id = #{id}
</select>

测试:

 /**
 * 通过post的id 查询post表的内容,
 * 同时通过此id查询评论表 comment 里的数据列表,即这篇文章的评论列表
 */
@Test
public void selectPostById() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    PostMapper mapper = session1.getMapper(PostMapper.class);
    Post post = mapper.selectPostById(1);
    System.out.println("结果已查询" + post);
    session1.close();
}

32.高级结果映射-嵌套结果

1).先执行关联查询,一次性将所有数据都查询出来

2).再将所有查询出来的列组织成嵌套的结果对象

SELECT * FROM
blog b
LEFT JOIN author a
ON b.author_id = a.id;
SELECT
 b.id as blog_id,
 b.title as blog_title,
 b.author_id as blog_author_id,
 b.state as blog_state,
 b.featured as blog_featured,
 b.style as blog_style,
 
 a.id as author_id,
 a.username as author_username,
 a.password as author_password,
 a.email as author_email
 
FROM blog b
LEFT JOIN author a
ON b.author_id = a.id;

BlogMapper.xml

<resultMap id="blogResultMapNested" type="Blog">
    <id column="blog_id" property="id"/>
    <result column="blog_title" property="title"/>
    <result column="blog_state" property="state"/>
    <result column="blog_featured" property="featured"/>
    <result column="blog_style" property="style"/>
    <!--<result column="blog_author_id" property="author_id"/>-->
    <association property="author" column="blog_author_id" javaType="Author">
        <id column="author_id" property="id"/>
        <result column="author_username" property="username"/>
        <result column="author_password" property="password"/>
        <result column="author_email" property="email"/>
    </association>
</resultMap>
<!--32.高级结果映射-嵌套结果-->
<select id="selectBlogListNested" resultMap="blogResultMapNested">
    SELECT
     b.id as blog_id,
     b.title as blog_title,
     b.author_id as blog_author_id,
     b.state as blog_state,
     b.featured as blog_featured,
     b.style as blog_style,

     a.id as author_id,
     a.username as author_username,
     a.password as author_password

    FROM blog b
    LEFT JOIN author a
    ON b.author_id = a.id;
</select>

/**
 * 嵌套查询
 */
List<Blog> selectBlogListNested();

/**
 * 嵌套查询
 */
@Test
public void testSelectBlogListNested() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    List<Blog> blogs = blogMapper1.selectBlogListNested();
    session1.close();
    System.out.println("结果已查询2:" + blogs);
}

33.为什么要做扩展结果集|34.扩展结果的实现

1).mapper

BlogCustomMapper.xml

<sql id="baseColumn">
    b.id,
    b.`title`,
    b.`author_id`,
    b.`state`,
    b.`featured`,
    b.`style`,
    a.username as authorUsername
</sql>

<select id="selectBlogById" parameterType="int" resultType="BlogCustom">
    select
    <include refid="baseColumn"/>
    from blog b
    left join author a
    on b.author_id = a.id
    where b.id = #{id}
</select>

BlogCustomMapper.java

public interface BlogCustomMapper {
    BlogCustom selectBlogById(Integer id);
}

2)vo.BlogCustom.java

/**
 * 扩展Blog
 */
public class BlogCustom extends Blog {

    private static final long serialVersionUID = 1L;
    private String authorUsername;

    public String getAuthorUsername() {
        return authorUsername;
    }

    public void setAuthorUsername(String authorUsername) {
        this.authorUsername = authorUsername;
    }

    @Override
    public String toString() {
        return "BlogCustom{" +
                "authorUsername='" + authorUsername + ''' +
                '}';
    }
}

<!--定义别名-->
<typeAliases>
    <!--<typeAlias type="pojo.Blog" alias="Blog"/>-->
    <package name="me.jing.pojo"/>
    <package name="me.jing.pojo.vo"/>
</typeAliases>

3)测试

/**
 * 通过id查具体的博客,查询时 再拿到作者id 去作者表查具体的作者 username
 */
@Test
public void testSelectBlogById() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogCustomMapper mapper = session1.getMapper(BlogCustomMapper.class);
    BlogCustom blog = mapper.selectBlogById(3);

    session1.close();

    System.out.println("结果已查询" + blog);
}

35.高级结果映射 - 构造方式映射

Bolg.xml

public Blog(Integer id, String title) {
    this.id = id;
    this.title = title;
    System.out.println("构造函数调用-----");
}

<!--构造方法映射-->
<resultMap id="blogResultMapConstructor" type="Blog">
    <constructor>
        <idArg column="id" javaType="int"/>
        <arg column="title" javaType="string"/>
    </constructor>
</resultMap>
<select id="selectBlogByIdConstructor" parameterType="int" resultMap="blogResultMapConstructor">
  select * from blog where id = #{id}
</select>

 /**
 * 构造方式映射
 */
Blog selectBlogByIdConstructor(Integer id);

 /**
 * 构造方式映射
 */
@Test
public void testSelectBlogByIdConstructor() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    Blog blog = blogMapper1.selectBlogByIdConstructor(3);
    session1.close();
    System.out.println("结果已查询:" + blog);
}

36.鉴别器

CREATE TABLE `vehicle`(
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`vin` VARCHAR(50) COLLATE utf8_bin DEFAULT NULL,
	`year` YEAR(4) DEFAULT NULL,
	`make` VARCHAR(50) COLLATE utf8_bin DEFAULT NULL,
	`model` VARCHAR(50) COLLATE utf8_bin DEFAULT NULL,
	`color` VARCHAR(50) COLLATE utf8_bin DEFAULT NULL,
	`vehicle_type` INT(11) DEFAULT NULL,
	`door_count` INT(11) DEFAULT NULL,
	`all_wheel_drive` TINYINT(1) DEFAULT NULL,
	PRIMARY KEY(`id`)
 ) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
VehicleMapper.xml

<resultMap type="Vehicle" id="vehicleResultMap">
    <id column="id" property="id" jdbcType="INTEGER"/>
    <discriminator javaType="int" column="vehicle_type">
        <case value="1" resultType="Car">
            <result column="door_count" property="doorCount"/>
        </case>
        <case value="2" resultType="Suv">
            <result column="all_wheel_drive" property="allWheelDrive"/>
        </case>
    </discriminator>
</resultMap>


<select id="selectVehicleById" parameterType="int" resultMap="vehicleResultMap">
    select * from vehicle where id = #{id}
</select>

Vehicle selectVehicleById(Integer id);

pojo

public class Vehicle {

    private Integer id;
    private Integer vehicle_type;
    private String vin;
    private String make;
    private String model;
    private String color;
    private Boolean all_wheel_drive;
}

public class Suv extends Vehicle {

    // 全轮驱动 awd
    private Boolean allWheelDrive;

    public Suv() {
    }

    public Boolean getAllWheelDrive() {
        return allWheelDrive;
    }

    public void setAllWheelDrive(Boolean allWheelDrive) {
        this.allWheelDrive = allWheelDrive;
    }

    @Override
    public String toString() {
        return "Suv{" +
                "allWheelDrive=" + allWheelDrive +
                '}';
    }
}

public class Car extends Vehicle {

    // 门的数量
    private Integer doorCount;

    public Integer getDoorCount() {
        return doorCount;
    }

    public void setDoorCount(Integer doorCount) {
        this.doorCount = doorCount;
    }

    @Override
    public String toString() {
        return "Car{" +
                "doorCount=" + doorCount +
                '}';
    }
}

测试:

 /**
 * 鉴别器
 */
@Test
public void testSelectVehicleById() {
    SqlSession session1 = MyBatisUtil.getSqlSession();
    VehicleMapper mapper = session1.getMapper(VehicleMapper.class);
    Vehicle vehicle = mapper.selectVehicleById(1);
    Vehicle vehicle2 = mapper.selectVehicleById(2);

    if (vehicle instanceof Car) {
        Car car = (Car) vehicle;
        Suv suv = (Suv) vehicle2;
        System.out.println("car:" + car);
        System.out.println("suv:" + suv);
    } else {
        Car car = (Car) vehicle2;
        Suv suv = (Suv) vehicle;
        System.out.println("car:" + car);
        System.out.println("suv:" + suv);
    }

    System.out.println("vehicle:" + vehicle);
    System.out.println("vehicle2:" + vehicle2);
    session1.close();
}

37.延迟加载 - 不配置延迟加载的情况

测试一:

没有配置任何选项,执行两遍查询,性能比较低

无论是否查询blog的任意属性,都会执行author的任何查询,就是说 始终会执行两次查询。

查询blog----
Opening JDBC Connection
Created connection 504858437.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1e178745]
==>  Preparing: select * from blog where id = ? 
==> Parameters: 3(Integer)
====>  Preparing: select * from author where id = ? 
====> Parameters: 15(Integer)
<====      Total: 1
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1e178745]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1e178745]
Returned connection 504858437 to pool.
查询blog的title属性----
Android开发艺术探索
查询blog的author属性----
景彬
结果已查询

38.延迟加载 - 配置lazyloadingenabled

测试二:

如果不查询blog的任意属性,那么不会执行author的查询

配置了全局属性:

<settings>
    <!--<setting name="useGeneratedKeys" value="true"/>-->
    <!--延迟加载 配置lazyloadingenabled-->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

测试:

/**
 * 测试延迟加载
 * 没有配置 lazyLoadingEnabled 时,会始终执行两次查询
 */
@Test
public void testSelectBlogByIdLazyLoading() {

    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    System.out.println("查询blog----");
    Blog blog = blogMapper1.selectBlogById(3);
    session1.close();

//        System.out.println("查询blog的title属性----");
//        System.out.println(blog.getTitle());
//        System.out.println("查询blog的author属性----");
//        System.out.println(blog.getAuthor().getUsername());
    System.out.println("结果已查询");
}

日志打印:

查询blog----
Opening JDBC Connection
Created connection 210156003.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
==>  Preparing: select * from blog where id = ? 
==> Parameters: 3(Integer)
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Returned connection 210156003 to pool.
结果已查询

39.延迟加载 - 测试用例1和2的比较

40.延迟加载 - 积极的延迟加载

延迟加载:用属性就加载,不用就不加载。

积极的延迟加载:只要用属性,就把所有要查询的属性sql全部执行一遍。

测试三:

只要查询bolg的任意属性,都会执行author数据的查询

配置了全局属性(同测试2的配置):

<settings>
    <!--<setting name="useGeneratedKeys" value="true"/>-->
    <!--延迟加载 配置lazyloadingenabled-->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

测试:

/**
 * 测试延迟加载
 * 没有配置 lazyLoadingEnabled 时,会始终执行两次查询
 */
@Test
public void testSelectBlogByIdLazyLoading() {

    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    System.out.println("查询blog----");
    Blog blog = blogMapper1.selectBlogById(3);
    session1.close();

    System.out.println("查询blog的title属性----");
    System.out.println(blog.getTitle());
//        System.out.println("查询blog的author属性----");
//        System.out.println(blog.getAuthor().getUsername());
    System.out.println("结果已查询");
}

41.延迟加载 - 非积极延迟加载

测试四:

延迟加载,并且是非积极的。如果需要访问blog的非author属性,则不执行关联的author查询。

配置了全局属性:

配置后,没有调用 blog.getAuthor() 属性,就只会执行一次,调用 blog.getAuthor() 属性才回再执行查询author表一次。

<!--具体的insert也得配置 keyProperty-->
<settings>
    <setting name="useGeneratedKeys" value="true"/>
    <!--延迟加载 配置lazyloadingenabled-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--非积极的延迟加载-->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

测试:

 /**
 * 测试延迟加载
 */
@Test
public void testSelectBlogByIdLazyLoading() {

    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    System.out.println("查询blog----");
    Blog blog = blogMapper1.selectBlogById(3);
    session1.close();

    System.out.println("查询blog的title属性----");
    System.out.println(blog.getTitle());
//        System.out.println("查询blog的author属性----");
//        System.out.println(blog.getAuthor().getUsername());
    System.out.println("结果已查询");
}

打印:

查询blog----
Opening JDBC Connection
Created connection 210156003.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
==>  Preparing: select * from blog where id = ? 
==> Parameters: 3(Integer)
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Returned connection 210156003 to pool.
查询blog的title属性----
Android开发艺术探索
结果已查询

测试五:

配置了全局属性 同配置四

延迟加载,并且是不积极的。如果访问了blog的author属性,则执行关联的author查询

测试:

/**
 * 测试延迟加载
 */
@Test
public void testSelectBlogByIdLazyLoading() {

    SqlSession session1 = MyBatisUtil.getSqlSession();
    BlogMapper blogMapper1 = session1.getMapper(BlogMapper.class);
    System.out.println("查询blog----");
    Blog blog = blogMapper1.selectBlogById(3);
    session1.close();

    System.out.println("查询blog的title属性----");
    System.out.println(blog.getTitle());
    System.out.println("查询blog的author属性----");
    System.out.println(blog.getAuthor().getUsername());
    System.out.println("结果已查询");
}

打印:

查询blog----
Opening JDBC Connection
Created connection 210156003.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
==>  Preparing: select * from blog where id = ? 
==> Parameters: 3(Integer)
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Returned connection 210156003 to pool.
查询blog的title属性----
Android开发艺术探索
查询blog的author属性----
Opening JDBC Connection
Checked out connection 210156003 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
==>  Preparing: select * from author where id = ? 
==> Parameters: 15(Integer)
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c86b9e3]
Returned connection 210156003 to pool.
景彬
结果已查询