MyBatis学习记录

一、框架作用

作为数据库整体解决方案,解决了高耦合的问题,ORM(object relation mapping)把javabean与数据库一一映射,把JDBC的操作封装

在这里插入图片描述
但是编写sql需要手动进行,所以mybatis把sql与java编码分离,是半自动框架

二、properties使用文件

将数据库配置信息放到properties文件中,在mybatis.xml文件中引用为reousrces
properties文件

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql:///mybatis?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

xml文件

    <properties resource="conf/dbconfig.properties">
        <!--resource:路径下的资源
            url:网络路径或者磁盘下的路径-->
    </properties>
``

```java
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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>

三、全局配置文件

在mubatis_config.xml文件名中
可以设置自动驼峰命名,还有其他参数之后再学

    <!--setting设置每一个设置项-->
<!--    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>-->

貌似不是很建议用这个参数

    <!--typeAliases:别名处理器,可以为java类型起别名,默认是类名小写-->
<!--    <typeAliases>
        &lt;!&ndash;为某个java类型起别名,别名不区分大小写,或者用注解&ndash;&gt;
        <typeAlias type="com.uestc.mybatis.Employee" alias="emp"></typeAlias>
        &lt;!&ndash;package批量起别名,指定包名批量起名&ndash;&gt;
        <package name=""/>
    </typeAliases>-->

之后做了多库再来看这个文件

    <!--id为唯一标识,在default里面来指定使用某种环境(切换id),可以快速切换
    transactionManager:事务管理器
    type:事务管理类型 POPLED,UNPOLLED,JNDI
    -->
<!--    <environments default="">
        <environment id="">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
    </environments>-->

三、映射文件(魔法源泉!)

1、参数处理规则

(1)单个参数

mb不做任何处理
#{参数名}:取出参数值

(2)多个参数

mb做特殊处理
多个参数会被封装成一个map
key:param1…paramN,或者参数的索引
value:传入的参数值
#{}就是从map获取指定的key值
推荐使用命名参数:明确指定封装的map和key

public Employee getEmp(@Param("id")Integer id, @Param("lastName")String last_name);

接口定义参数

    <select id="getEmp" resultType="emp">
        select * from tbl_employee where id = #{id} and last_name=#{lastName}
    </select>

在xml文件中来对应参数值传入位置

(3)使用POJO传递多个参数

(4)使用Map来传递

用的不多

(4 )使用TO

多个参数不是业务模型中的数据,但是经常使用,推荐写一个TO(Transfer Object)数据传输对象
Page{ int index; int size}

(5)#和¥区别

#{}以预编译的形式,将参数设置到SQL,PreparedStatement
¥{}将区处得知直接拼装到sql中,有注入安全问题
但是原生jdbc不支持占位符的地方使用¥{}进行取值

2、select语句

(1)、返回List

Mapper.xml文件

    <!--resultType为返回值的类型不是集合类型-->
    <select id="getEmpsByLastNameLike" resultType="com.uestc.mybatis.Employee">
        select * from tbl_employee where last_name like #{lastName}
    </select>

Mapper接口文件

public List<Employee> getEmpsByLastNameLike(String lastName);

Test文件就可以使用通配符查询方式查询多个对象返回集合

List<Employee> like = mapper.getEmpsByLastNameLike("%a%");

(2)、返回多条记录Map集合

Mapper.xml文件

    <!--resultType为返回值的类型不是集合类型-->
    <select id="getEmpsByLastNameLikeReturnMap" resultType="com.uestc.mybatis.Employee">
        select * from tbl_employee where last_name like #{lastName}
    </select>

Mapper接口文件

    @MapKey("id")  //注解指明封装map的key的属性
    public Map<Integer, Employee> getEmpsByLastNameLikeReturnMap(String lastName);

Test文件就可以使用通配符查询方式查询多个对象返回集合

            Map<Integer, Employee> mappp = mapper.getEmpsByLastNameLikeReturnMap("%o%");
            System.out.println(mappp);
```java
在这里插入代码片

(3)、resultMap自定义映射规则

可以自定义javabean与数据库中列名的映射规则

<mapper namespace="com.uestc.mybatis.EmployeeMapperPlus">
    <!--自定义某个javaBean封装规则
    type:自定义规则的Java类型
    id:唯一方便引用-->
    <resultMap id="MyEmp" type="com.uestc.mybatis.Employee">
        <!--指定主键列封装规则 column指定列,property指定对应javabean属性-->
        <id column="id" property="id"></id>
        <!--定义普通封装规则-->
        <result column="last_name" property="email"></result>
        <result column="email" property="last_name"></result>
        <!--其他不指定的列会自动封装,JavaBean和table中对象的属性名相同-->
    </resultMap>
    <!--resultMap自定义结果应设计规则-->
    <select id="getEmpById"  resultMap="MyEmp">
        select  * from tbl_employee where id=#{id};
    </select>
</mapper>

比如上面我们把邮箱和名字的映射换了一下,于是测试类输出

Employee{id=1, last_name='ustc.com', email='tom', gender='0'}

真的是非常的灵活哈

(4)、联表查询

1、最基础联表查询

表结构
在这里插入图片描述

在这里插入图片描述
Mapper.xml文件

    <resultMap id="DeptThing" type="com.uestc.mybatis.Employee">
        <id column="id" property="id"></id>
        <result column="last_name" property="last_name"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
<!--    <result column="id" property="dept.id"></result>
        <result column="dept_name" property="dept.deptName"></result>-->
        <association property="dept" javaType="com.uestc.mybatis.Department">
            <id column="id" property="id"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>
    <!--查出员工对应的部门-->
    <!--public Employee getEmpAndDept(Integer id);-->
    <select id="getEmpAndDept" resultMap="DeptThing">
        SELECT e.id, e.last_name, e.gender, e.email,d.id, d.dept_name FROM tbl_employee e INNER JOIN tbl_dept d ON e.d_id=d.id where e.id=#{id}
    </select>

Employee的类属性,可以直接通过点的方式来读取,也可以通过association来封装

2、使用association分布式查询

首先需要建立公司表的Mapper接口和xml文件,定义方法和查询返回对象类型,不要忘记在mybatis配置文件中注册

<mapper namespace="com.uestc.mybatis.DepartmentMapper">
    <!--public Department getDeptById(Integer id)-->
    <select id="getDeptById" resultType="com.uestc.mybatis.Department">
        select id, dept_name deptName from tbl_dept where id=#{id}
    </select>
</mapper>

分布式查询

    <!--使用association进行分步查询
       1、先通过员工id查出员工信息
       2、查询员工西席中的d_id值去部门表查询部门信息
       3、部门信息设置到员工中-->
    <resultMap id="MyEmpByStep" type="com.uestc.mybatis.Employee">
        <id column="id" property="id"></id>
        <result column="last_name" property="last_name"></result>
        <result column="gender" property="gender"></result>
        <result column="email" property="email"></result>
        <!--association封装规则
        select表明当前书信是调用select指定的方法查处结果
        column:指定将那一列的值传给这个方法
        然后把select查出的对象封装非property指定的属性-->
        <association property="dept"
                     select="com.uestc.mybatis.DepartmentMapper.getDeptById"
                            column="d_id" >
        </association>
    </resultMap>
    <!--public Employee getEmpByIdStep(Integer id);-->
    <select id="getEmpByIdStep" resultMap="MyEmpByStep">
        select * from tbl_employee where id=#{id}
    </select>

可以看到公司xml返回的对象被封装后赋予给了员工的公司属性,进一步降低了耦合,对已有方法进行组合
可以使用延迟加载,在查询员工对象时,部门信息使用时再去查询
在mybatis配置文件中进行设置

    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
3、使用collection进行分布式查询

需求:查询部门信息,同时返回部门中的员工集合

    <select id="getDeptById" resultType="com.uestc.mybatis.Department">
        select id, dept_name deptName from tbl_dept where id=#{id}
    </select>

    <!--    private Integer id;
            private String deptName;
            private List<Employee> emps;-->
    <!--id dept_name || id last_name email gender-->
    <resultMap id="MyDept!" type="com.uestc.mybatis.Department">
        <id column="id" property="id"></id>
        <result column="dept_name" property="deptName"></result>
        <!--collection定义集合类型属性封装规则
        ofType指定结合元素类型-->
        <collection property="emps" ofType="com.uestc.mybatis.Employee">
            <!--定义集合中元素封装规则-->
            <id column="id" property="id"></id>
            <result column="last_name" property="last_name"></result>
            <result column="email" property="email"></result>
            <result column="gender" property="gender"></result>
        </collection>
    </resultMap>
    <select id="getDeptByIdPlus" resultMap="MyDept!">
        SELECT d.id, d.dept_name,e.id, e.last_name , e.email, e.gender  FROM tbl_dept d LEFT JOIN tbl_employee e ON d.id=e.d_id WHERE d.id=#{id}
    </select>

下面才是分布查询,同时需要在员工接口中定义返回集合的方法

    public List<Employee> getEmpsByDeptId(Integer id);

同步在mapper文件中定义查询语句

    <select id="getEmpsByDeptId" resultType="com.uestc.mybatis.Employee">
        select * from tbl_employee where d_id=#{dept_id}
    </select>

在部门mapper中定义分布式查询语句

    <resultMap id="MyDeptStep" type="com.uestc.mybatis.Department">
        <id column="id" property="id"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="emps"
            select="com.uestc.mybatis.EmployeeMapperPlus.getEmpsByDeptId"
            column="id"
        ></collection>
    </resultMap>
    <select id="getDeptByIdStep" resultMap="MyDeptStep">
        SELECT id,dept_name FROM tbl_dept WHERE id=#{id}
    </select>
    <!--如果分布式查询,要传入的值有多列,应该封装为map传递
        column="{key1=column1,key2=column2}  fetchType="lazy/eager""
        同时在分布式被查询的地方
        where x1=#{key1} ,x2=#{key2}
        fetchType="lazy/eager" 分别表示延迟加载和立即加载-->

由于emps集合属性是存在于公司javabean中,不存在于公司数据库的列属性中,所以select中不含emps属性,而是通过resultMap中的collection来返回属性进行封装

四、动态SQL

五、缓存

    /*两级缓存
    * 一级缓存(本地缓存) sqlSession级别的缓存,一直开着起的
    *       与数据库同一次会话查询到的数据会放在本地缓存中
    *       以后如果获取相同的数据直接从缓存中拿,不再访问数据库
    *       一级缓存失效情况(没使用到一级缓存,就需要向数据库查询)
    *       1、sqlSession不同
    *       2、sqlSession相同但是查询条件不同
    *       3、sqlSession相同但是两次查询之间执行了增删改(可能会对当前数据有影响)
    *       4、sqlSession相同,手动清空一级缓存
    *           openSession.clearCache();
    * 二级缓存(全局缓存) 一个namespace对应一个二级缓存
    *       工作机制
    *       1、一个会话查询一条数据,就会放在当前会话一级缓存
    *       2、如果会话关闭:以及缓存中的数据会被保存到二级缓存中
    *       3、sqlSession==>EmployeeMapper==>Employee
    *                       DepartmengtMapper==>Department
    *                       不同的namespace查处的数据会放在自己对应的缓存中
    *       使用
    *       1、开启全局二级缓存配置:<setting name="cacheEnabled"  value="true">
            2、mapper.xml中配置二级缓存
            3、POJO需要实现序列化接口
            <eviction:缓存回收策略:
            *   LRU(默认): 最近最少使用的;移除最长时间不被使用的对象
            *   FIFO:先进先出,SPFT,WEAK:JAVA虚拟机规则
            * flushInterval:缓存刷新键和,默认不清空
            * readOnly:是否只读
            *   true:只读,mybatis认为缓存中获取数据的操作都是读操作,不会修改数据,快,不安全
            *   false:非只读:mybatis使用序列化反序列化技术克隆一份新数据给你,安全速度慢
            * >
            *
            * 查出的数据先放在一级缓存中,只有提交或者关闭以后,一级缓存数据才会转移到二级缓存
      有关设置
      * 1、cacheEnabled=false:关闭二级缓存(一级还在)
      * 2、对于每个select标签都有useCache:false不使用二级缓存
      * !3、每个增删改标签的flushCache=true  执行命令完成后就会清空一级缓存和二级缓存
      * 4、clearCache()之清除一级缓存
      *
      *
 但是我们流出了接口给第三方库哦,比如redis
 
    * */

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

六、整合Spring等框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值