SSM持久层框架MyBatis,看这一篇就够了

前言
此篇仅为个人初期学习笔记,如有错误,请xd们指正 你这么好看,还。。。。

MyBatis


前言

后续会更新spring、springmvc、springboot、分布式微服务等 关注我,一起学习,一起进步吧

来源
尚硅谷视频教程

一、MyBatis简介

  • 是一个基于Java的半自动的ORM(Object Relation Mapping)持久层框架
  • iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO
  • 支持存储过程以及高级映射
  • 不需要手动写jdbc代码、不需要手动设置参数和获取结果集
  • 使用简单的XML或注解用于配置和原始映射
  • SQL 和 Java 编码分开,SQL语句专注于数据,java代码专注于业务逻辑
  • 封装了jdbc,简化操作

二、搭建MyBatis项目

1. 开发环境

  • ide
  • maven
  • MySQL
  • MyBatis

2. 创建maven工程

  1. 设置打包方式:jar
<packaging>war</packaging>
  1. 引入依赖—在pom.xml文件
<dependencies>

   <!-- Mybatis核心 -->

   <dependency>

   <groupId>org.mybatis</groupId>

   <artifactId>mybatis</artifactId>

   <version>3.5.7</version>

   </dependency>

   <!-- junit测试 -->

   <dependency>

   <groupId>junit</groupId>

   <artifactId>junit</artifactId>

   <version>4.12</version>

   <scope>test</scope>

   </dependency>

   <!-- MySQL驱动 -->

   <dependency>

   <groupId>mysql</groupId>

   <artifactId>mysql-connector-java</artifactId>

   <version>5.1.3</version>

   </dependency>

   </dependencies>

3. 创建MyBatis核心配置文件

  • 习惯命名:mybatis-config.xml

  • ssm整合之后可以省略不写

  • 作用:配置连接数据库的环境以及MyBatis的全局配置信息

 <?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>

  <!--设置连接数据库的环境-->

  <environments default="development">

  <environment id="development">

  <transactionManager type="JDBC"/>

  <dataSource type="POOLED">

  <property name="driver" value="com.mysql.jdbc.Driver"/>

  <property name="url"

  value="jdbc:mysql://localhost:3306/MyBatis"/>

  <property name="username" value="root"/>

  <property name="password" value="123456"/>

  </dataSource>

  </environment>

  </environments>

  <!--引入映射文件-->

  <mappers>

  <mapper resource="mappers/UserMapper.xml"/>

  </mappers>

  </configuration>

4. 创建Mapper接口

  1. mapper接口相当于以前的DAO,用来操作数据库,
    MyBatis是面向接口编程的,所以不需要提供实现类
  2. 位置:main----com.nuesoft.mybatis.mapper

5. 创建MyBatis映射文件

相关概念:
ORMObject Relationship Mapping)对象关系映射。

  • O:Object,java中的实体对象
  • R:Relationship,关系型数据库
  • M:Mapping,俩者之间的映射关系
  1. 映射关系

    • Java 数据库概念
    • 类 表
    • 对象 行
    • 属性 字段
  2. 注意事项

    • 映射文件的命名规则:

      表所对应的实体类的类名+Mapper.xml

    • 一个映射文件对应一个实体类,对应一张表的操作

    • MyBatis映射文件用于编写SQL,访问以及操作表中的数据

    • MyBatis中想要面向接口操作数据,要保证两个一致:

      • mapper接口的全类名和映射文件的命名空间(namespace)保持一致
      • mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致

6. 通过junit(测试单元)测试代码

//读取MyBatis的核心配置文件

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

//创建SqlSessionFactoryBuilder对象

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new

SqlSessionFactoryBuilder();

//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象

SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);

//创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务

//SqlSession sqlSession = sqlSessionFactory.openSession();

//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交

SqlSession sqlSession = sqlSessionFactory.openSession(true);

//通过**代理模式**创建UserMapper接口的代理实现类对象

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配

映射文件中的SQL标签,并执行标签中的SQL语句

int result = userMapper.insertUser();

//sqlSession.commit();'

7. 配置log4j日志功能

a>引入依赖(pom.xml文件中)

<!-- log4j日志 -->

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

</dependency>

### b>加入配置文件

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">


<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">

<param name="Encoding" value="UTF-8" />

<layout class="org.apache.log4j.PatternLayout">

<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}

%m (%F:%L) \n" />

</layout>

</appender>

<logger name="java.sql">

<level value="debug" />

</logger>

<logger name="org.apache.ibatis">

<level value="info" />

</logger>

<root>

<level value="debug" />

<appender-ref ref="STDOUT" />

</root>

</log4j:configuration>

c>日志级别

  • FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试)

  • 从左到右打印的内容越来越详细

三、MyBatis核心配置文件

1. 标签顺序

properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,
objectWrapperFactory?,reflectorFactory?,plugins?,environments?,
databaseIdProvider?,mappers?

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="jdbc.properties"/>

<!--全局变量-->

<settings>

<!--将表中字段的下划线自动转换为驼峰-->

<setting name="mapUnderscoreToCamelCase" value="true"/>

<!--开启延迟加载-->

<setting name="lazyLoadingEnabled" value="true"/>

</settings>

<typeAliases>



<!-- typeAlias:设置某个具体的类型的别名

属性:

type:需要设置别名的类型的全类名

alias:设置此类型的别名,若不设置此属性,该类型拥有默认的别名,即类名且不区分大小

写

若设置此属性,此时该类型的别名只能使用alias所设置的值

-->

<!--<typeAlias type="com.atguigu.mybatis.bean.User"></typeAlias>-->

<!--<typeAlias type="com.atguigu.mybatis.bean.User" alias="abc">

</typeAlias>-->

<!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写-->

<package name="com.atguigu.mybatis.bean"/>

</typeAliases>

<!--

environments:设置多个连接数据库的环境

属性:

default:设置默认使用的环境的id

-->

<environments default="mysql_test">

<!--

environment:设置具体的连接数据库的环境信息

属性:

id:设置环境的唯一标识,可通过environments标签中的default设置某一个环境的id,

表示默认使用的环境

-->

<environment id="mysql_test">

<!--

transactionManager:设置事务管理方式

属性:type:设置事务管理方式,type="JDBC|MANAGED"

type="JDBC":设置当前环境的事务管理都必须手动处理

type="MANAGED":设置事务被管理,例如spring中的AOP

-->

<transactionManager type="JDBC"/>

<!--

dataSource:设置数据源

属性:

type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI"

type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从

缓存中直接获取,不需要重新创建

type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建

type="JNDI":调用上下文中的数据源

-->

<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>

<mapper resource="UserMapper.xml"/>

<!--

以包为单位,将包下所有的映射文件引入核心配置文件

注意:此方式必须保证mapper接口和mapper映射文件必须在相同的包下

-->

<package name="com.atguigu.mybatis.mapper"/>

</mappers>

</configuration>

四、MyBatis增删改查

1.添加

<insert> 

​	insert into t_user values(null,'admin','123456',23,'男')

<insert/>

2.删除

<delete>delete from t_user where id = 7 </delete>

3.修改

<update>

​		update t_user set username='ybc',password='123' where id = 6

</update>

4.查询一条数据

返回单个对象

<select resultType = "com.nuesoft.mybatis.User">
    SELECT * FROM EMP WHERE id = #{id}
</select>


5.查询多条数据

返回集合

<select>
	select * from emp;
</select>

6.注意

a>
  • 查询的标签select必须设置属性resultTyperesultMap,用于设置实体类数据库表映射关系

  • resultType:

    自动映射,用于属性名和表中字段名一致的情况

  • resultMap:

​ 自定义映射,用于一对多多对一字段名和属性名不一致的情况

b>
  • 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常 TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值

五、MyBatis获取参数的俩种方式

1.#{}和${}

  • ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引 号;
  • 但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

2.单个字面量类型参数

  • 若mapper接口中的方法参数为单个的字面量类型
  • 此时可以使用KaTeX parse error: Expected 'EOF', got '#' at position 4: {}或#̲{}以任意的名称获取参数的值,…{}需要手动加单引号

3.多个字面量类型参数

  • 若mapper接口中的方法参数为多个
  • 此时MyBatis会自动将这些参数放在一个map集合中,以arg0,arg1…为键,以参数为值; 以 param1,param2…为键,以参数为值;
  • 因此只需要通过KaTeX parse error: Expected 'EOF', got '#' at position 4: {}和#̲{}访问map集合的键就可以获…{}需要手动加单引号

4.map集合类型参数

  • 若mapper接口中的方法需要的参数为多个时

  • 此时可以手动创建map集合,将这些数据放在map中

  • 只需要通过KaTeX parse error: Expected 'EOF', got '#' at position 4: {}和#̲{}访问map集合的键就可以获…{}需要手动加单引号

5.实体类类型参数

  • 若mapper接口中的方法参数为实体类对象时
  • 此时可以使用KaTeX parse error: Expected 'EOF', got '#' at position 4: {}和#̲{},通过访问实体类对象中的*…{}需要手动加单引号

6.使用@Param标识参数

  • 可以通过@Param注解标识mapper接口中的方法参数
  • 此时,会将这些参数放在map集合中,以@Param注解的value属性值为键,以参数为值;
  • 以 param1,param2…为键,以参数为值;
  • 只需要通过KaTeX parse error: Expected 'EOF', got '#' at position 4: {}和#̲{}访问**map集合的键**…{}需要手动加单引号

六、MyBatis的各种查询功能

1.查询单个实体类对象

 User getUserById(@Param("uid") uid);
<select>
    select * from t_user where id = #{id}
</select>

2.查询list集合

list<User> getAllUser()
<select>
    select * from t_user
</select>

3.查询单个数据

  • 单个值或者聚合函数
int getAcount()
<select>
    select count(*) form emp
</select>

4.查询一条数据为map集合

Map <String , Object>  getUserToMap(@Param("id")  int  id)
  • 将表中的数据以map集合的方式查询
<select>
    select * from t_user where id = #{id}
</select>

5.查询多条数据为map集合

a>存入到list集合中

  • 存到list<map<String,Object>>中
  • 将表中的数据以map集合的方式查询,一条数据对应一个map;
  • 若有多条数据,就会产生多个map集合,此 时可以将这些map放在一个list集合中获取

b>指定键的值

  • 使用注解@MapKey(“key”)
  • 键的值一般为主键(唯一字段)
  • 最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的 map集合

七、特殊SQL执行

1. 模糊查询


`/**

\* 测试模糊查询

\* @param mohu

\* @return

*/

List<User> testMohu(@Param("mohu") String mohu);

<!--List<User> testMohu(@Param("mohu") String mohu);-->

<select id="testMohu" resultType="User">


<!--select * from t_user where username like '%${mohu}%'-->

<!--select * from t_user where username like concat('%',#{mohu},'%')-->

select * from t_user where username like "%"#{mohu}"%"

</select>`

2. 批量删除

`/**

\* 批量删除

\* @param ids

\* @return

*/

int deleteMore(@Param("ids") String ids);

<!--int deleteMore(@Param("ids") String ids);-->

<delete id="deleteMore">

delete from t_user where id in (${ids})

</delete>`

3. 动态设置表名

`/**

\* 动态设置表名,查询所有的用户信息

\* @param tableName

\* @return

*/

List<User> getAllUser(@Param("tableName") String tableName);

<!--List<User> getAllUser(@Param("tableName") String tableName);-->

<select id="getAllUser" resultType="User">


select * from ${tableName}

</select>`

4. 添加功能获取自增主键

t_clazz(clazz_id,clazz_name)

t_student(student_id,student_name,clazz_id)

  1. 添加班级信息

  2. 获取新添加的班级的id

  3. 为班级分配学生,即将某学的班级id修改为新添加的班级的id

`/**

\* 添加用户信息

\* @param user

\* @return

\* useGeneratedKeys:设置使用自增的主键

\* keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参

数user对象的某个属性中

*/

int insertUser(User user);

<!--int insertUser(User user);-->

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">

insert into t_user values(null,#{username},#{password},#{age},#{sex})

</insert>`

八、自定义映射resultMap

为什么需要自定义映射?

无疑,自动映射解决不了问题了,因为字段名和属性名不一致了

1. 处理字段和属性的映射关系

  • 解决字段名和属性名不一致的情况

  • resultMap:设置自定义映射

    • 属性:

      • id:表示自定义映射的唯一标识

      • type:查询的数据要映射的实体类的类型

    • 子标签:

      • id:设置主键的映射关系

      • result:设置普通字段的映射关系

      • association:设置多对一的映射关系 ,在多的一方创建一的属性

      • collection:设置一对多的映射关系 ,在一的一方创建集合属性存储多的一方对象

      • 属性:

        • property:设置映射关系中实体类中的属性名
        • column:设置映射关系中表中的字段名
    • 若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性 名符合Java的规则(使用驼峰)

    • 此时也可通过以下两种方式处理

      • 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
      • 可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,此配置可以在查询表中数据时,自动将_类型的字段名转换为驼峰

2. 多对一映射关系

查询员工信息以及员工所对应的部门信息

a>级联方式

`<resultMap id="empDeptMap" type="Emp">

<id column="eid" property="eid"></id>

<result column="ename" property="ename"></result>

<result column="age" property="age"></result>

<result column="sex" property="sex"></result>

<result column="did" property="dept.did"></result>

<result column="dname" property="dept.dname"></result>

</resultMap>

<!--Emp getEmpAndDeptByEid(@Param("eid") int eid);-->

<select id="getEmpAndDeptByEid" resultMap="empDeptMap">


select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did =

dept.did where emp.eid = #{eid}

</select>`

b>使用association处理映射关系


`<resultMap id="empDeptMap" type="Emp">

<id column="eid" property="eid"></id>

<result column="ename" property="ename"></result>

<result column="age" property="age"></result>

<result column="sex" property="sex"></result>

<association property="dept" javaType="Dept">

<id column="did" property="did"></id>

<result column="dname" property="dname"></result>

</association>

</resultMap>

<!--Emp getEmpAndDeptByEid(@Param("eid") int eid);-->

<select id="getEmpAndDeptByEid" resultMap="empDeptMap">


select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did =

dept.did where emp.eid = #{eid}

</select>`

c>分步查询

  1. 查询员工信息
 `/**

   \* 通过分步查询查询员工信息

   \* @param eid

   \* @return

   */

   Emp getEmpByStep(@Param("eid") int eid);

   <resultMap id="empDeptStepMap" type="Emp">

   <id column="eid" property="eid"></id>

   <result column="ename" property="ename"></result>

   <result column="age" property="age"></result>

   <result column="sex" property="sex"></result>

   <!--

   select:设置分步查询,查询某个属性的值的sql的标识(namespace.sqlId)

   column:将sql以及查询结果中的某个字段设置为分步查询的条件

   -->

   <association property="dept"

   select="com.atguigu.MyBatis.mapper.DeptMapper.getEmpDeptByStep" column="did">

   </association>

   </resultMap>

   <!--Emp getEmpByStep(@Param("eid") int eid);-->

   <select id="getEmpByStep" resultMap="empDeptStepMap">


   select * from t_emp where eid = #{eid}

   </select>`

2. 根据员工所对应的部门id查询部门信息

   `/**

   \* 分步查询的第二步:根据员工所对应的did查询部门信息

   \* @param did

   \* @return

   */

   Dept getEmpDeptByStep(@Param("did") int did);

   <!--Dept getEmpDeptByStep(@Param("did") int did);-->

   <select id="getEmpDeptByStep" resultType="Dept">


   select * from t_dept where did = #{did}

   </select>`

3. 一对多的映射关系

a>Collection

`/**

\* 根据部门id查新部门以及部门中的员工信息

\* @param did

\* @return

*/

Dept getDeptEmpByDid(@Param("did") int did);

<resultMap id="deptEmpMap" type="Dept">

<id property="did" column="did"></id>

<result property="dname" column="dname"></result>

<!--

ofType:设置collection标签所处理的集合属性中存储数据的类型

-->

<collection property="emps" ofType="Emp">

<id property="eid" column="eid"></id>

<result property="ename" column="ename"></result>

<result property="age" column="age"></result>

<result property="sex" column="sex"></result>

</collection>

</resultMap>

<!--Dept getDeptEmpByDid(@Param("did") int did);-->

<select id="getDeptEmpByDid" resultMap="deptEmpMap">


select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did =

emp.did where dept.did = #{did}

</select>`

b>分步查询

  1. 查询部门信息
  `/**

   \* 分步查询部门和部门中的员工

   \* @param did

   \* @return

   */

   Dept getDeptByStep(@Param("did") int did);

   <resultMap id="deptEmpStep" type="Dept">

   <id property="did" column="did"></id>

   <result property="dname" column="dname"></result>

   <collection property="emps" fetchType="eager"

   select="com.atguigu.MyBatis.mapper.EmpMapper.getEmpListByDid" column="did">

   </collection>

   </resultMap>

   <!--Dept getDeptByStep(@Param("did") int did);-->

   <select id="getDeptByStep" resultMap="deptEmpStep">


   select * from t_dept where did = #{did}

   </select>`

2. 根据部门id查询员工信息
   `/**

   \* 根据部门id查询员工信息

   \* @param did

   \* @return

   */

   List<Emp> getEmpListByDid(@Param("did") int did);

   <!--List<Emp> getEmpListByDid(@Param("did") int did);-->

   <select id="getEmpListByDid" resultType="Emp">


   select * from t_emp where did = #{did}

   </select>`
  1. 注意事项

    分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:

    lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

    aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个

    属性会按需加载

    此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和

    collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加

    载)|eager(立即加载)"

九、动态SQL

1. 简介

Mybatis框架的动态SQL技术(一系列标签)是一种根据特定条件动态拼装SQL语句的功能,为了解决拼接SQL语句字符串时的痛点问题。

2. if

  • if标签可通过test属性的表达式进行判断
    • 若表达式的结果为true,则标签中的内容会执行;
    • 反之标签中的内容就不会执行

3. where

  • where和if一般结合使用:
  • a>若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字
  • b>若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的 and或者or去掉
  • 注意:where标签不能去掉条件最后多余的and或or

4. trim

  • trim用于去掉或添加标签中的内容
  • 常用属性:
    • prefix:在trim标签中的内容的前面添加某些内容
    • prefixOverrides:在trim标签中的内容的前面去掉某些内容
    • suffix:在trim标签中的内容的后面添加某些内容
    • suffixOverrides:在trim标签中的内容的后面去掉某些内容

5. choose… when… ortherwise…

  • 相当于if…else if…else

6. foreach

  • 遍历集合或者数组

  • 属性:

    • collection:设置要循环的数组或集合
    • item:表示集合或数组中的每一个数据
    • separator:设置循环体之间的**分隔符 **
    • open:设置foreach标签中的内容的开始符
    • close:设置foreach标签中的内容的结束符

7. SQL片段

  • 可以记录一段重复使用的sql片段,在使用的地方通过include标签进行引入

​ eid,ename,age,sex,did

select refid=“empColumns” from t_emp

十、MyBatis缓存

1. 一级缓存

a>简介

  • 一级缓存是SqlSession级别的

  • 通过同一个SqlSession查询的数据会被缓存

  • 下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问

  • 提高了查询的速度

b>使一级缓存失效的四种情况:

  1. 不同的SqlSession对应不同的一级缓存

  2. 同一个SqlSession但是查询条件不同

  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作-----清空缓存

  4. 同一个SqlSession两次查询期间手动清空了缓存

2. 二级缓存

a>简介

  • 二级缓存是SqlSessionFactory级别

  • 通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存

  • 此后若再次执行相同的查询语句,结果才会从缓存中获取

b>二级缓存开启的条件:

  1. 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
  1. 在映射文件中设置标签<cache />
  2. 二级缓存必须在SqlSession关闭提交之后才会生效
  3. 查询的数据所转换的实体类的类必须实现序列化的接口Serializable

c>使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

3. 二级缓存相关配置

在mapper配置文件中添加的cache标签可以设置一些属性

  1. eviction属性:缓存回收策略

    • LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
    • FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    • 默认的是 LRU。
  2. flushInterval属性:刷新间隔,单位毫秒

    • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
    • size属性:引用数目,正整数,代表缓存最多可以存储多少个对象,太大容易导致内存溢出
    • readOnly属性:只读,true/false
    • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
    • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

4. MyBatis缓存查询的顺序

  • 先查询二级缓存,因为二级缓存中有多个SqlSession的数据,更容易查询到

  • 如果二级缓存没有命中,再查询一级缓存

  • 如果一级缓存也没有命中,则查询数据库

  • SqlSession关闭之后,一级缓存中的数据会写入二级缓存

5. 整合三方缓存EHCache

a>添加依赖

`<!-- Mybatis EHCache整合包 -->

<dependency>

<groupId>org.mybatis.caches</groupId>

<artifactId>mybatis-ehcache</artifactId>

<version>1.2.1</version>

</dependency>

<!-- slf4j日志门面的一个具体实现 -->

<dependency>

<groupId>ch.qos.logback</groupId>

<artifactId>logback-classic</artifactId>

<version>1.2.3</version>

</dependency>`

b>各jar包的功能

  1. mybatis-ehcache
    • Mybatis和EHCache的整合包
  2. ehcache
    • EHCache核心包
  3. slf4j-api
    • SLF4J日志门面包
  4. logback-classic
    • 支持SLF4J门面接口的一个具体实现

c>创建EHCache的配置文件ehcache.xml


`<?xml version="1.0" encoding="utf-8" ?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

<!-- 磁盘保存路径 -->

<diskStore path="D:\atguigu\ehcache"/>

<defaultCache

maxElementsInMemory="1000"

maxElementsOnDisk="10000000"

eternal="false"

overflowToDisk="true"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

</defaultCache>

</ehcache>`

d>设置二级缓存的类型

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

c>加入logback日志

存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。

创建logback的配置文件logback.xml

`<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="true">

<!-- 指定日志输出的位置 -->

<appender name="STDOUT"

class="ch.qos.logback.core.ConsoleAppender">

<encoder>

<!-- 日志输出的格式 -->

<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -

->

<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger]

[%msg]%n</pattern>

</encoder>

</appender>

<!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->

<!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->

<root level="DEBUG">

<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->

<appender-ref ref="STDOUT" />

</root>

<!-- 根据特殊需求指定局部日志级别 -->

<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>

</configuration>`

d>EHCache配置文件说明

在这里插入图片描述

十一、逆向工程

1. 简介

  1. 正向工程:
    • 先编写实体类,框架根据实体类在数据库中生成对应的表
  2. 逆向工程:
    • 框架根据数据库中的表来生成:
      • JAVA实体类
      • 映射接口
      • 映射文件

2. 逆向工程实现步骤

a>添加依赖和插件


```xml

`<!-- 依赖MyBatis核心包 -->

<dependencies>

<dependency>

<groupId>org.mybatis</groupId>

<artifactId>mybatis</artifactId>

<version>3.5.7</version>

</dependency>

</dependencies>

<!-- 控制Maven在构建过程中相关配置 -->

<build>

<!-- 构建过程中用到的插件 -->

<plugins>

<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->

<plugin>

<groupId>org.mybatis.generator</groupId>

<artifactId>mybatis-generator-maven-plugin</artifactId>

<version>1.3.0</version>

<!-- 插件的依赖 -->

<dependencies>

<!-- 逆向工程的核心依赖 -->

<dependency>

<groupId>org.mybatis.generator</groupId>

<artifactId>mybatis-generator-core</artifactId>

<version>1.3.2</version>

</dependency>

<!-- 数据库连接池 -->

<dependency>

<groupId>com.mchange</groupId>

<artifactId>c3p0</artifactId>

<version>0.9.2</version>

</dependency>

<!-- MySQL驱动 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.8</version>

</dependency>

</dependencies>

</plugin>

</plugins>

</build>`

b>创建MyBatis核心配置文件

c>创建逆向工程的配置文件

  • 文件名必须是:generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"


"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

<!--

targetRuntime: 执行生成的逆向工程的版本

MyBatis3Simple: 生成基本的CRUD(**清新简洁版**)

MyBatis3: 生成带条件的CRUD(**奢华尊享版**)

-->

<context id="DB2Tables" targetRuntime="MyBatis3Simple">

<!-- 数据库的连接信息 -->

<jdbcConnection driverClass="com.mysql.jdbc.Driver"

connectionURL="jdbc:mysql://localhost:3306/mybatis"

userId="root"

password="123456">

</jdbcConnection>

<!-- javaBean的生成策略-->

<javaModelGenerator targetPackage="com.atguigu.mybatis.bean"

targetProject=".\src\main\java">

<property name="enableSubPackages" value="true" />

<property name="trimStrings" value="true" />

</javaModelGenerator>

<!-- SQL映射文件的生成策略 -->

<sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper"

targetProject=".\src\main\resources">

<property name="enableSubPackages" value="true" />

</sqlMapGenerator>

<!-- Mapper接口的生成策略 -->

<javaClientGenerator type="XMLMAPPER"

targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java">

<property name="enableSubPackages" value="true" />

</javaClientGenerator>

<!-- 逆向分析的表 -->

<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->

<!-- domainObjectName属性指定生成出来的实体类的类名 -->

<table tableName="t_emp" domainObjectName="Emp"/>

<table tableName="t_dept" domainObjectName="Dept"/>

</context>

</generatorConfiguration>`

d>执行MBG插件的generate目标

  • 在maven工程中双击执行

3.QBC查询

  • QBC(Qurey By Criteria)就是指按规则进行查询
  • 代码实现
`@Test

public void testMBG() throws IOException {

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

SqlSession sqlSession = new

SqlSessionFactoryBuilder().build(is).openSession(true);

EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

EmpExample empExample = new EmpExample();

//创建条件对象,通过andXxx方法为SQL添加查询添加,每个条件之间是and关系

empExample.createCriteria().andEnameLike("a").andAgeGreaterThan(20).andDidIsNot

Null();

//将之前添加的条件通过or拼接其他条件

empExample.or().andSexEqualTo("男");

List<Emp> list = mapper.selectByExample(empExample);

for (Emp emp : list) {

System.out.println(emp);}

}

十二、分页插件

1. 分页插件使用步骤

a>添加依赖

<dependency><groupId>\>com.github.pagehelper</groupId><artifactId>\>pagehelper</artifactId><version>\>5.2.0</version>

</dependency>

b>配置分页插件

  • 在MyBatis的核心配置文件中配置插件
<plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>

</plugins>

2. 分页插件使用

I>在查询功能之前分页
  • 使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能
    • 属性
      • pageNum:页码
      • pageSize:每页的数据条码数
II>在获取list之后分页
  • 使用PageInfo pageInfo = new PageInfo<>(List list, int navigatePages)获取分页相关数据
  • 属性:
    • list:分页之后的数据
    • navigatePages:导航分页的页码数
III>分页相关数据
  • PageInfo{ pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8, list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30, pages=8, reasonable=false, pageSizeZero=false}, prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8, navigatepageNums=[4, 5, 6, 7, 8] }

  • 常用数据:

    • pageNum:当前页的页码
    • pageSize:每页显示的条数
    • size:当前页显示的真实条数
    • total:总记录数
    • pages:总页数
    • prePage:上一页的页码
    • nextPage:下一页的页码
  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小B学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值