SpringMybatis

目录

什么是Mybatis

Mybaits的优点与缺点以及使用场合?

参数解析

动态sql

 通过注解实现

 MybatisPlus

MP生效配置

 MP常用操作

总结:

#{}和${}的区别是什么?

Mybatis的一级,二级缓存:

 Mybatis是如何进行分页的?分页插件的原理是什么?

为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?


什么是Mybatis

Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注Sql语句本身,不需要花费精力去处理加载驱动,创建链接,创建statement等繁杂的过程,程序元直接编写原生态sql,可以严格控制sql执行性能,灵活度高。

Mybatis可以使用XML或者注释来配置和映射原生信息,将POJO映射成数据库中的记录,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。

通过XML文件或注释的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回

Mybaits的优点与缺点以及使用场合?

优点:
1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)
3)能够与Spring很好的集成提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护
缺点:
1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求
2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库
使用场合
MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择

Mybatis实现数据查询时的两种sql写法

1.将所有的SQl语句都写到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="cn.pqz.emsboot.modules.output.mapper.OutputLogMapper">
    <select id="getOutputLogList" resultType="cn.pqz.emsboot.modules.output.entity.OutputLog">
       SELECT ol.*,u.username from output_log ol,user u where ol.operator=u.id and ol.oid = #{oid}
   </select>
</mapper>

id是mapper接口中的抽象方法名

package cn.pqz.emsboot.modules.output.mapper;

import cn.pqz.emsboot.modules.output.entity.OutputLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface OutputLogMapper extends BaseMapper<OutputLog> {
    public List<OutputLog> getOutputLogList(Integer oid);
}

resultType是映射数据库列名的属性类的全路径

package cn.pqz.emsboot.modules.output.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

@Data
public class OutputLog implements Serializable {

    private Integer id;
    private String orderNum;
    private String orderName;
    private Date startTime;
    private Date endTime;
    private Integer oid;
    private Integer operator;
    @TableField(exist = false)
    private String username;
}

调用在severe里面调用

package cn.pqz.emsboot.modules.output.service;

import cn.pqz.emsboot.modules.output.entity.OutputLog;
import cn.pqz.emsboot.modules.output.mapper.OutputLogMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class OutputLogService extends ServiceImpl<OutputLogMapper, OutputLog> {
    @Autowired
    private OutputLogMapper outputLogMapper;

    public List<OutputLog> getOutputLogList(Integer oid){
        return outputLogMapper.getOutputLogList(oid);
    }
}

参数解析

别名:alias

在sqlMapConfig.xml配置,映射文件中直接写对象名称即可

<typeAliases>
<typeAlias type="cn.mybatis.pojo.User" alias="User"/>
</typeAliases>

参数值:parameterType

指定参数类型,通常制定一个对象类型

返回值:resultType

非常重要的东西,即完成ORM的映射关系所在,这里指定的cd.tedu.mybatis.domain.User代表把结果集转换成一个User对象实例。

返回值:resultMap

resultMap用于对复杂对象结构时,对应的ResultMap结构名称

2.可以将sql语句通过注解的方式标识在接口方法中(只适用于简单操作)

在这里插入图片描述

动态sql

1.同一个dao的方法,根据不同的条件表示不同的sql语句主要是where部分有变化

2.使用mybatis提供的标签,实现动态sql能力,主要使用如 if, where, foreach, sql;

3.使用动态sql的时候,dao方法的形参使用java对象;

4.多条件查询时可以使用动态sql;

 通过注解实现

说明:该注解一般都是操作简单的数据查询,如果遇到相关查询、复杂sql则使用Mapper映射文件的形式更加通用

在这里插入图片描述

 Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?

还有很多其他的标签<resultMap><parameterMap><sql><include><selectKey>,加上动态 sql 的 9 个标签, trim|where|set|foreach|if|choose|when|otherwise|bind 等,其中为<sql>片段标签,通<include>过标签引入 sql 片段,<selectKey> 为不支持自增的主键生成策略标签

MybatisPlus

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生

使用MP主要完成单表的CURD操作简化开发,提高开发效率

编辑POJO类

说明:
1.POJO应该与数据库中的表完成映射
2.POJO中的属性与表中的字段一一映射.

注解:
1. @TableName(“demo_user”) //实现对象与表名映射
2. //设定主键自增 @TableId(type = IdType.AUTO)
3. @TableField(“name”) 实现属性与字段映射.
规则: 如果属性与字段的名称一致,则注解可以省略

实际用法:

在这里插入图片描述

 配置过程

在这里插入图片描述

MP生效配置

说明: 将原来的mybatis 改为mybatis-plus
在这里插入图片描述

 MP常用操作

根据ID查询

//1.根据id主键 查询id=1的数据
    //SELECT id,name,age,sex FROM demo_user WHERE id=?
    @Test
    public void testSelect1(){
        User user = userMapper.selectById(1);
        System.out.println(user);
    }

selectList查询(一)

	//2.查询name="小乔" sex="男"的用户
    //Sql: select * from demo_user where name="xx" and sex="xx"
    @Test
    public void testSelect2(){
        //创建条件构造器 封装where条件的.
        User user = new User();
        user.setName("小乔").setSex("男");
        //实现时会动态的根据对象中不为null的属性,拼接where条件,
        //默认的关系链接符 and
        QueryWrapper queryWrapper = new QueryWrapper(user);
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询(二)

  //3.查询name="小乔" sex="男"的用户
    //Sql:SELECT id,name,age,sex FROM demo_user WHERE name=? AND sex=?
    @Test
    public void testSelect3(){
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.eq("name","小乔")
                    .eq("sex","男");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询(三)

//4.查询 age> 18 sex="女"的用户
    //Sql:SELECT * demo_user WHERE age > 18 and sex="女"
    //逻辑运算符  > gt, < lt, = eq, >= ge, <= le, != ne
    @Test
    public void testSelect4(){
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.gt("age",18)
                    .eq("sex","女");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询-like关键字

//5. like关键字
    //5.1 查询name包含"乔" where name like '%乔%'
    //5.2 查询name以乔结尾的 where name like '%乔'
    @Test
    public void testSelect5(){
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        //queryWrapper.like("name","乔");
        queryWrapper.likeLeft("name","乔");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询-in关键字

 /**
     *  6. in 关键字
     *  需求: 查询ID为1,3,5,6的数据
     *  Sql: select * from demo_user where id in (1,3,5,6)
     */
    @Test
    public void testSelect6(){
        //一般的数组采用包装类型,使用对象身上的方法  基本类型没有方法
        Integer[] ids = {1,3,5,6};
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.in("id",ids);
        //采用可变参数类型 实现查询
        //queryWrapper.in("id",1,3,5,6);
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询-order by

/**
     * 关键字: order by  排序
     * 默认规则:  升序 asc   如果降序 desc
     * 需求: 查询性别为男的用户并且 按照年龄降序排列.
     * Sql: select * from demo_user where sex="男" order by age desc
     */
    @Test
    public void testSelect7(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sex","男")
                    .orderByDesc("age");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询-动态sql

 /**
     * 动态Sql:
     *  根据用户的条件,动态的拼接where条件
     *  案例: 根据sex,age查询数据
     *  1.select * from demo_user where age > 18 and sex="女"
     *  API说明:
     *      queryWrapper.gt(判断条件,字段名称,字段值)
     *      判断条件: true  则动态的拼接where条件
     *               false 不会拼接where条件
     *  判断语句:
     *       Boolean sexBoo = (sex !=null) && sex.length()>0;
     */
    @Test
    public void testSelect8(){
        Integer age = 18;
        String sex = "女";
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        Boolean ageBoo = (age !=null);
        Boolean sexBoo = StringUtils.hasLength(sex);
        queryWrapper.gt(ageBoo, "age",age)
                    .eq(sexBoo,"sex","女");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

selectList查询-objs

  /**
     * 练习9: 只获取主键ID的值
     * Sql: select id from demo_user
     */
    @Test
    public void testSelect9(){
       List idList = userMapper.selectObjs(null);
        System.out.println(idList);
    }

删除操作

	/**
     * 练习10: 删除name="xxx"的数据
     */
    public void testDelete(){
        //删除ID为100的数据
        userMapper.deleteById(100);
        //userMapper.deleteBatchIds(null);
        //删除操作的条件构造器
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("name","xxx");
        userMapper.delete(queryWrapper);
    }

更新操作-ById

 /**
     * 练习11: 数据修改
     * 案例1:  要求修改id=233 name改为="晚上吃什么"
     * API说明: userMapper.updateById(对象信息)
     */
    @Test
    public void testUpdate(){
        //修改除ID之外的所有不为null的数据,id当作where一位条件
        User user = new User();
        user.setId(233).setName("晚上吃什么");
        userMapper.updateById(user);
    }

更新操作-任意字段

 /**
     * 练习12: 数据修改
     * 案例2:  将name=mp的用户改为name="宵夜吃什么" age=20 sex=女
     * API说明:
     *         userMapper.update(对象,修改条件构造器)
     *         对象: 修改后的数据使用对象封装
     *         修改条件构造器: 负责修改的where条件
     */
    @Test
    public void testUpdate2(){
        User user = new User();
        user.setName("宵夜吃什么").setAge(20).setSex("女");
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("name","MP");
        userMapper.update(user,updateWrapper);
    }

总结:

#{}和${}的区别是什么?

  1. #{}是预编译处理,${}是字符串替换
  2. Mybatis在处理#{}时,会将sql中的#{}替换成?号,调用PreparedStatement的set方法来赋值
  3. Mybatis在处理${}时,就是把${}替换成变量的值
  4. 使用#{}可以有效的防止sql注入,提高安全性

Mybatis的一级,二级缓存:

  1. 一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Session,当Session flush或者close之后,该Session中的所有Cache就将清空,默认打开一级缓存
  2. 二级缓存与一级缓存其机制相同,默认也是采用PerpetualCache,HashMap存储,不同在于其存储作用域为Mapper,并且可以自定义存储源,如Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口,可在它的映射文件中配置判断是否刷新。
  3. 对于缓存数据更新机制,当某个作用域(一级缓存Session、二级缓存Namespaces)的进行了CUD操作后,默认该作用域下所有select中的缓存将被clear掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新

 Mybatis是如何进行分页的?分页插件的原理是什么?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值