Mybatis个人学习

相关练习源码:
https://gitee.com/zhi-shou/java_-my-batis

1、简介

1.1、什么是 MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

如何获得MyBATIS:

maven仓库

<dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
</dependency>

1.2、持久化

数据持久化
  • 持久化就是将程序的数据在持久状态和瞬时状态转换的过程
  • 内存:断电即失
  • 数据库(jdbc) io文件持久化
为什么需要持久化?

有一些对象,不能让他丢掉。

1.3、持久层

Dao层,Service层,Controller层…

  • 完成持久化工作的代码块
  • 层界限十分明显

1.4、为什要需要MyBatis

  • 方便
  • 传统的JDBC代码太复杂、简化、框架、自动化。
  • 帮助将数据存入到数据库中

2、搭建第一个MyBatis程序(day01)

思路:搭建环境—>导入MyBatis---->编写代码----->测试

2.1、搭建环境

搭建数据库

2.2、创建一个模块

  • 编写mybatis
  • 配置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>
    <!--环境配置,连接的数据库,这里使用的是MySQL-->
    <environments default="mysql">
        <environment id="mysql">
            <!--指定事务管理的类型,这里简单使用Java的JDBC的提交和回滚设置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 指连接源配置,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useSSL=true&amp;useUnicode=true&amp;CharacterEncoding=UTF-8"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--这是告诉Mybatis区哪找持久化类的映射文件,对于在src下的文件直接写文件名,
            如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml-->
        <mapper resource="User.xml"></mapper>
    </mappers>
</configuration>
  • 读取配置文件,配置mybatis工具类
public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    //初始即加载
    static {
        try {
            String resource = "mybatis-config.xml";
            //加载配置文件,得到配置文件的流
            InputStream ras = Resources.getResourceAsStream(resource);
            //加载流 获取工厂类
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(ras);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //有了sqlSessionFactory,顾名思义我们就可以获得sqlSession的实例
    //SqlSession完全包含了面向数据库执行sql所需的所有方法
    public static SqlSession getSqlSession(){
        //工厂类生产对象
      return sqlSessionFactory.openSession();
    }
    
}

2.3、编写代码

  • 实体类

    package com.lxf.pojo;
    
    /**
     * @program: java_mybatis
     * @description: 顾客实体类
     * @author: 李向飞
     * @create: 2020-10-14 11:39
     **/
    public class Customer {
        private int id;
        private String name;
        private String sex;
        private String address;
    
        public Customer(int id, String name, String sex, String address) {
            this.id = id;
            this.name = name;
            this.sex = sex;
            this.address = address;
        }
    
        public Customer() {
    
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "Customer{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", sex='" + sex + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
    
  • Dao接口

    package com.lxf.dao;
    
    import com.lxf.pojo.Customer;
    
    import java.util.List;
    
    /**
     * @program: java_mybatis
     * @description: 顾客对象接口
     * @author: 李向飞
     * @create: 2020-10-14 11:41
     **/
    public interface CustomerDao {
        List<Customer> getCustomerList();
    }
    
    
  • 接口实现类

    由原来的实现类变为mapper.xml配置文件

    <?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <!--namespace 为对应的dao层接口 -->
    <mapper namespace="com.lxf.dao.CustomerDao">
    <!--查询语句 -->
      <!--id 为对应的dao层接口的实现方法  resultType返回值类型为对应的实体类型-->
       <select id="getCustomerList" resultType="com.lxf.pojo.Customer">
           select * from Customer
       </select>
    </mapper>
    

    最后在mybatis的总配置文件中注册mapper

    <!--添加mapper映射:每一个mapper.xml都需要在mybatis核心配置文件中注册-->
        <mappers>
            <!--这是告诉Mybatis去找持久化类的映射文件,对于在src下的文件直接写文件名,
                如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml-->
            <mapper resource="com/lxf/dao/CustomerMapper.xml"></mapper>
        </mappers>
    

2.4、测试

​ 注意点:

此类报错是因为java目录下的配置文件 无法通过maven 编译到jar包中需要更改maven配置

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>

            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>

    </build>

测试代码

package com.lxf.dao;

import com.lxf.pojo.Customer;
import com.lxf.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

/**
 * @program: java_mybatis
 * @description:
 * @author: 李向飞
 * @create: 2020-10-14 14:23
 **/
public class CustomerDaoTest {
    @Test
    public void test(){
        //获得sqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //方式一:执行sql
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
        List<Customer> customerList = mapper.getCustomerList();
        for (Customer customer : customerList) {
            System.out.println(customer.toString());
        }
        //关闭连接
        sqlSession.close();
    }

}

3、CRUD(day01)

3.1、查询

3.1、全量查询

首先在dao层接口添加普通查询方法

    //全量查询搜索
    List<Customer> getCustomerList();

在dao层的实现类(mapper文件)书写sql

  <select id="getCustomerList" resultType="com.lxf.pojo.Customer">
       select * from Customer
   </select>

测试:

  @Test
    public void test(){
        //获得sqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //方式一:执行sql
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
        List<Customer> customerList = mapper.getCustomerList();
        for (Customer customer : customerList) {
            System.out.println(customer.toString());
        }
        //关闭连接
        sqlSession.close();
    }

3.2条件查询

首先在dao层接口添加条件查询方法

 //根据ID查寻用户
    Customer getCustomerById(int id);

在dao层的实现类(mapper文件)书写sql

 <select id="getCustomerById" parameterType="int" resultType="com.lxf.pojo.Customer">
       select * from Customer where id = #{id}
   </select>

测试:

 @Test
    public void test1(){
    //根据工具类获得对象
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtils.getSqlSession();
            //执行sql
            CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
            Customer customer = null;
            try {
                customer = mapper.getCustomerById(1);
                System.out.printf(customer.toString());
            } catch (NullPointerException e) {
                System.out.println("此id用户不存在");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭
            if (sqlSession != null){
                sqlSession.close();
            }
        }
    }

3.2、增加

首先在dao层接口添加增加方法

//增加
    void insertCustomer(Customer customer);

在dao层的实现类(mapper文件)书写sql

  <insert id="insertCustomer" parameterType="com.lxf.pojo.Customer" >
        insert into Customer values (#{id}, #{name},#{age}, #{sex}, #{address})
    </insert>

测试:

@Test
    public void test3(){

        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
//
        mapper.insertCustomer(new Customer("皮皮",17,"男","河南许昌"));
        //提交事务
        sqlSession.commit();
        sqlSession.close();
    }

3.3、修改

首先在dao层接口添加修改方法

 //修改
    void updateCustomer(Customer customer);

在dao层的实现类(mapper文件)书写sql

  <update id="updateCustomer" parameterType="com.lxf.pojo.Customer" >
        update Customer  set id = #{id}, name=#{name}, age = #{age}, sex = #{sex}, address = #{address} where id = #{id}
    </update>

测试:

    @Test
    public void test4(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
        mapper.updateCustomer(new Customer(5,"李程",20,"男","河南省禹州市"));
        sqlSession.commit();
        sqlSession.close();
    }

3.4、删除

首先在dao层接口添加删除方法

//删除
    void deleteCustomer(int id);

在dao层的实现类(mapper文件)书写sql

 <delete id="deleteCustomer" parameterType="int">
        delete  from Customer where id=#{id}
    </delete>

测试:

    @Test
    public void test5(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
        mapper.deleteCustomer(6);
        sqlSession.commit();
        sqlSession.close();
    }

3.5、MAP

假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应该去考虑Map

Map传递参数,直接在sql中取出key即可![paramenterType=“map”]

对象传递参数,直接在sql中取对象属性即可![paramenterType=“Object”]

只有一个基本类型参数的情况下,可以直接在sql中取到!

多个参数用Map,或者注解

首先在dao层接口添加方法

 //万能Map
    void insert(Map<String, Object> map);

在dao层的实现类(mapper文件)书写sql

<!--    万能map-->
    <insert id="insert" parameterType="map">
        insert into Customer values (#{id},#{customerName},#{customerAge}, #{customerSex}, #{customerAddress})
    </insert>

测试:

    public void test6(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("customerName","犀利");
        map.put("customerAge",88);
        map.put("customerSex","男");
        map.put("customerAddress", "1211123");
        mapper.insert(map);
        sqlSession.commit();
        sqlSession.close();
    }

3.6、模糊查询

1、java代码执行的时候,传递通配符%%

select * from Customer where name like "%"#{value}"%"

2、在sql拼接时使用通配符

  @Test
    public void test7(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        CustomerDao mapper = sqlSession.getMapper(CustomerDao.class);
        List<Customer> customerList = mapper.getCustomerLike("%小%");
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
        sqlSession.close();
    }

4、配置解析(day02)

4.1、核心配置文件

  • mybatis-config.xml

  • mybatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息

    configuration(配置)
        properties(属性)
        settings(设置)
        typeAliases(类型别名)
        typeHandlers(类型处理器)
        objectFactory(对象工厂)
        plugins(插件)
        environments(环境配置)
        environment(环境变量)
        transactionManager(事务管理器)
        dataSource(数据源)
        databaseIdProvider(数据库厂商标识)
        mappers(映射器)
    

4.2、环境配置(environments)

MyBatis可以配置成适应多种环境

注意:尽管可以配置多套环境但每一个sqlsession实例只能选择一种环境

学会使用配置多套运行环境

MyBatis默认的事物管理器就是JDBC,连接池:POOLED

4.3、属性(properties)

可以通过properties属性来实现引用配置文件

这些属性都是可外部配置且可东台替换的,即可以在典型的java属性文件中配置,亦可通过properties元素的子元素来传递

步骤

1.创建db.properties文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test?useSSL=true&amp;useUnicode=true&amp;CharacterEncoding=UTF-8
username=root 
password=123456

2.核心配置文件映入

<?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配置文件-->
    <properties resource="db.properties"/>


    <!--环境配置,连接的数据库,这里使用的是MySQL-->
    <environments default="mysql">
<!--        环境1-->
        <environment id="mysql">
            <!--指定事务管理的类型,这里简单使用Java的JDBC的提交和回滚设置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 指连接源配置,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
<!--        环境2-->
        <environment id="test">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
    </environments>
    <!--添加mapper映射:每一个mapper.xml都需要在mybatis核心配置文件中注册-->
    <mappers>
        <mapper resource="com/lxf/dao/UserMapper.xml"></mapper>
    </mappers>
</configuration>

  • 可以直接引入外部文件
  • 可以在其中增加一些属性配置
  • 如果两个文件有同一个字段,优先使用外部配置文件的

4.4、类型别名

类型别名是为java类型设置一个短的名字,他只和XML有关,存在的意义仅在于用来减少类完全限定类冗余

    <typeAliases>
        <typeAlias type="com.lxf.pojo.User" alias="user"/>
    </typeAliases>
    <typeAliases>
        <package type="com.lxf.pojo" />
    </typeAliases>

  • 在实体类比较少的时候,使用第一种
  • 如果实体类特别多,建议使用第二种
  • 第一种可以DIY别名,第二种不行
  • 第二种如果非要可以在实体类上加注解@Alias(“xxx”)

4.5、设置(settings)

4.6、其他配置

4.7、映射器(Mapper)

MapperRegistry:注册绑定Mapper文件

方式一:

<mappers>
        <mapper resource="com/lxf/dao/UserMapper.xml"></mapper>
 </mappers>

方式二:

<mappers>
        <mapper url="com/lxf/dao"></mapper>
</mappers>

4.8、作用域与生命周期

不同作用域和生命周期类别是至关重要的,错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

  • 一旦创建了SqlSessionFactoryBuilder,就不再需要他了
  • 局部变量
SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

  • 类似于数据库连接池
  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由去丢弃他,或重新创建另外一个实例
  • 最简单的就是使用单例模式或者静态单例模式
SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

  • 连接到连接池的一个请求
  • 用完即关闭,否则资源被占用

5、解决属性名和字段名不一致的问题(day03)

结果集映射

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lxf.dao.ShopDao">
    <resultMap id="shopMap" type="shop">
        <result column="id" property="id"/>
        <result column="shopname" property="shopName"/>
        <result column="shopnumber" property="shopNumber"/>
        <result column="shoptype" property="shopType"/>
        <result column="shopaddress" property="shopAddress"/>
    </resultMap>
    <select id="getAll" resultMap="shopMap">
        select * from SHOP
    </select>
</mapper>

6、日志(day03)

6.1、日志工厂

Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging

在MyBatis中核心文件中配置

    <settings>
<!--       添加日志设置-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

6.2、LOG4J

Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就 是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

1、导包

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
 </dependency>

2.配置配置文件

#将登记为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/project.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-mm-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

简单使用

  1. 要在使用Log4j的类中,导入包 import org.apache.log4j.Logger;

  2. 日志对象,参数为当前类的class

       static Logger logger = Logger.getLogger(ShopTest.class);
       
       @Test
        public void testLog4j(){
            logger.info("info");
            logger.debug("debug");
            logger.error("error");
        }
    

7、分页(day04)

7.1、limit分页

select * from user limit startIndex,pageSize
select * from tablename limit 3; [0,n]

使用mybatis

  1. 接口

    List<Shop> getUserByLimit(Map<String, Integer> map);
    
  2. Mapper.xml

    <!--    分页查询-->
        <select id="getUserByLimit" parameterType="map" resultMap="shopMap">
            select * from SHOP limit #{startIndex},#{pageSize}
        </select>
    
  3. 测试

        @Test
        public void test2(){
            SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory();
            ShopDao mapper = sqlSession.getMapper(ShopDao.class);
            HashMap<String, Integer> map = new HashMap<String, Integer>();
            map.put("startIndex",1);
            map.put("pageSize",2);
            List<Shop> userByLimit = mapper.getUserByLimit(map);
            for (Shop shop : userByLimit) {
                System.out.println(shop);
            }
            sqlSession.close();
        }
    

7.2、RowBounds分页

不再使用Sql实现分页

使用java代码 查询出特定个数,进行分页

  1. 接口

        //分页2
        List<Shop> getUserByRowBounds();
    
  2. mapper.xml

        <select id="getUserByRowBounds"  resultMap="shopMap">
            select * from SHOP
        </select>
    
  3. 测试

        @Test
        public void test4() {
            //RowBounds分页
            RowBounds rowBounds = new RowBounds(1, 2);
    
            SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory();
            List<Shop> shopList = sqlSession.selectList("com.lxf.dao.ShopDao.getUserByRowBounds", null, rowBounds);
    
            for (Shop shop : shopList) {
                System.out.println(shop);
            }
            sqlSession.close();
        }
    

    7.3、分页插件

PageHelper:https://pagehelper.github.io/

8、使用注解开发(day04)

8.1、面向接口编程

什么叫面向接口编程

在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。

根本原因:解耦合 可拓展 提高复用,分层开发,上层不用管具体的实现,大家遵守共同的标准,使得开发变得容易,规范性更好

1.关于接口的理解。

接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。

接口的本身反映了系统设计人员对系统的抽象理解。

接口应有两类:第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);

第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);

一个体有可能有多个抽象面。

抽象体与抽象面是有区别的。

2.设计接口的另一个不可忽视的因素是接口所处的环境(context,environment),系统论的观点:环境是系统要素所处的空间与外部影响因素的总和。任何接口都是在一定的环境中产生的。因此环境的定义及环境的变化对接口的影响是不容忽视的,脱离原先的环境,所有的接口将失去原有的意义。

3.三个面向

面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法

面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现

接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题

8.2、使用注解开发

1、注解在接口上实现


public interface OrderMapper {
    @Select("select * from order_list")
    List<Order> getAll();

}

2、需要在核心配置文件中绑定接口

<!--    绑定接口-->
    <mappers>
        <mapper class="com.lxf.dao.OrderMapper"/>
    </mappers>

3、测试

   @Test
    public void test1(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        List<Order> all = mapper.getAll();
        for (Order order : all) {
            System.out.println(order);
        }
        sqlSession.close();
    }

本质:反射机制实现

底层:动态代理

8.3、CRUD

1、我们可以在工具类创建的时候自动提交事务

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }

2、接口添加映射关系

 @Results(id = "OrderMap", value = {
            @Result(column = "serial_num", property = "serialNum"),
            @Result(column = "order_id", property = "orderId"),
            @Result(column = "date", property = "date"),
            @Result(column = "prod_id", property = "prodId"),
            @Result(column = "prodname", property = "prodName"),
            @Result(column = "cust_id", property = "custId"),
            @Result(column = "cust_name", property = "custName"),
            @Result(column = "quantity", property = "quantity"),
    })

3、查找

  • 接口

    @ResultMap("OrderMap") 
    @Select("select * from order_list")
    List<Order> getAll();
    
    //方法存在多个参数,所有的参数前面必须加上@Param
    @ResultMap("OrderMap")
    @Select("select * from order_list where serial_num = #{id}")
    Order getOrderById(@Param("id") int id);
    
  • 测试

    public void test1(){	
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            List<Order> all = mapper.getAll();
            for (Order order : all) {
                System.out.println(order);
            }
            Order order = mapper.getOrderById(00000004);
            System.out.println(order);
    			sqlSession.close();
    }
    

4、增加

  • 接口

    //增加
        @ResultMap("OrderMap")
        @Insert("insert into order_list values (#{serialNum},#{orderId},#{date},#{prodId},#{prodName},#{custId},#{custName},#{quantity})")
        void addOne(Order order);
    
  • 测试

    public void test1(){	
    				SqlSession sqlSession = MyBatisUtils.getSqlSession();
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
            Order order = new Order("00000002", "20190410001", "2019-04-10", "20007", "趣多多", "C00100110", "李一", "4");
            System.out.println(order);
            mapper.addOne(order);
    			sqlSession.close();
    }
    
5、修改
  • 接口

    //修改
        @ResultMap("OrderMap")
        @Update("update order_list  set order_id=#{order.orderId}, date = #{order.date}, prod_id = #{order.prodId}, prodname = #{order.prodName},cust_id = #{order.custId},cust_name = #{order.custName},quantity = #{order.quantity} where serial_num = #{id} ")
        void update(@Param("id") String id,@Param("order") Order order);
    
    
  • 测试

    public void test1(){	
    				SqlSession sqlSession = MyBatisUtils.getSqlSession();
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
      			Order order = new Order("00000002", "20190410001", "2019-04-10", "20007", "趣多多", "C00100110", "李一", "4");
             mapper.update("00000002",order);
    			sqlSession.close();
    }
    

6、删除

  • 接口

     //删除
        @ResultMap("OrderMap")
        @Delete("delete from  order_list where  serial_num = #{id}")
        void delete(@Param("id") String id);
    
  • 测试

    public void test1(){	
    				SqlSession sqlSession = MyBatisUtils.getSqlSession();
            OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
      			mapper.delete("00000029");
            mapper.addOne(order);
    			 sqlSession.close();
    }
    

6、注意事项

测试类:

我们必须将接口注册绑定到我们的核心配置文件中

关于@param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型的话,可以忽略,但是建议加上
  • 在Sql中引用的就是我们这里@param()中设定的属性名

#{} ${}区别:

${}无法防止sql注入

#{}能够很大部分防止sql注入

9、Lombok(day04)

Lombok项目是一个Java库,它会自动插入您的编辑器和构建工具中,从而使您的Java更加生动有趣。
永远不要再写另一个getter或equals方法,带有一个注释的您的类有一个功能全面的生成器,自动执行记录变量等。

1)引入相应的maven包

​ org.projectlombok

​ lombok

​ 1.16.18

​ provided

Lombok的scope=provided,说明它只在编译阶段生效,不需要打入包中。事实正是如此,Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件。

2)添加IDE工具对Lombok的支持

IDEA中引入Lombok支持如下:

点击File-- Settings设置界面,安装Lombok插件

点击File-- Settings设置界面,开启 AnnocationProcessors

开启该项是为了让Lombok注解在编译阶段起到作用。

Eclipse的Lombok插件安装可以自行百度,也比较简单,值得一提的是,由于Eclipse内置的编译器不是Oracle javac,而是eclipse自己实现的Eclipse Compiler for Java (ECJ).要让ECJ支持Lombok,需要在eclipse.ini配置文件中添加如下两项内容:

-Xbootclasspath/a:[lombok.jar所在路径

3)Lombok实现原理

自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。

Lombok就是一个实现了"JSR 269 API"的程序。在使用javac的过程中,它产生作用的具体流程如下:


\1. javac对源代码进行分析,生成一棵抽象语法树(AST)

\2. javac编译过程中调用实现了JSR 269的Lombok程序

\3. 此时Lombok就对第一步骤得到的AST进行处理,找到Lombok注解所在类对应的语法树 (AST),然后修改该语法树(AST),增加Lombok注解定义的相应树节点

\4. javac使用修改后的抽象语法树(AST)生成字节码文件


4) Lombok注解的使用

POJO类常用注解:

@Getter/@Setter: 作用类上,生成所有成员变量的getter/setter方法;作用于成员变量上,生成该成员变量的getter/setter方法。可以设定访问权限及是否懒加载等。

package com.kaplan.pojo;

import lombok.*;

import lombok.extern.log4j.Log4j;

@Getter

@Setter

public class TestDemo {

private String name;

​ private int age ; private String email;

private String address; private String password;

​ @Getter @Setter private boolean funny;

}

@ToString:作用于类,覆盖默认的toString()方法,可以通过of属性限定显示某些字段,通过exclude属性排除某些字段。

**
@EqualsAndHashCode:作用于类,覆盖默认的equals和hashCode**

@NonNull:主要作用于成员变量和参数中,标识不能为空,否则抛出空指针异常。

@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor:作用于类上,用于生成构造函数。有staticName、access等属性。

staticName属性一旦设定,将采用静态方法的方式生成实例,access属性可以限定访问权限。

@NoArgsConstructor:生成无参构造器;

@RequiredArgsConstructor:生成包含final和@NonNull注解的成员变量的构造器;

@AllArgsConstructor:生成全参构造器

img

**@Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
**

@Builder:作用于类上,将类转变为建造者模式

@Log:作用于类上,生成日志变量。针对不同的日志实现产品,有不同的注解:

其他重要注解:

@Cleanup:自动关闭资源,针对实现了java.io.Closeable接口的对象有效,如:典型的IO流对象

@SneakyThrows:可以对受检异常进行捕捉并抛出,可以改写上述的main方法如下:

@Synchronized:作用于方法级别,可以替换synchronize关键字或lock锁,用处不大

10、多对一(day05)

数据库准备:

create table teacher( 
id int(10) not null, 
name varchar(30) default null, 
primary key(id) 
)ENGINE=INNODB DEFAULT CHARSET=utf8;

insert into teacher values('1','李老师');

create table student( 
id int(10) not null, 
name varchar(30) default null, 
tid int(10) default null, 
primary key(id),
KEY fktid (tid),
CONSTRAINT fktid FOREIGN KEY (tid) REFERENCES teacher (id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;

insert into student values('1','小明','1');
insert into student values('2','小红','1');
insert into student values('3','小蓝','1');
insert into student values('4','小黑','1');
insert into student values('5','小绿','1');
insert into student values('6','小紫','1');

10.1、按照查询嵌套处理

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lxf.dao.StudentMapper">
    <resultMap id="StudentTeacher" type="student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--
            对象:association
            集合:collection
        -->
        <result property="tid" column="tid"/>
        <association property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
    </resultMap>
<!--    1.查询所有学生的信息,
        2、根据学生的tid寻找对应的老师(子查询)
        -->
    <select id="getAllStudent" resultMap="StudentTeacher">
        select * from student
    </select>
<!--    查询寻老师-->
    <select id="getTeacher" resultType="teacher">
        select * from teacher where id = #{id}
    </select>
    
    
</mapper>

10.2、按照结果嵌套处理

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lxf.dao.StudentMapper">

    
    
<!-- =======================================================-->
<!--按照查询结果嵌套处理-->
    <resultMap id="StudentTeacher_2" type="student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
        <association property="teacher"  javaType="teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    <select id="getAllStudent2" resultMap="StudentTeacher_2">
        select
        s.id sid,
        s.name sname,
        s.tid tid,
        t.name tname
        from
        student s,teacher t
        where s.tid = t.id
    </select>
</mapper>

10.3、回顾

  • 子查询
  • 连表查询

11、一对多(day06)

比如:一个老师拥有多个学生!

对于老师而言就一对多

11.1、按照子查询

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lxf.dao.TeacherMapper">
<!--    根据子查询-->
    <resultMap id="TeacherStudent_1" type="teacher">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="students" javaType="ArrayList" ofType="studnet" select="getStudent" column="id"/>
    </resultMap>

    <select id="getTeacher1" parameterType="_int" resultMap="TeacherStudent_1">
        select * from teacher where id = #{tid};
    </select>
    <select id="getStudent" resultType="student">
        select * from student where tid = ${id}
    </select>
</mapper>

11.2、按结果嵌套查询

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.lxf.dao.TeacherMapper">


<!--根据嵌套查询-->
    <resultMap id="TeacherStudent" type="teacher">
        <result property="id" column="tid" />
        <result property="name" column="tname" />
<!--
javaType="" 指定属性的类型
ofType = "" 指定泛型集合
 -->
        <collection property="students" javaType="ArrayList" ofType="student">
                <result property="id" column="sid"/>
                <result property="name" column="sname"/>
                <result property="tid" column="tid"/>
        </collection>
    </resultMap>

    <select id="getTeacher" parameterType="_int" resultMap="TeacherStudent">
        select
        t.id tid,
        t.name tname,
        s.id sid,
        s.name sname
        from
        student s,teacher t
        where
        t.id = s.tid
        and t.id = #{tid}
    </select>


</mapper>

11.3、总结

子查询相当于 子查询到对象之后进行赋值

嵌套查询当于查询出所有结果之后进行赋值

javaType & ofType

javaType:用来指定实体类类型(指定属性的类型)

ofType:泛型中的约束类型(指定泛型集合)

association&collection

association: 多对一(对象)

collection: 一对多(集合)

注意点:

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一中,属性名和字段的问题
  • 如果问题不好排查错误,可以使用日志,建议使用Log4j

慢SQL问题

12、动态SQL(day07)

什么是动态sql:就是根据不同的条件生成不同的sql语句

JSTL标签

  • if
  • choose(when, otherwise)
  • trim(where ,set)
  • foreach

12.1、搭建环境

create table blog(
	id varchar(50) not null comment '博客id',
  title varchar(100) not null comment '博客标题',
  author varchar(30) not null comment '博客作者',
  create_time datetime not null comment '创建时间',
  views int(30) not null comment '浏览量'
)ENGINE=InnoDB DEFAULT CHARSET=utf8

12.2、创建工程

  1. 导包

  2. 编写配置文件

    public class MyBatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                InputStream ras = Resources.getResourceAsStream("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(ras);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession(true);
        }
    
    }
    
  3. 编写实体类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Blog {
        private String id;
        private String tile;
        private String author;
        private Date createTime;
        private int views;
    }
    
  4. 编写实体类对应的Mpaaer接口与xml文件

12.3、动态sql添加

1、if

Dao:

    //查询博客
    List<Blog> queryBlogIF(Map map);

Mapper.xml

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from blog where 1 = 1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>

2、choose(when, otherwise)

有时候我们不行应用到所有的条件语句,而是只想选择其中的一项。针对这种情况,MyBatis提供了Choose语句,类似于java中的switch case语句

Dao接口

 //查询博客
    List<Blog> queryBlogChoose(Map map);

xml文件

   <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from blog where 1 = 1
        <choose>
            <when test="title != null">
                and title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                
            </otherwise>
        </choose>
    </select>

3、trim(where ,set)

<select id="queryBlogTrim" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <if test="title != null">title = #{title}</if>
            <if test="author != null">AND author = #{author}</if>
        </where>
    </select>
<!-- where 标签会在套在标签中的语句自动拼接 where 如果有and/or开头的语句,且作为拼接的第一句 会强行替换为where-->

<!-- where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。-->


<!--如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:-->
    <select id="queryBlogTrim" parameterType="map" resultType="blog">
        select * from blog
        <trim prefix="WHERE" prefixOverrides="AND|OR">
            <if test="title != null">title = #{title}</if>
            <if test="author != null">AND author = #{author}</if>
        </trim>
    </select>

<!-- 用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列-->
    <update id="updateBlogSet" parameterType="map">
        update Blog
        <set>
            <if test="title">title = #{title},</if>
            <if test="author"> author = #{author},</if>
            <if test="createTime">create_time = #{createTime},</if>
            <if test="views">views = #{views},</if>
        </set>
        where id = #{id}
    </update>


3、foreach

注:

item:循环元素(如果传来的是map 则为value)

index:循环下标(如果传来的是map 则为key)

open: 循环开始以open后的元素开头

separator:以separator后的元素添加到循环元素末尾

close:循环结束以close后的元素结尾

collection:

当传来的是一个数组类型时:array

当传来的是一个列表类型时:list

当传来的是复杂map嵌套类型时:应该与map的key保持一

<!--  动态 SQL 的另一个常见使用场景是对集合进行遍历  -->
    <select id="queryBlogForEach" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <if test="title != null">
                title in
                <foreach item="item" index="index" open="(" separator="," close=")" collection="title" >
                    #{item}
                </foreach>
            </if>
        </where>

    </select>
@Test
    public void test1(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        ArrayList<String> list = new ArrayList<String>();
        list.add("MyBatis如此简单");
        list.add("java如此简单");
        map.put("title", list);
        List<Blog> blogs = mapper.queryBlogForEach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

13、缓存

13.1、简介

查询:连接数据库,消耗资源
一次查询的结束,给它暂存在一个可以直接渠道的地方!---->内存:缓存

1.什么是缓存?

  • 存在内存中的临时数据
  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据文件)查询,从而提高查询效率,解决高并发系统的性能问题

2.为什么使用缓存?

  • 减少喝数据库的交互次数,减少系统开销,提高工作效率

3.什么样的数据能够使用缓存?

  • 经常查询且不经常改变的数据

13.2、MyBatis缓存

  • MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存,缓存可以极大的提升查询效果
  • MyBatis系统中默认定义了二级缓存:一级缓存喝二级缓存
    • 默认情况下,只有以及缓存开启。(sqlSession级别的缓存,也成本地缓存)
    • 二级缓存需要手动开启喝配置,它是基于namespace级别的缓存、
    • 为了提高扩展性,Mybatis定义了缓存接口Cache,我们可以通过实现Cache接口来定义二级缓存

13.3、一级缓存(会话缓存)

  • 一级缓存也叫本地缓存:sqlsession
    • 与数据库同一次回话期间查询到的数据会放在本地缓存中。
    • 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。

测试步骤:

1、开启日志工厂

2、测试在一个session查询两次记录

3、查看日志输出

13.4、二级缓存(全局缓存)

  • 二级缓存也叫全局缓存,以及缓存作用域太低了。所以诞生了二级缓存
  • 基于namespace级别的缓存,一个名称空间对应一个二级缓存
  • 工作机制
    • 一个会话查询到一条数据,这个数据就会被放在当前会话的一级缓存中
      • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存的数据会被保存到二级缓存中。
      • 新的会话查询信息,就可以从二级缓存中获取内容
      • 不动的mapper查出的数据会放在自己对应的缓存(map)中

添加二级缓存:

1、接口对应的mapper.xml文件中添加:

<!--    开启二级缓存-->
    <cache/>

2、显示开启二级缓存:在全局配置文件的settings标签中添加

<!--       显示的开启全局缓存-->
        <setting name="cacheEnabled" value="true"/>

小结:

  • 只有开启了二级缓存,在同一个Mapper下就有效果
  • 所有的数据都会先放在一级缓存中
  • 只有当会话提交,或者关闭的时候,才会提交到二级缓存中

13.5、缓存原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qiQHMH5E-1603105210174)(/Users/mac/Library/Application Support/typora-user-images/image-20201019183921414.png)]

用户查询开始时:二级缓存---->一级缓存----->数据库

13.6、自定义缓存-ehcache

https://www.jianshu.com/p/154c82073b07

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。

1、导包

  <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>1.1.0</version>
        </dependency>

2、创建配置文件ehcache.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">
    <!--
       diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     -->
    <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
    <!--
       defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
     -->
    <!--
      name:缓存名称。
      maxElementsInMemory:缓存最大数目
      maxElementsOnDisk:硬盘最大缓存个数。
      eternal:对象是否永久有效,一但设置了,timeout将不起作用。
      overflowToDisk:是否保存到磁盘,当系统当机时
      timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
      timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
      diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
      memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
      clearOnFlush:内存数量最大时是否清除。
      memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>

</ehcache>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值