Mybatis全场回顾-2021-7-26

一、原生态JDBC实现数据的增删改查

二、mybatis简介

MyBatis是一个优秀的基于ORM半自动轻量级持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码

mybatis 历史

MyBatis 本是apache的一个开源项目iBatis, 2010年6月这个项目由apache software foundation 迁移到google code,随着开发团队转投到Google Code旗下,iBatis正式改名为MyBatis ,代码于2013年11月迁移到Github

ORM(Object Relational Mapping)对象关系映射

  • O(对象模型):

    实体对象,即我们在程序中根据数据库表结构建立的一个个实体javaBean

  • R(关系型数据库的数据结构):

    关系数据库领域的Relational(建立的数据库表)

  • M(映射):

    从R(数据库)到O(对象模型)的映射,可通过XML文件映射

实现:

(1)让实体类和数据库表进行一一对应关系

		先让实体类和数据库表对应

		再让实体类属性和表里面字段对应

(2)不需要直接操作数据库表,直接操作表对应的实体类对象

ORM是一种思想帮助我们跟踪实体的变化,并将实体的变化翻译成sql脚本,执行到数据库中去,也就是将实体的变化映射到了表的变化。

mybatis采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作

三、初级查询

mybatis实操,用mybatis实现对用户的增删改查

3.1执行流程
  1. 创建表
  2. 建工程,导入包依赖
  3. 编写实体类
  4. 写接口和对应的xml文件
  5. 建mybatis核心配置文件
    1. 包的别名
    2. 数据库环境(数据源)
    3. mapper配置
  6. 写代码
    1. 加载核心配置文件
    2. sqlSessionFactory
    3. SqlSession
    4. 调用方法
    5. 打印结果
    6. 提交事务
    7. 释放资源
3.2 配置文件
  1. properties标签
  • <properties resource="db.properties"/>
  1. setting标签

  2. typeAliases标签

  3. environment标签

  • environments-environment:transactionManager&dataSource
  • 事务管理器: JDBC,MANAGED
  • 数据源:POOLED,UNPOOLED,JNDI
  1. mapper标签

四、mybatis几大对象的介绍以及执行流程和原理的总结归纳

五、高级查询

  • resultMap 结果集映射
5.1 、多条件查询 (sql语句中不止一个参数)
  1. 使用 #{arg0}-#{argn} 或者 #{param1}-#{paramn} 获取参数

select * from user where username = #{username} and password = #{password}

<select * from user where id = #{arg0} and username = #{arg1} > 

<select * from user where id = #{param1} and username = #{param2} >
  1. 使用注解,引入 @Param() 注解获取参数
public List<User> findByIdAndUsername2(@Param("id") Integer id,@Param("username") String username);
<select id="findByIdAndUsername2" resultType="user"> select * from user where id = #{id} and username = #{username} </select>
  1. 使用pojo对象传递参数
public List<User> findByIdAndUsername3(User user);
<select id="findByIdAndUsername3" parameterType="com.lagou.domain.User" 		resultType="com.lagou.domain.User"> 
    select * from user where id = #{id} and username = #{username}
</select>
5.2 、模糊查询
5.3、${} #{} 区别【笔试题】

#{} 表示一个占位符号

  • 通过 #{} 可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,
  • #{}可以有效防止sql注入。
  • #{} 可以接收简单类型值或pojo属性值。
  • 如果parameterType传输单个简单类型值, #{} 括号中名称随便写。

${} 表示拼接sql串

  • 通过 ${} 可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,会出现sql注入问题。
  • ${} 可以接收简单类型值或pojo属性值。
  • 如果parameterType传输单个简单类型值, ${} 括号中只能是value。
5.4、动态Sql
一、if
  • 基础语法格式
<select id="">
	SELECT * FROM BLOG
    WHERE state = 'ACTIVE'
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test = "author != null and author_name != null">
    	AND author_name like #{author_name}
    </if>
</select>
二、choose(when, otherwise)
  • 类似于Java中的switch语句

  • 只会匹配一个,即匹配到第一个符合的条件之后,就会跳过后面的。并且其中也有一个类似于DEFAULT的语句,叫做otherwise,但是在这个里面,otherwise必须有

  • 基础语法

  • <select id="">
    	SELECT * FROM BLOG
        WHERE state = 'ACTIVE'
        <choose>
            <when test="title != null">
                AND title like #{title}
            </when>
            <when test = "author != null and author_name != null">
                AND author_name like #{author.name}
            </when>
            <otherwise>
                AND featured = 1
            </otherwise>
        </choose>
    </select>
    
三、trim(where, set)
  • where标签,只会在子语句中有值存在的情况下,才会在最后的sql语句中,加上 WHERE 关键字,如果所有的子标签都为否,即没有子标签则不存在。
  • 如果匹配成功的子句中,前面有一个AND,那么where标签会自动的将AND去掉
<select id="">
	SELECT * FROM BLOG
   	<where>
        <choose>
            <when test="title != null">
                AND title like #{title}
            </when>
            <when test = "author != null and author_name != null">
                AND author_name like #{author.name}
            </when>
            <otherwise>
                AND featured = 1
            </otherwise>
    	</choose>
    </where>
</select>
  • set标签
<update>
	update Author
    <set>
    	<if></if>
        <if></if>
    </set>
</update>
四、foreach
5.5 、多表查询
一对一
  • 一、实现功能:根据订单查询对应的用户。一对一
  • 二、Sql语句
select * from mybatis2.orders o
left join mybatis2.users u
on o.uid = u.uid
  • 分析代码:
<resultMap id="orderMap" type="com.simon.entity.Order">
        <id property="id" column="uid" />
        <result property="orderTime"  column="ordertime"/>
        <result property="total" column="total"/>
        <!--配置关联的属性
            association 关联的属性是一个实体类
            property="user"
            javaType="User"  关联属性的类型
        -->
        <association property="user"  javaType="User">
            <!--这一行没有-->
            <id property="id" column="uid"/>

            <result property="username" column="username"/>
            <result property="birthday" column="birthday"/>
            <result property="sex" column="sex"/>
            <result property="address" column="address"/>
        </association>
    </resultMap>

    <!--关联查询-->
    <select id="findAllOrdersAndUser" resultMap="orderMap">
        select * from mybatis2.orders o
        left join mybatis2.users u
        on o.uid = u.uid
    </select>
  • 错误代码
Mapped Statements collection already contains value for com.simon.dao.OrderMapper.findAllOrdersAndUser
一对多
  • 一、实现功能:根据用户找到对应的订单 一对多

  • 二、代码

  • sql

select * from users u
left join orders o
on u.uid = o.uid
  • User.java

  • private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    private List<Order> orders;
    
  • Order.java

  • private Integer id;
    private String orderTime;
    private Double total;
    private Integer uid;
    
  • 被包含的即==‘多’==,

    • 使用的类型是ofType,而不是javaType
    • 使用的是collection而不是association

错误代码

Cause: org.apache.ibatis.reflection.ReflectionException: Could not set property 'orders' of 'class com.simon.entity.User' with value 'Order{id=1, orderTime='2020-12-12', total=3000.0}' Cause: java.lang.IllegalArgumentException: argument type mismatch

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

<mapper namespace="com.simon.dao.UserMapper">
    <resultMap id="userMap" type="com.simon.entity.User">
        <!--这一行没有都行,没有影响-->
        <id property="id" column="uid"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="orders"  ofType="com.simon.entity.Order">
            <id property="id" column="id" />
            <result property="orderTime"  column="ordertime"/>
            <result property="total" column="total"/>
            <result property="uid" column="uid"/>
        </collection>
    </resultMap>
    <!--关联查询-->
    <select id="findOrderByUser" resultMap="userMap">
        select * from mybatis2.users u
        left join mybatis2.orders o
        on u.uid = o.uid
    </select>

</mapper>
  • Test.java

  • @Test
    public void orderToUserTest(){
        SqlSession sqlSession = MybatisUtil.get_sqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        List<User> users = mapper.findOrderByUser();
        for (User user : users) {
            System.out.println(user);
        }
        sqlSession.close();
    }
    
多对多(跟一对多类似)
  • 一、实现功能:根据角色表去找用户,中间要借助sys_user_role表

  • 二、sql语句

select * from sys_role sr
left join sys_user_role sur
on sr.id = sur.userid
left join users u
on sur.userid = u.uid
5.6、嵌套查询
一对一(订单-用户)

OrderMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.simon.dao.OrderMapper">
    <resultMap id="orderMap1" type="order">
        <id column="id" property="id"/>
        <result column="ordertime" property="orderTime"/>
        <result column="total" property="total"/>
        <!--
            select 代表要嵌套那个查询语句
            column 表示要传递那个参数
            fetchType="lazy" 局部懒加载
        -->
        <association fetchType="lazy" property="user" javaType="user" select="com.simon.dao.UserMapper.findUserById" column="uid">

        </association>
    </resultMap>
    <select id="OrderToUser"  resultMap="orderMap1">
        select * from orders
    </select>
    <!--============================================-->
    
</mapper>
UserMapper.xml
<select id="findUserById"  parameterType="_int" resultType="user">
    select * from users where uid = #{uid}
</select>
一对多(用户到订单)

USerMapper.xml

<resultMap id="userMap1" type="user">
    <id column="uid" property="id"/>
    <result column="birthday" property="birthday"/>
    <result column="sex" property="sex"/>
    <result column="address" property="address"/>

    <!--
            select 代表要嵌套那个查询语句,通过全限定名
            column 表示要传递那个参数  ,即通过那个属性相连接
            一对多的话,property传的就是一对应的那个多,在一实体类中的变量名
            如果对应的是多,那么一定要用collection
        -->
    <collection property="orders" ofType="order" select="com.simon.dao.OrderMapper.findOrderByUid" column="uid">

    </collection>
</resultMap>

<select id="findAllUsersToOrder" resultMap="userMap1">
    select * from users
</select>

OrderMapper.xml

<select id="findOrderByUid" parameterType="_int" resultType="order">
    select * from orders where uid = #{uid}
</select>
多对多(用户对应角色)

UserMapper.xml

<resultMap id="userMap2" type="user">
    <id column="uid" property="id"/>
    <result column="birthday" property="birthday"/>
    <result column="sex" property="sex"/>
    <result column="address" property="address"/>

    <!--
            select 代表要嵌套那个查询语句,通过全限定名
            column 表示要传递那个参数  ,即通过那个属性相连接
            一对多的话,property传的就是一对应的那个多,在一实体类中的变量名
            如果对应的是多,那么一定要用collection
        -->
    <collection property="roles" ofType="role" select="com.simon.dao.RoleMapper.UserToRoleByUserId" column="uid">

    </collection>
</resultMap>

<select id="UserToRole" resultMap="userMap2">
    select * from users
</select>

RoleMapper.xml

<select id="UserToRoleByUserId" parameterType="_int" resultType="role">
    select * from sys_role sr, sys_user_role sur
    where sr.id = sur.roleid and sur.userid = #{uid}
</select>
小结

一对一配置:使用+做配置,通过column条件,执行select查询 ,javaType

一对多配置:使用+做配置,通过column条件,执行select查询 ,ofType

多对多配置:使用+做配置,通过column条件,执行select查询 ,ofType

优点:简化多表查询操作

缺点:执行多次sql语句,浪费数据库性能

六、缓存

6.1一级缓存
6.2二级缓存

七、注解开发

小结

注解开发和xml配置优劣分析

1.注解开发和xml配置相比,从开发效率来说,注解编写更简单,效率更高。

2.从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

荆北彭于晏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值