MyBatis框架学习

2022 5/31 

前序学习 javaSE-> MySQL-> JDBC -> ->AJAX

代理模式


1.代理模式的作用
  1)控制目标对象的访问
  2)增强功能

2.代理模式的分类 
  1)静态代理
  2)动态代理,又分为JDK动态代理,CGLib动态代理(子类代理)

静态代理

什么是静态代理
  它是代理模式的一种.
  它具备以下特点:
  1)目标对象和代理对象实现同一个业务接口
  2)目标对象必须实现接口
  3)代理对象在程序运行前就已经存在
  4)能够灵活的进行目标对象的切换,却无法进行功能的灵活处理(使用动态代理解决此问题)

动态代理


MyBatis实体类的属性名和数据库列名不一致解决方法汇总

http://wjhsh.net/yif0118-p-14601572.html

1.1.查询的sql语句中使用别名进行查询(dnp

1.2.使用resultMap映射实体

    <!--
    查询全部图书
    List<Book>  getAll();

    实体类
    private Integer id;
    private String name;
    字段的名称和实体类的属性名不一致
    方案一:起别名
    -->
 <!--   <select id="getAll" resultType="book" >
        select  bookid id  ,bookname  name
        from  book
    </select>-->


    <!--
    方案二
    resultMap="bookmap"
    -->
    <resultMap id="bookmap" type="book">
        <!--主键绑定-->
        <id property="id" column="bookid"></id>
        <!--非主键绑定-->
        <result  property="name" column="bookname"></result>
    </resultMap>
    <select id="getAll"  resultMap="bookmap">
        select  bookid   ,bookname
        from  book
    </select>

1.3.开启SpringBoot-Mybatis驼峰命令配置(默认是开启的)

瑞吉外卖中提到过!!!

一个表 address_book ——> AddressBook

或者某个字段 user_name ——> userName

#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射 map-underscore-to-camel-case: true

1.4 mp特有 @TableField()


mybatis返回主键ID 

  • 设置< insert >便签的属性 设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了(在fortune项目中用到)
  • 看一下图片

mybatisplus insert后会自动返回


记录一下mybatis主要知识点

1. 关于parameterType和resultType

  • 参数超过一个\集合\数组\简单类型 不用写parameterType  实体类必须写
  • 增删改不用写resulttype
  • resultType: 指定查询返回的结果集的类型,如果是集合,必须带泛型
    在这里决定了返回的类型
  • 实体类你可以写小驼峰是因为注册了别名
<typeAliases>
             <!--单个实体类别名的注册-->
            <!-- <typeAlias type="com.bjpowernode.bean.Student" alias="student"></typeAlias>-->

             <!--批量注册别名
                 1.主要用这种 它可以批量注册一个包下的所有类
                 2.别名是类名的小驼峰  StudentOne是studentOne
             -->
             <package name="com.bjpowernode.bean"/>
         </typeAliases>

而使用了spring boot的mybatisplus/mybatis也需要自己手动配置

2. 关于#{}和${}  、 @Param注解

2.1#{}占位符

传参大部分使用#{}传参,它的底层使用的是PreparedStatement对象,是安全的数据库访问 ,防止sql注入. #{}里如何写,看parameterType参数的类型 1)如果parameterType的类型是简单类型(8种基本(封装)+String),则#{}里随便写. 2)parameterType的类型是实体类的类型,则#{}里只能是类中成员变量的名称,而且区分大小写.

2.2${}字符串拼接或字符串替换 拼接尽量不用 因为有sql注入的风险

 不要用${}来模糊查询 掌握优化后的模糊查询

'%${username}%'     concat('%',#{username},'%')

替换:

${columnName}是字符串替换(这辈子唯一闪耀的地方)   #{columnValue}是占位 加个注解就能用
<select id="getByNameOrAddress" resultType="users">
    select id,username,birthday,sex,address
    from users
    where ${columnName} like concat('%',#{columnValue},'%')  ==>此处使用的是@Param注解里的名称
</select>

2.3 @param注解

1. 多个参数是要写的(事实上多参数可以不写该注解,但处理起来会很麻烦);

不需要用@Param注解与需要用@Param注解的情况_征程123的博客-CSDN博客

3. Mapper的注册(了解)

使用springboot以后 无论是mybatis or plus  都只需要:(1)@MapperScan注解在启动类上或者配置类上  (2)其他的配置(别名、日志、驼峰映射)都在application文件中  真的是从配置地狱中解放了出来

这是mybatis (spring springmvc中同理 )

 springboot+mybatis

 springboot+MybatisPlus 

4.动态SQL(需要熟练掌握)

<sql> <include> 一组   <if><where>一组   <set>  <foreach>

4.1<sql>

    <!--定义代码片段-->
    <sql id="allColumns">
        id,username,birthday,sex,address
    </sql>

4.2<include>  用来引用<sql>定义的代码片断

4.3<if>  

4.4<where>

    <where>中的and是条件的拼接 初始条件1=1(永真)

    -->
    <select id="getByConditions" resultType="users" parameterType="users">
          select   <include refid="allColumns"></include>
          from users
          <where>
              <if test="userName != null and userName != '' ">
                  and username like concat('%',#{userName},'%')
              </if>
              <if test="birthday !=null">
                and birthday = #{birthday}
              </if>
              <if test="sex != null and sex !='' ">
                and sex = #{sex}
              </if>
              <if test="address != null and address !='' ">
                  and address like  concat('%',#{address},'%')
              </if>
          </where>
    </select>

4.5<set>

    <!--
        有选择的更新
    int  updateBySet(Users user);
    <set>中的逗号不必纠结
    -->
    <update id="updateBySet" parameterType="users">
          update users
          <set>
                 <if test="userName != null and userName != '' ">
                     username = #{userName},
                 </if>
                 <if test="birthday !=null">
                     birthday= #{birthday},
                 </if>
                 <if test="sex != null and sex !='' ">
                     sex= #{sex},
                 </if>
                 <if test="address != null and address !='' ">
                   address = #{address},
                 </if>
          </set>
          where id = #{id}
    </update>

4.6<foreach>用来进行循环遍历,完成循环条件查询,批量删除(最常用),批量增加(掌握),批量更新(用的很少

<foreach>参数详解:

collection:用来指定入参的类型,如果是List集合,则为list,如果是Map集合,则为map,如果是数组,则为array. ​

item:每次循环遍历出来的值或对象 就是foreach中的item

​ separator:多个值或对象或语句之间的分隔符

open:整个循环外面的前括号 ​

close:整个循环外面的后括号

 <!--
     批量删除
    int    deleteBatch(Integer[] id);
    -->   
 <delete id="deleteBatch" >
          delete  from users
          where id  in
            <foreach collection="array" separator="," item="id" open="(" close=")">
                #{id}
            </foreach>
    </delete>
 <!--
      批量增加
    int    insertBatch(List<Users> list);
    private Integer id;
    private String userName;
    private Date  birthday;
    private  String sex;
    private String address;

    思考一下这里的括号 open close
    parameterType是不必要的
    -->
    <insert id="insertBatch" >
            insert  into users
            (username,birthday,sex,address)
            values
               <foreach collection="list" item="u"  separator=",">
                   (#{u.userName},#{u.birthday},#{u.sex},#{u.address})
               </foreach>
    </insert>

5.关于Map

5.1入参是map(重点掌握)

 如果入参超过一个以上,使用map封装查询条件,更有语义,查询条件更明确.

#{这里面要写的就是map的key}

5.2返回值是Map

5.3 返回多行map

6. resultMap

一个作用是映射实体  看上文;

一个是7;

7.关联关系 了解一下 用的不多

(瑞吉中的dto    dishdto中有dishflavor的List , 我们只需要用dishflavor的service/mapper再查一边就好了 )

总结:无论是什么关联关系,如果某方持有另一方的集合,则使用<collection>标签完成映射,如果某方持有另一方的对象,则使用<association>标签完成映射。


MP

application.yml

spring:
# 配置数据源信息
  datasource:
# 配置数据源类型
    type: com.zaxxer.hikari.HikariDataSource
# 配置连接数据库信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
    username: root
    password: root
#日志
mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      id-type:auto           
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  #起别名
  type-aliases-package: com.atguigu.pojo

mp中生成主键id默认使用的是雪花算法

BaseMapper、Iservice、ServiceImpl

extends 、implement ?

常用注解

1.@TableName

在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表 由此得出结论,MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定

a.问题? 若实体类类型的类名和要操作的表的表名不一致,会出现什么问题?

b>通过@TableName解决问题 在实体类类型上添加@TableName("t_user"),标识实体类对应的表,即可成功执行SQL语句 

c>通过全局配置解决问题

global-config: db-config: # 配置MyBatis-Plus操作表的默认前缀 table-prefix: t_

2 @TableId

详细看一下pdf

3.@TableField

a>情况1 若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格 例如实体类属性userName,表中字段user_name 此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格 相当于在MyBatis中配置

b>情况2 若实体类中的属性和表中的字段不满足情况1 例如实体类属性name,表中字段username 此时需要在实体类属性上使用@TableField("username")设置属性所对应的字段名

还可以通过起别名、 resultMap 一共四种方法

4 @TableLogic

>逻辑删除

条件构造器和常用接口

以后查询就用LambdaQueryWrapper

更新就用LambdaUpdateWrapper

带condition的Lambda

    @Test
    public void test11(){
        String username = null;
        Integer ageBegin = 10;
        Integer ageEnd = 24;

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper
                .like(username !=null,User::getName,"a")
                 .ge(ageBegin !=null,User::getAge,ageBegin)
                .le(ageEnd != null,User::getAge,ageEnd)
        ;

        userMapper.selectList(lambdaQueryWrapper);


    }

分页插件

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

@Configuration
@MapperScan("com.atguigu.Mapper")     //添加到这里
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor  interceptor  = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        return interceptor;
    }
}

reggie中的demo

* long current   当前页 从1开始
* long size
    /**
     * 分页查询
     * @return
     */
    @GetMapping("/page")
    public R<Page>  page(int page,int pageSize){
       Page<Category> p = new Page<>(page,pageSize);

       //根据sort进行排序
        LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(Category::getSort);

       categoryService.page(p,lambdaQueryWrapper);

        return  R.success(p);
    }

AND和OR


    @Test
    /**
     * 将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
     */
    public void test04(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .gt("age",20)           //grand than  大于
                .like("name","a")
                .or()                              //链式之间是and
                .isNull("email")
        ;
        User user = new User();
        user.setEmail("123@qq.com");

        userMapper.update(user,queryWrapper);
    }


    /**
     *  和04对比!!   条件的优先级 lamdba优先!!
     *  将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
     */
    @Test
    public void test05(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .like("name","a")
/*                .and(new Consumer<QueryWrapper<User>>() {
                    @Override
                    public void accept(QueryWrapper<User> userQueryWrapper) {
                        userQueryWrapper.gt("age",20).isNull("email");
                    }
                })*/
                .and(i -> i.gt("age",20).or().isNull("email") )
        ;
        User user = new User();
        user.setEmail("123567@qq.com");

        userMapper.update(user,queryWrapper);
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值