前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SSM第六讲 MyBatis的高级特性

SSM第六讲 MyBatis的高级特性

作者头像
易兮科技
发布2020-09-27 17:13:44
8510
发布2020-09-27 17:13:44
举报
文章被收录于专栏:CSDN博客专栏

MyBatis的高级特性

1 学习目标

1,理解Mybatis多对多关系 2,掌握Mybatis的延迟加载 3,掌握Mybatis缓存 4,掌握逆向工程生成mapper和实体类

2 Mybatis 延迟加载

2.1 延迟加载介绍

通过前面的学习,我们已经掌握了 Mybatis 中一对一,一对多,多对多关系的配置及实现,可以实现对象的关联查询。实际开发过程中有时候我们并不需要在加载用户信息时,就加载他的账户信息。 而是在使用用户账号的时候,再向数据库查询,此时就是我们所说的延迟加载。

即时加载:

代码语言:javascript
复制
// 条件查询
@Test
public void findAll() throws Exception {
    //  SELECT u.*,a.* FROM USER u LEFT JOIN account a ON a.UID=u.id;
    //  执行userDao.findAll()方法,执行查询用户、账户信息,一次加载所有的数据,这种叫做及时加载。
    List<User> list = userDao.findAll();
    for(User u : list){
        System.out.println(u);
        System.out.println(u.getAccounts());
    }
}

2.2 何为延迟加载?

延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.

好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。 坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

如何实现延迟加载:前面实现多表操作时,我们使用了resultMap 来实现一对一,一对多,多对多关系的操作。主要是通过 association、 collection 实现一对一及一对多映射。 association、 collection 具备延迟加载功能。

思考:什么是及时加载?什么是延时加载?

及时加载:一次加载所有数据。

延迟加载:也叫做懒加载,再需要用到数据时候再查询数据。

2.3 一对一实现延时加载

2.3.1 实现需求

​ 需求:查询Account账户信息时候,也要显示User用户信息,但User用户信息用到的时候再向数据库发送查询语句。

数据库中实现:

代码语言:javascript
复制
-- 一对一延迟加载
-- 需求:查询账户,同时也要显示用户。但用户信息是再用到的时候再查询.
-- 实现过程:
-- 1) 查询账户
SELECT * FROM account
-- 3) 使用用户对象数据时候,查询用户
SELECT * FROM USER WHERE id=46 

2.3.2 entity

代码语言:javascript
复制
public class Account {
    private int accountId;
    private int uid;
    private double money;
    // 一个账户对应一个用户
    private User user;
}
代码语言:javascript
复制
public class User {
    private int  id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    // 一个用户,对应多个账户
    private List<Account> accounts;
}

2.3.3 dao

代码语言:javascript
复制
public interface AccountMapper {
    /**
     * 查询账户
     */
    List<Account> findAll();
}
代码语言:javascript
复制
public interface UserMapper {
    /**
     * 根据用户id查询
     */
    User findById(int id);
}

2.3.4 UserMapper.xml

代码语言:javascript
复制
<?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.itdfbz.dao.UserMapper" >
   <select id="findById" resultType="user">
      select * from user where id=#{id}
  </select>
</mapper>

2.3.5 AccountMapper.xml 延时加载关键配置

代码语言:javascript
复制
<?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.itdfbz.dao.AccountMapper">

   <resultMap id="accountResultMap" type="account">
       <!--1. 账户信息映射-->
       <id property="accountId" column="accountId"></id>
       <result property="uid" column="uid"></result>
       <result property="money" column="money"></result>
       <!--2. 延时加载的方式,查询账户的用户-->
       <!--select 延时加载的语句id(名称空间.方法)-->
       <!--column="uid" 表外键字段-->
       <association property="user" javaType="user" column="uid"
                    select="com.itdfbz.dao.UserMapper.findById"></association>
   </resultMap>

   <select id="findAll" resultMap="accountResultMap">
       SELECT * FROM account
   </select>
</mapper>

2.3.6 测试,观察问题

代码语言:javascript
复制
@Test
public void test1() {
    AccountMapper accountMapper = session.getMapper(AccountMapper.class);
    List<Account> accountList = accountMapper.findAll();
    for (Account account : accountList) {
        System.out.println(account.getAccountId());
    }
}

​ 执行结果:

在这里插入图片描述
在这里插入图片描述

​ 发现,我们在测试中,只输出了账户信息,并没有使用用户信息,但还是查询了用户,并没有应用懒加载。如何解决?

2.3.7 解决方案

2.3.7.1 解决1:

查看mybatis官网

代码语言:javascript
复制
http://www.mybatis.org/mybatis-3/zh/configuration.html

打开页面,找到settings

在这里插入图片描述
在这里插入图片描述

然后在SqlMapConfig.xml中配置开启懒加载支持

在这里插入图片描述
在这里插入图片描述

最后,再次执行测试

1.测试类中没有使用Account账户的User信息

代码语言:javascript
复制
@Test
public void find() throws  Exception{
    List<Account> list = accountDao.findAccounts();
    for (Account a : list) { 
        System.out.println(a.getAccountId() + ","+a.getUid() + "," +a.getMoney());
    }
}

测试结果

在这里插入图片描述
在这里插入图片描述

2.测试类中有使用Account账户的User信息

代码语言:javascript
复制
@Test
public void test1() {
    AccountMapper accountMapper = session.getMapper(AccountMapper.class);
    List<Account> accountList = accountMapper.findAll();
    for (Account account : accountList) {
        System.out.println(account.getAccountId()+"----"+account.getUser());
    }
}

测试结果: 可以看到使用对象数据的时候,才向数据库发送查询的SQL

在这里插入图片描述
在这里插入图片描述
2.3.7.2 解决2:

(1) 注释SqlMapConfig.xml中全局懒加载的的开启

在这里插入图片描述
在这里插入图片描述

(2) 修改映射文件

在这里插入图片描述
在这里插入图片描述

通过打印的SQL可以看到,懒加载一样生效:

在这里插入图片描述
在这里插入图片描述

2.3.8 小结

通过本示例,我们可以发现 Mybatis 的延迟加载对于提升软件性能这是一个不错的手段。实现的关键: association 的配置

代码语言:javascript
复制
<resultMap id="accountResultMap" type="account">
    <!--1. 账户信息映射-->
    <id property="accountId" column="accountId"></id>
    <result property="uid" column="uid"></result>
    <result property="money" column="money"></result>
    <!--2. 延时加载的方式,查询账户的用户-->
    <!--select 延时加载的语句id(名称空间.方法)-->
    <!--column="uid" 表外键字段(要传入findById方法的参数)-->
    <!--
        fetchType:懒加载设置
            lazy:开启懒加载
            eager:立即加载
    -->
    <association property="user" javaType="user" column="uid" fetchType="lazy"
                 select="com.itdfbz.dao.UserMapper.findById"></association>
</resultMap>

2.4 一对多实现延时加载

2.4.1 需求

查询用户信息,再使用用户账户时候再查询账户。

数据库实现:

代码语言:javascript
复制
-- 一对多延迟加载
-- 1) 查询用户
SELECT * FROM USER;
-- 2) 使用用户的账户对象数据时候再查询账户
SELECT * FROM account WHERE uid=46;

2.4.2 entity

代码语言:javascript
复制
public class User {
   private Integer id;
   private String username;
   private Date birthday;
   private String sex;
   private String address;
   // 一个用户,对应多个账户
   private List<Account> accounts;
}

2.4.3 dao

代码语言:javascript
复制
public interface UserMapper {
    /**
     * 查询所有用户
     */
    List<User> findAll();
}
代码语言:javascript
复制
public interface AccountMapper {
    /**
     * 根据用户的id查询
     */
    List<Account> findAccountByUserId(Integer userId);
}

2.4.4 AccountMapper.xml

代码语言:javascript
复制
<!--根据用户,查询其下的多个账户-->
<select id="findAccountByUserId" resultType="account">
   select * from account where uid=#{userId}
</select>

2.4.5 UserMapper.xml 延时加载关键配置

代码语言:javascript
复制
<resultMap id="userResultMap" type="user">
   <id property="id" column="id"></id>
   <result column="username" property="username"></result>
   <result column="sex" property="sex"></result>
   <result column="address" property="address"></result>

   <!--
       collection:一对多映射
           property:JavaBean中的实体类的多方属性名
           column: 本表的id(要传入findAccountByUserId的参数)
           ofType:属性类型
           select:映射的方法
   -->
   <collection property="accounts" column="id"
               ofType="account"
               select="com.itdfbz.dao.AccountMapper.findAccountByUserId">
   </collection>
</resultMap>
<select id="findAll" resultMap="userResultMap">
   select * from user
</select>

2.4.6 开启延时加载支持

在这里插入图片描述
在这里插入图片描述

2.4.7 测试

代码语言:javascript
复制
@Test
public void test1() {
    UserMapper userMapper = session.getMapper(UserMapper.class);
    List<User> userList = userMapper.findAll();
    for (User user : userList) {
        System.out.println(user.getSex());
    }
}

测试结果:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
// 查询用户
@Test
public void find() throws  Exception{
    List<User> list = userDao.findUsers();
    for (User u : list) {
        System.out.println(u.getId() + "," + u.getUsername());
        System.out.println(u.getAccounts());
    }
}
在这里插入图片描述
在这里插入图片描述

2.5. 注解实现延迟加载开发

2.5.1 注解实现一对一映射及延迟加载

在这里插入图片描述
在这里插入图片描述
2.5.1.1 entity

(1) 账户与用户,一对一

代码语言:javascript
复制
public class Account implements Serializable {
    private int accountId;
    
    private int uid;
    
    private double money;
    
    //一个账号对应一个账户
    private User user;
}

(2) 用户与账户,一对多

代码语言:javascript
复制
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    
    //一个用户对应多个账号
    private List<Account> accountList;
}
2.5.1.2 dao
代码语言:javascript
复制
public interface UserMapper {

    // 根据用户id查询
    @Select("select * from user where id=#{id}")
    User findById(int id);
}
代码语言:javascript
复制
package com.itdfbz.dao;

import com.itdfbz.entity.Account;
import com.itdfbz.entity.User;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

public interface AccountMapper {

    /*
    *
    * @One:代表一对一
    * select:要映射到本表属性的数据提供方法
    * user:本类中要映射的属性名
    * uid:外键,要传入findById方法的参数
    * fetchType: 配置懒加载
    *   LAZY:懒加载
    *   EAGER:立即加载
    *
    * */
    @Select("select * from account where accountId=#{id}")
    @Results({
            @Result(id=true,property = "accountId",column = "accountId"),
            @Result(property = "uid",column = "uid"),
            @Result(property = "money",column = "money"),
            @Result(property = "user",column = "uid",javaType = User.class,
                one = @One(select = "com.itdfbz.dao.UserMapper.findById",fetchType = FetchType.EAGER )

            )
    })
    Account findById(Integer id);
}
2.5.1.3 测试
代码语言:javascript
复制
@Test
public void test1(){
    AccountMapper mapper = session.getMapper(AccountMapper.class);
    Account account = mapper.findById(1);
    System.out.println(account.getAccountId());
    System.out.println(account.getUser());
}

2.5.2 注解实现一对多映射及延迟加载

2.5.1.1 dao 接口

代码语言:javascript
复制
/**
 * many:代表一对多
 * accountList:代表本类中的多方属性名
 * id:要传入findByUserId的参数
 * List.class:多方集合类型
 * FetchType.LAZY:懒加载
 * 
 */
@Select("select * from user where id=#{id}")
@Results({
        @Result(id = true,property = "id",column = "id"),
        @Result(property = "username",column = "username"),
        @Result(property = "birthday",column = "birthday"),
        @Result(property = "sex",column = "sex"),
        @Result(property = "address",column = "address"),
        @Result(property = "accountList",column = "id",javaType = List.class,
                many=@Many(select = "com.itdfbz.dao.AccountMapper.findByUserId",fetchType = FetchType.LAZY)
        )
})

2.5.1.2 测试

代码语言:javascript
复制
@Test
public void test2() {
    UserMapper userMapper = session.getMapper(UserMapper.class);

    User user = userMapper.findById(46);
    System.out.println(user.getUsername());
    List<Account> accountList = user.getAccountList();
    for (Account account : accountList) {
        System.out.println(account);
    }

}

3 Mybatis 缓存机制

3.1 缓存介绍

像大多数的持久化框架一样, Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。Mybatis 中缓存分为一级缓存,二级缓存。

在这里插入图片描述
在这里插入图片描述

从图中可以看出什么 ? 一级缓存是基于SqlSessoion的缓存,一级缓存的内容不能跨sqlsession。由mybatis自动维护。二级缓存是基于映射文件的缓存,缓存范围比一级缓存更大。不同的sqlsession可以访问二级缓存的内容。哪些数据放入二级缓存需要自己指定。

3.2 一级缓存测试

同一个SqlSession的一级缓存的测试:

代码语言:javascript
复制
@Test
public void test1() {
    SqlSession session = factory.openSession();

    UserMapper userMapper1 = session.getMapper(UserMapper.class);

    User user1 = userMapper1.findById(41);   //发送sql查询出来,放入一级缓存
    System.out.println(user1.getUsername());
    
    User user2 = userMapper1.findById(41);       //直接从一级缓存中查询(不发送sql)
    System.out.println(user2.getUsername());

    session.close();            //session关闭(此session的一级缓存销毁)

    SqlSession session2 = factory.openSession();
    UserMapper userMapper2 = session2.getMapper(UserMapper.class);
    User user3 = userMapper2.findById(41);          //发送sql查询一级缓存

    System.out.println(user3.getUsername());

}

​ 测试结果分析:

在这里插入图片描述
在这里插入图片描述

小结

在这里插入图片描述
在这里插入图片描述

tips:如果更改了一级缓存中的任何数据那么一级缓存会被清空

3.3 二级缓存

3.3.1 介绍

二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession 的。

二级缓存结构图:

在这里插入图片描述
在这里插入图片描述

首先开启 mybatis的二级缓存。 sqlSession1去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。sqlSession2去查询与 sqlSession1 相同的用户信息, 首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。如果 SqlSession3 去执行相同 mapper 映射下 sql,执行 commit 提交, 将会清空该 mapper映射下的二级缓存区域的数据。

3.3.2 测试二级缓存

3.3.2.1 第一步:开启二级缓存
在这里插入图片描述
在这里插入图片描述

因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true代表开启二级缓存;为 false 代表不开启二级缓存。

官网介绍:

在这里插入图片描述
在这里插入图片描述
3.3.2.2 第二步:配置mapper
代码语言:javascript
复制
<mapper namespace="com.itdfbz.dao.UserMapper">

    <!--
        cache: 表示当前这个mapper对象的查询结果会放入二级缓存
        userCache: 表示当前sql语句查询结果是否被存入二级缓存(首先应该配置<cache>标签)
            true:存入二级缓存(默认值)
            false:不存入二级缓存
    -->
    <cache></cache>
    <select id="findById" parameterType="int" resultType="user" useCache="true">
        select * from user where id=#{id}
    </select>
</mapper>

将 UserMapper.xml 映射文件中的标签中设置 useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。 注意: 针对每次查询都需要最新的数据 sql,要设置成useCache=false,禁用二级缓存。

3.3.2.3 第三步:实体类实现Serializable

当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口:

在这里插入图片描述
在这里插入图片描述
3.3.2.4 测试
代码语言:javascript
复制
public void test1() throws IOException {

    InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

    SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);

    SqlSession session1 = factory.openSession();

    UserMapper mapper1 = session1.getMapper(UserMapper.class);

    User user1 = mapper1.findById(41);          //发送sql查询,放入一级缓存
    System.out.println(user1);

    session1.close();           //关闭一级缓存,并将一级缓存的内容写入二级缓存

    SqlSession session2 = factory.openSession();
    UserMapper mapper2 = session2.getMapper(UserMapper.class);

    User user2 = mapper2.findById(41);          //从二级缓存查询(反序列化)直接返回(此时一级缓存还是空的)
    User user3 = mapper2.findById(41);      //查询二级缓存(反序列化)

    System.out.println(user3==user2);       //false

    session2.close();
    is.close();
}

测试结果

在这里插入图片描述
在这里插入图片描述

二级缓存执行原理:

在这里插入图片描述
在这里插入图片描述

tips:如果更改了任何数据那么二级缓存和一级缓存都将被清空

3.4 MyBatis缓存深入

一级缓存测试:

代码语言:javascript
复制
@Test
public void test2() throws IOException {
    InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);

    SqlSession session1 = factory.openSession();

    UserMapper mapper1 = session1.getMapper(UserMapper.class);

    User user1 = mapper1.findById(41);          //发送sql查询,放入一级缓存
    user1.setAddress("NanChang");
    mapper1.update(user1);              //清空一级缓存 update delete 

    User user2 = mapper1.findById(41);          //再次发送sql

    session1.close();           //关闭一级缓存,并将一级缓存的内容写入二级缓存
}

二级缓存测试:

代码语言:javascript
复制
@Test
public void test3() throws IOException {
    InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);

    SqlSession session1 = factory.openSession();

    UserMapper mapper1 = session1.getMapper(UserMapper.class);

    User user1 = mapper1.findById(41);          //发送sql查询,放入一级缓存
    System.out.println(user1);

    session1.close();           //关闭一级缓存,并将一级缓存的内容写入二级缓存

    SqlSession session2 = factory.openSession();
    UserMapper mapper2 = session2.getMapper(UserMapper.class);

    User user2 = mapper2.findById(41);          //从二级缓存查询(反序列化)直接返回(此时一级缓存还是空的)
    mapper2.update(user2);                      //清空二级缓存、一级缓存

    User user3 = mapper2.findById(41);      //查询二级缓存--->一级缓存--->数据库
    User user4 = mapper2.findById(41);      //查询二级缓存(空的)---->查询一级缓存---返回结果
    System.out.println(user3 == user4);       //true

    session2.close();
    is.close();
}

3.5 MyBatis缓存总结

一级缓存和二级缓存的执行顺序为:二级缓存---->一级缓存---->数据库

查询语句始终是由一级缓存发送的

一级缓存默认由MyBatis维护,我们只需了解使用即可

二级缓存需要我们开启:

1、在SqlMapConfig.xml中开启二级缓存(默认开启)

代码语言:javascript
复制
<settings>
    <!--开启二级缓存,默认是开启状态 false为关闭二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

2、在mapper文件中加入标签代表本mapper文件的所有查询结果放入二级缓存,并保证useCache不为false(默认为true)

代码语言:javascript
复制
<cache></cache>
<select id="findById" parameterType="int" resultType="user" useCache="true">
    select * from user where id=#{id}
</select>

3、MyBatis的二级缓存默认采用序列化/反序列化来保证对象的存取,所以所有的entity对象都应该实现serializable接口

3.6 mybatis自身缓存的弊

A. 分布式的项目架构下,也就是最少使用两个服务器,如果使用两个服务器mybatis的缓存技术就无法在两个服务器通用就是,也就是两个服务器无法达到数据通用,比如我在一个服务器存储了我的信息,但是我转跳到另一个服务器那使用mybatis数据就是需要从新加载,这里就是一个非常大的问题。

B. mybatis无法实现细粒度的缓存管理,当你查询大量数据的时候而且将数据存储到mybatis二级缓存中的时候,但是一旦队一个数据操作增加,删除,修改,这里二级缓存就全部清空,而mybatis无法实现对这里单个信息的修改

问题:如何解决这个缺陷?

答:使用第三方的缓存如:ehcache、redis

在这里插入图片描述
在这里插入图片描述

3.7.ehcache的整合配置

ehcache需要slf4j这个日志包支持

3.7.1.导入包

代码语言:javascript
复制
<dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.35</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-ehcache</artifactId>
        <version>1.1.0</version>
    </dependency>

3.7.2.引入缓存配置文件

classpath下添加:ehcache.xml(EhcacheCache实现类的默认配置文件)

代码语言:javascript
复制
<?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">
<!--diskStore:缓存数据持久化的目录 地址  -->
<diskStore path="F:\temp\cache"/>
<!--
maxElementsInMemory:内存中最大缓存对象数  
    maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大  
    eternal:Element是否永久有效,一但设置了,timeout将不起作用  
    overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中  
    diskPersistent:是否缓存虚拟机重启期数据
    timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大  
    timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,
    也就是element存活时间无穷大   
    memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),
    可选的有LFU(最不常使用)和FIFO(先进先出)
 -->
<defaultCache 
maxElementsInMemory="1000" 
maxElementsOnDisk="10000000" 
eternal="false" 
overflowToDisk="true" 
diskPersistent="false" 
timeToIdleSeconds="120" 
timeToLiveSeconds="120" 
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>

3.7.3.开启ehcache缓存

EhcacheCache 是ehcache对Cache接口的实现;修改mapper.xml文件,在cache标签的type属性中指定EhcacheCache。覆盖其默认实现

根据需求调整缓存参数:(根据条件对EhcacheCache实现类的参数调整,可选)

代码语言:javascript
复制
    <cache type="org.mybatis.caches.ehcache.EhcacheCache" >
       <!--最大的空闲时间  -->
       <property name="timeToIdleSeconds" value="10000"/>
       <!-- 最大的在线时间 -->
       <property name="timeToLiveSeconds" value="20000"/>
       <!-- 内存的大小 b字节 m1 =1024k 1k=1024b -->
       <property name="maxEntriesLocalHeap" value="2000000"/>
       <!-- 文件的大小 b字节-->
       <property name="maxEntriesLocalDisk" value="20000000"/>
       <!-- 算法 LRU:最少使用优先, "LFU" or "FIFO:先进先出 -->
       <property name="memoryStoreEvictionPolicy" value="LRU"/>
    </cache> 

结果:观察缓存命中,且在写入磁盘配置路径处可以看到生成文件

在这里插入图片描述
在这里插入图片描述

4 逆向工程

idea的逆向工程,通过maven的插件来实现

4.1.创建maven项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2. 引入插件mybatis-generator-maven-plugin

在maven项目的pom.xml 添加mybatis-generator-maven-plugin 插件

代码语言:javascript
复制
<build>

    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.2</version>
        </plugin>
    </plugins>
</build>

更新下载依赖包

在这里插入图片描述
在这里插入图片描述

4.3. generatorConfig.xml

在maven项目下的src/main/resources 目录下建立名为 generatorConfig.xml的配置文件,作为mybatis-generator-maven-plugin 插件的执行目标,模板如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!--引入数据库配置文件以解耦-->
    <properties resource="mybatis.properties"/>
    <!-- mysql jar 文件位置 -->
    <classPathEntry location="D:\.m2\repository\mysql\mysql-connector-java\5.1.35\mysql-connector-java-5.1.35.jar" />
    
    <context id="testTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释,true:是;false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}" userId="${jdbc.username}"
                        password="${jdbc.password}">
        </jdbcConnection>
        <!--Oracle数据库的连接信息-->
        <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
            connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
            userId="yycg"
            password="yycg">
        </jdbcConnection> -->

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
            NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetProject:生成PO类的位置 -->
        <javaModelGenerator targetPackage="cn.nyse.entity"
                            targetProject="src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- targetProject:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="cn.nyse.mapper"
                         targetProject="src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!--
        targetPackage:mapper接口生成的位置,遵循MyBatis规范,让mapper.xml
        和mapper.java在同一目录下
        ANNOTATEDMAPPER:注解方式
        XMLMAPPER:xml方式
         -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="cn.nyse.mapper"
                             targetProject="src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- 指定数据库表 -->
        <table tableName="${jdbc.table.items}"></table>

      

        <!-- 有些表的字段需要指定java类型
         <table schema="" tableName="">
            <columnOverride column="" javaType="" />
        </table> -->
    </context>
</generatorConfiguration>

mybatis.properties:

代码语言:javascript
复制
<!--jdbc连接数据库配置信息-->
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis
jdbc.username = root
jdbc.password = 123456

#数据库中要生成的表
jdbc.table.items = student

项目目录如下

在这里插入图片描述
在这里插入图片描述

4.4. 使用maven运行mybatis-generator-maven-plugin插件

在这里插入图片描述
在这里插入图片描述

观察控制台输出结果:

在这里插入图片描述
在这里插入图片描述

生成的文件:

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
    <!-- 有些表的字段需要指定java类型
     <table schema="" tableName="">
        <columnOverride column="" javaType="" />
    </table> -->
</context>
代码语言:javascript
复制
mybatis.properties:

```properties
<!--jdbc连接数据库配置信息-->
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis
jdbc.username = root
jdbc.password = 123456

#数据库中要生成的表
jdbc.table.items = student

项目目录如下

在这里插入图片描述
在这里插入图片描述

4.4. 使用maven运行mybatis-generator-maven-plugin插件

在这里插入图片描述
在这里插入图片描述

观察控制台输出结果:

在这里插入图片描述
在这里插入图片描述

生成的文件:

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MyBatis的高级特性
  • 1 学习目标
  • 2 Mybatis 延迟加载
    • 2.1 延迟加载介绍
      • 2.2 何为延迟加载?
        • 2.3 一对一实现延时加载
          • 2.3.1 实现需求
          • 2.3.2 entity
          • 2.3.3 dao
          • 2.3.4 UserMapper.xml
          • 2.3.5 AccountMapper.xml 延时加载关键配置
          • 2.3.6 测试,观察问题
          • 2.3.7 解决方案
          • 2.3.8 小结
        • 2.4 一对多实现延时加载
          • 2.4.1 需求
          • 2.4.2 entity
          • 2.4.3 dao
          • 2.4.4 AccountMapper.xml
          • 2.4.5 UserMapper.xml 延时加载关键配置
          • 2.4.6 开启延时加载支持
          • 2.4.7 测试
        • 2.5. 注解实现延迟加载开发
          • 2.5.1 注解实现一对一映射及延迟加载
          • 2.5.2 注解实现一对多映射及延迟加载
          • 2.5.1.1 dao 接口
          • 2.5.1.2 测试
      • 3 Mybatis 缓存机制
        • 3.1 缓存介绍
          • 3.2 一级缓存测试
            • 3.3 二级缓存
              • 3.3.1 介绍
              • 3.3.2 测试二级缓存
            • 3.4 MyBatis缓存深入
              • 一级缓存测试:
              • 二级缓存测试:
            • 3.5 MyBatis缓存总结
              • 3.6 mybatis自身缓存的弊
                • 3.7.ehcache的整合配置
                  • 3.7.1.导入包
                  • 3.7.2.引入缓存配置文件
                  • 3.7.3.开启ehcache缓存
              • 4 逆向工程
                • 4.1.创建maven项目
                  • 4.2. 引入插件mybatis-generator-maven-plugin
                    • 4.3. generatorConfig.xml
                      • 4.4. 使用maven运行mybatis-generator-maven-plugin插件
                        • 4.4. 使用maven运行mybatis-generator-maven-plugin插件
                        相关产品与服务
                        数据保险箱
                        数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档