mybatis框架学习笔记-狂神说

目录

一、什么是mybatis

二、第一个mybatis程序

三、Map和模糊查询扩展

四、配置之属性优化、别名优化、映射器说明

五、生命周期和作用域、Mybatis执行流程剖析

六、ResultMap结果集映射

七、日志工厂、log4j讲解

八、Limit实现分页、RowBounds分页

九、使用注解开发、注解增删改查、Lombok的使用

十、复杂查询环境搭建、多对一的处理、一对多的处理

十一、动态SQL环境搭建、IF语句、常用标签、Foreach语句

十二、缓存原理、一二级缓存、自定义缓存Ehcache

gitee仓库地址:https://gitee.com/inandout/mybatis/tree/dev/

一、什么是mybatis

1、官网

  • Mybatis是一款优秀的持久层框架
  • Mybatis支持定制化sql、存储过程、高级映射
  • Mybatis避免了几乎所有的JDBC代码、手动设置参数、获取结果集操作
  • Mybatis可以使用简单的xml、注解 来配置和映射 原生类型、接口、pojo(普通老式java对象) 为数据库中的记录

MyBatis中文网

2、百度百科

MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github

单独使用mybatis是有很多限制的(比如无法实现跨越多个session的事务),而且很多业务系统本来就是使用spring来管理的事务,因此mybatis最好与spring集成起来使用。

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的ORM字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。
  • 提供xml标签,支持编写动态sql。

开源、maven项目

 无关联依赖,只需要导入1个包

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

3、持久层

数据持久化:就是将程序的数据在瞬时状态和持久状态之间转化的过程。

  • 内存:断电即丢失(太贵了)
  • 硬盘:断电不丢失

持久层:Dao层、Service层、Controller层

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

4、从XML 中构建 SqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。后面会再探讨 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>
  <environments default="development">
    <environment id="development">
      <transactionManager type="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>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

注意 XML 头部的声明,它用来验证 XML 文档的正确性。

二、第一个mybatis程序

1、创建mybatis数据库

        create database mybatis;

创建user表

CREATE TABLE `user` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='用户表';

2、创建mybatis工程

本地创建maven工程,推送gitee仓库。

在VCS选项栏里,选择Git,点击create a git project,将本项目设为git仓库

commit -> push 

choose a remote url https://gitee.com/inandout/mybatis

创建子项目,继承了父项目的依赖

3、编写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?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>

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

</configuration>

4、编写Mapper层,增删改查实现

查全部、查单个

    <select id="getUserList" resultType="com.kuang.pojo.User">
        select *
        from mybatis.User
    </select>

    <select id="selectUserById" parameterType="int" resultType="com.kuang.pojo.User">
        select *
        from mybatis.User
        where id = #{id}
    </select>

新增

    <insert id="insertUser" parameterType="com.kuang.pojo.User">
        insert into mybatis.User
            (id, name, password)
        values (#{id}, #{name}, #{password})
    </insert>

修改

    <update id="updateUser" parameterType="com.kuang.pojo.User">
        update mybatis.User
        set name     =#{name},
            password =#{password}
            where id = #{id}
    </update>

删除

    <delete id="deleteUser" parameterType="int">
        delete
        from mybatis.User
        where id =
        #{id}
    </delete>

5、编写Dao层

package com.kuang.dao;

import com.kuang.pojo.User;

import java.util.List;

public interface UserDao {

    List<User> getUserList();

    User selectUserById(int id);

    int insertUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
}

6、编写Test层,执行测试,输出结果

    @Test
    public void insertUser() {
        // 开启连接
        try (SqlSession sqlSession = MybatisUtils.getSqlSession()) {
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            User user = new User();
            user.setName("测试1");
            user.setPassword("324");
            // 调用dao的接口
            int i = mapper.insertUser(user);
            // 打印结果
            System.out.println(i);
            // 提交事务,否则数据库里不会有值
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 关闭session
    }

三、Map和模糊查询扩展

1、万能的Map

入参为User时,所有参数都得传,而将入参改为Map,就可以只传某个参数

    <select id="selectUserByIdAndName" parameterType="map" resultType="com.kuang.pojo.User">
        select *
        from mybatis.User
        where id = #{id}
          and name = #{name}
    </select> 

    <insert id="insertUserByMap" parameterType="map">
        insert into mybatis.User
            (name, password)
        values (#{name}, #{password})
    </insert>

2、模糊查询

①Java代码执行的时候,传递通配符%%

List<User> userList = mapper.getUserListLike("%T%");

②在sql拼接中使用通配符

select * from mybatis.User where name like "李" or 1=1

sql注入问题

${}无法防止sql注入,而#{}可以防止注入

四、配置之属性优化、别名优化、映射器说明

核心配置文件:mybatis-config.xml

1、环境配置

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:

  • 每个数据库对应一个 SqlSessionFactory 实例

为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);

2、属性优化

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:

因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

propertie必须放在第一个标签,因为标签具有顺序。 

3、别名优化

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

    <typeAliases>
        <typeAlias type="com.kuang.pojo.User" alias="User"/>
    </typeAliases>

各种设置总览:

4、映射器说明

五、生命周期和作用域、Mybatis执行流程剖析

1、生命周期和作用域

官方文档

 

2、Mybatis执行流程剖析

debug+源码分析

configuration配置文件解析结果

 Executor

 mapper创建

六、ResultMap结果集映射

1、基础结果映射

resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

    <resultMap id="userResultMap" type="User">
        <id property="id" column="id"/>
        <result property="userName" column="name"/>
        <result property="passWord" column="password"/>
    </resultMap>

    <select id="getUserList" resultMap="userResultMap">
        select *
        from mybatis.User
    </select>

    <select id="selectUserById" parameterType="int" resultType="com.kuang.pojo.User">
        select id       as "userId",
               name     as "userName",
               password as "passWord"
        from mybatis.User
        where id = #{id}
    </select>

在学习了上面的知识后,你会发现上面的例子没有一个需要显式配置 ResultMap,这就是 ResultMap 的优秀之处——你完全可以不用显式地配置它们。 

2、高级结果映射

第十节,association、collection。

七、日志工厂、log4j讲解

1、日志工厂

如果一个数据库操作出现了异常,我们需要排错,日志就是最好的助手!

  • 基本的方法:sout、debug
  • 现在的办法:日志工厂

LOG4J Apache日志输出

STDOUT_LOGGING 标准日志输出

2、LOG4J

百度百科

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

导入LOG4J的包

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

配置log4j.properties文件

 在代码里添加日志打印

    static Logger logger = Logger.getLogger(UserTest.class);

    @Test
    public void testLog4j() {
        logger.info("进入了”testLog4j“方法");

八、Limit实现分页、RowBounds分页

1、Limit实现分页

通过在sql代码里拼接limit的值来实现

    <select id="getUserByLimit" parameterType="map" resultType="com.kuang.pojo.User">
        select *
        from mybatis.User limit #{startIndex},#{pageSize}
    </select>

2、RowBounds分页

List<Object> objects = sqlSession.selectList("com.kuang.dao.UserDao.getUserList", null, new RowBounds(1, 2));

直接使用mybatis自带的原生方法

 3、pageHelper

最热门的分页插件,具体请查看百度

九、使用注解开发、注解增删改查、Lombok的使用

1、增删改查

    @Select("select * from mybatis.User")
    List<User> getUserList();

    @Select("select * from mybatis.User where id = #{id}")
    User getUserById(@Param("id") int id);

    @Insert("insert into mybatis.User (id,name,password) values (#{id},#{name},#{password})")
    int addUser(User user);

    @Update("update mybatis.User set name = #{name}, password = #{password}) where id = #{id}")
    int updateUser(User user);

    @Delete("delete from mybatis.User where id = #{id}")
    int deleteUser(@Param("id") int id);

2、@Param注解

  • 基本数据类型要加,引用类型不用加
  • 只有一个参数时,可以不加

3、Lombok的使用

①安装插件 

②导入jar包

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.18</version>
        </dependency>

③使用Lombok注解

Data

整合了Getter、Setter、ToString、EqualsAndHashCode、RequiredArgsConstructor注解。

Getter

快速构建Getter方法。

Setter

快速构建Setter方法。

ToString

快速将当前对象转换成字符串类型,便于log

EqualsAndHashCode

快速进行相等判断。

十、复杂查询环境搭建、多对一的处理、一对多的处理

1、建立复杂查询环境

建立student表,teacher表,和user表整体结构完全一样

2、多对一处理

按照查询嵌套处理

    <!--按照查询嵌套处理-->
    <select id="getStudentList" resultMap="StudentTeacher">
        select *
        from mybatis.student
    </select>

    <resultMap id="StudentTeacher" type="com.kuang.pojo.Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--复杂的属性,需要单独处理-->
        <association property="teacher" column="tid" javaType="com.kuang.pojo.Teacher" select="getTeacherList"/>
    </resultMap>

    <select id="getTeacherList" resultType="com.kuang.pojo.Teacher">
        select *
        from mybatis.teacher
        where id = #{id}
    </select>

按照结果嵌套处理

    <!--按照结果嵌套处理-->
    <select id="getStudentList2" resultMap="StudentTeacher2">
        select s.id sid, s.name sname, t.name tname, t.age tage
        from mybatis.student s,
             mybatis.teacher t
        where s.tid = t.id
    </select>

    <resultMap id="StudentTeacher2" type="com.kuang.pojo.Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <!--复杂的属性,需要单独处理-->
        <association property="teacher" javaType="com.kuang.pojo.Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>

3、一对多处理

按照结果嵌套处理

 关联association

按照查询嵌套处理

集合collection

十一、动态SQL环境搭建、IF语句、常用标签、Foreach语句

1、搭建环境

创建博客表,插入数据

CREATE TABLE `blog` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) DEFAULT NULL COMMENT '标题',
  `author` varchar(100) DEFAULT NULL COMMENT '作者',
  `createTime` date DEFAULT NULL COMMENT '创建时间',
  `views` int(11) DEFAULT NULL COMMENT '点赞数',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='博客表';

2、IF语句

    <select id="getBlogList" parameterType="com.kuang.pojo.Blog" resultType="com.kuang.pojo.Blog">
        select *
        from mybatis.blog
        where 1=1
        <if test="title !=null">
            and title=#{title}
        </if>
        <if test="author !=null">
            and author=#{author}
        </if>
    </select>

3、常用标签

choose标签

    <select id="findActiveBlogLike" resultType="com.kuang.pojo.Blog">
        select *
        from mybatis.blog
        where 1=1
        <choose>
            <when test="title != null">
                AND title like #{title}
            </when>
            <when test="author != null">
                AND author like #{author}
            </when>
            <otherwise>
                AND views = #{views}
            </otherwise>
        </choose>
    </select>

trim标签

    <select id="findActiveBlogWithTitleLike" resultType="com.kuang.pojo.Blog">
        select *
        from mybatis.blog
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
            <if test="title !=null">
                and title like #{title}
            </if>
            <if test="author !=null">
                and author like #{author}
            </if>
        </trim>
    </select>

4、Foreach语句

    <select id="selectNameIn" resultType="com.kuang.pojo.Blog">
        SELECT *
        FROM mybatis.blog b
        WHERE b.title in
        <foreach item="item" index="index" collection="list"
                 open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

十二、缓存原理、一二级缓存、自定义缓存Ehcache

Mybatis包含一个非常强大的查询缓存特性,他可以非常方便的定制和配置缓存,缓存可以极大的提高查询的效率。

Mybatis系统中默认定义了两种缓存:一级缓存、二级缓存

  • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动配置和开启,他是namespace级别的缓存
  • 为了提高扩展性,Mybatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

1、缓存原理

 ①什么是缓存Cache?

  • 存在内存中的临时数据。
  • 将用户经常查询的数据放在缓存中,这样用户查询时就不用去磁盘上查询,可以直接从缓存中拿到,从而提高查询效率,解决了高并发系统的性能问题。

②为什么要使用缓存?

  • 减少和数据库的交互次数,减少系统开销,提高系统效率。

③什么样的数据能使用缓存?

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

2、一级缓存

一级缓存也叫本地缓存

  • 与数据库同一次会话期间查询到的数据会放在本地缓存中
  • 以后如果需要获取相同的数据,直接从缓存中拿,不用再从数据库查

默认情况下,启用了本地的会话缓存,它仅仅对一个sqlSession会话中的数据进行缓存。

缓存失效的场景

1、SqlSession调用了close()方法后,就失效了

2、

3、查询不同的mapper.xml

4、SqlSession.clearCache()

3、二级缓存

二级缓存也叫全局缓存,因为一级缓存得到作用域太低了,所以诞生了二级缓存。

他是基于nameSpace级别的缓存,一个名称空间对应一个二级缓存。

  • 一个session查询一条数据,这个数据就会被放在一级缓存里;
  • 这个session关闭了,我们想让他从一级缓存转移到二级缓存中;
  • 新的sesssion查询数据,就可以从二级缓存中获取结果;
  • 不同的mapper查询出的数据会放在各自的缓存map中;

开启方式:

①在核心配置文件里,通过设置开启缓存

②在mapper.xml里,通过标签开启缓存

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

在代码里进行测试

    @Test
    public void cache() {
        // 开启2个会话
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        SqlSession sqlSession2 = MybatisUtils.getSqlSession();

        List<String> list = new ArrayList<>();
        list.add("花开伊吕波");
        list.add("测试");

        BlogDao mapper = sqlSession.getMapper(BlogDao.class);
        List<Blog> userList = mapper.selectNameIn(list);
        // 同一个mapper里,一个会话查询关闭了,会保存到二级缓存中
        sqlSession.close();

        // 看是查1次,还是2次
        BlogDao mapper2 = sqlSession2.getMapper(BlogDao.class);
        List<Blog> userList2 = mapper2.selectNameIn(list);
        sqlSession2.close();
    }

提示缓存命中

4、自定义缓存Ehcache

ehcache_百度百科

东亚多数用mybatis,国外多数用hibernate和JPA

Java的缓存技术:Ehcache与Redis比较

综上所述,Ehcache适合本地缓存和单机环境下的简单应用场景,提供快速的内存访问。而Redis更适合分布式缓存和高性能、高并发的需求,提供了更多高级功能和数据持久化选项。在选择时,需要根据实际需求和项目特点进行综合考虑。

实现自定义缓存的多种方式:

①导包、然后配置别人的Cache实现

        <!--   Ehcache缓存     -->
        <dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-ehcache</artifactId>
            <version>1.2.0</version>
        </dependency>

②自己实现Cache接口

package com.kuang.utils;

import org.apache.ibatis.cache.Cache;

public class MyCache implements Cache {
    @Override
    public String getId() {
        return null;
    }

    @Override
    public void putObject(Object key, Object value) {

    }

    @Override
    public Object getObject(Object key) {
        return null;
    }

    @Override
    public Object removeObject(Object key) {
        return null;
    }

    @Override
    public void clear() {

    }

    @Override
    public int getSize() {
        return 0;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值