Mybatis-plus和Mybatis的区别和详情讲解(附代码详解)

2年前 (2022) 程序员胖胖胖虎阿
286 0 0

文章目录

  • 1.简介
  • 2.Mybatis
    • 2.1Mapper层
    • 2.2Service层
    • 2.3Controller层
  • 3.Mybatis-plus
    • 3.1为什么使用mybatis-plus?
    • 3.2如何使用它Mybatis-plus?
    • 3.3如何实现一些特殊的sql语句呢?
  • 4.总结

1.简介

首先,在介绍Mybatis-plus之前呢,明怀我想给大家介绍一下Mybatis,其实mp(mybatis-plus)是对mybatis的一个增强,我更推荐大家在使用的时候可以结合着Mybatis和mp一起使用

2.Mybatis

Mybatis-plus和Mybatis的区别和详情讲解(附代码详解)

2.1Mapper层

mybatis在使用的过程当中,这里我再简要地来做一下讲解吧,首先也是建立相应的数据库表,然后再通过建立对应的实体类,着我想没必要再写上了吧,然后,需要做的就是书写对应的接口:

package com.example.qhb.model.mapper;

import com.example.qhb.model.entity.RedDetail;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

/*
2022.1.18
 */

@Service

public interface RedDetailMapper {
    int deleteByPrimaryKey(Integer id);//根据主键id删除
    int insert(RedDetail record);//插入数据记录
    int insertSelective(RedDetail record);//插入数据记录
    RedDetail selectByPrimaryKey(Integer id);//根据主键id查询记录
    int updateByPrimaryKeySelective(RedDetail record);//更新数据记录
    int updateByPrimaryKey(RedDetail record);//更新数据记录

}

然后,我们又该怎么做呢,那就是针对这个接口设置相应的相应的xml文件,在这里面就是设置的是:

1.建立结果集映射,也就是代码中的resultMap。
2.根据具体的sql语句,书写出来对应的sql

<?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.example.qhb.model.mapper.RedDetailMapper">
    <!--定义查询结果集映射-->
    <resultMap id="BaseResultMap" type="com.example.qhb.model.entity.RedDetail">
        <result column="id" property="id" jdbcType="INTEGER"/>
        <result column="record_id" property="recordId" jdbcType="INTEGER"/>
        <result column="amount" property="amount" jdbcType="DECIMAL"/>
        <result column="is_active" property="isActive" jdbcType="TINYINT"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
    </resultMap>

    <sql id="Base_Column_List">
        id,record_id,amount,is_active,create_time
    </sql>

    <!--根据主键查询数据库-->
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">
        select
             <include refid="Base_Column_List"/>
        from red_detail
        where id=#{id,jdbcType=INTEGER}
    </select>

    <!--根据主键删除数据记录-->
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
           delete from red_detail
           where id = #{id, jdbcType=INTEGER}
    </delete>
    <!--新增数据记录(不带判断条件)-->
    <insert id="insert" parameterType="com.example.qhb.model.entity.RedDetail" >
           insert into red_detail (id, record_id, amount, is_active, create_time)
                       values (#{id, jdbcType=INTEGER}, #{recordId, jdbcType=INTEGER},
                               #{amount,jdbcType=DECIMAL},
                                               #{isActive, jdbcType=TINYINT},
                               #{createTime, jdbcType=TIMESTAMP})
    </insert>
    <!--新增数据记录(带判断条件)-->
    <insert id="insertSelective" parameterType="com.example.qhb.model.entity.RedDetail" >
            insert into red_detail           <trim prefix="(" suffix=")" suffixOverrides=",">
                <if test="id ! = null" >id ,</if>
                <if test="recordId ! = null" >record_id,  </if>
                <if test="amount ! = null" >amount,</if>
                            <if test="isActive ! = null" >
                                           is_active,
                </if>           <if test="createTime ! = null" >
                                          create_time,
                </if>          </trim>
                                     <trim prefix="values (" suffix=")" suffixOverrides=", " >
                                                   <if test="id ! = null" >
                                                                 #{id, jdbcType=INTEGER},
                </if>             <if test="recordId ! = null" >
                                           #{recordId, jdbcType=INTEGER},
                </if>             <if test="amount ! = null" >
                                            #{amount, jdbcType=DECIMAL},
                </if>             <if test="isActive ! = null" >
                                             #{isActive, jdbcType=TINYINT},
                </if>             <if test="createTime ! = null" >
                                           #{createTime, jdbcType=TIMESTAMP},
                </if>
                         </trim>
                                  </insert>
    <!--更新数据记录-->
    <update id="updateByPrimaryKeySelective" parameterType="com.example.qhb.model.entity.RedDetail" >
           update red_detail           <set >
               <if test="recordId ! = null" >
                              record_id = #{recordId, jdbcType=INTEGER},
               </if>
                             <if test="amount ! = null" >
                                          amount = #{amount, jdbcType=DECIMAL},
               </if>
                          <if test="isActive ! = null" >
                                        is_active = #{isActive, jdbcType=TINYINT},
               </if>
                         <if test="createTime ! = null" >
                                       create_time = #{createTime, jdbcType=TIMESTAMP},
               </if>          </set>          where id = #{id, jdbcType=INTEGER}
</update>

    <!--更新数据记录-->
    <update id="updateByPrimaryKey" parameterType="com.example.qhb.model.entity.RedDetail">
            update red_detail
             set record_id=#{recordid,jdbcType=INTEGER},
             amount=#{amount,jdbcType=DECIMAL},
             is_active=#{isActive,jdbcType=TINYINT},
            create_time=#{createTime,jdbcType=TIMESTAMP}
            where id=#{id,jdbcType=INTEGER}
    </update>
</mapper>

2.2Service层

接下来,对应的就是编写相应的service层,你需要哪些业务的时候,只需要设置相应的接口,然后对这些接口进行实现类的操作,那么下一次就是可以在Controller里面通过指定相应的方法来执行。
首先,这里也是进行相应的接口编写,这个接口里面的名字,就要仔细思考,尽量和实际的业务名称一样才行。

package com.example.qhb.server.service;

import com.example.qhb.server.dto.RedPacketDto;

import java.math.BigDecimal;
import java.util.List;

public interface IRedService {
    //记录发红包时红包的全局唯一标识串、随机金额列表和个数等信息入数据库
    void recordRedPacket(RedPacketDto dto, String redId, List<Integer> list)
        throws Exception;
    //记录抢红包时用户抢到的红包金额等信息入数据库
    void recordRobRedPacket(Integer  userId, String redId, BigDecimal amount) throws Exception;

}

接下来就是针对着这些接口,设置相应的实现类,这里面的实现,首先要注意以下几点:

1.首先是要通过Autowired进行对应Mapper实例的注入
2.在对应的Service方法里面进行mapper的引用即可

2.3Controller层

在这一层当中,我们需要注意的就是设置对应的访问地址信息,然后建立通过Service层的访问即可…

3.Mybatis-plus

3.1为什么使用mybatis-plus?

看了上面的mybatis的一些配置,看了之后,明怀我属实都有点麻木了,怎么只是介绍了一个mapper都要配置那么多的sql语句,一旦落实到大的项目中,那岂不是玩完了吗,于是,我想到了借用mp来进行封装,mp完全脱离了大量的xml文件的配置,内置通用Mapper,通用Service,支持多种主键策略,包括解决主键自增问题,也就是只需要在接口、实体类、实现类中实现固定的继承,就可以完成大量的sql语句封装,这样岂不是更加轻松了吗,好啦,话不多说,我们直接开讲!

3.2如何使用它Mybatis-plus?

首先,我们需要保证自己是使用Spring-boot框架来搭建出的项目,于是这个时候,我们就可以先引入依赖
1.引入依赖

<!-- mybatis mybatis-plus mybatis-spring mvc -->  
<dependency>  
    <groupId>com.baomidou</groupId>  
    <artifactId>mybatis-plus</artifactId>  
    <version>${mybatis-plus.version}</version>  
</dependency>  

接下来就是建立相应的实体类,包括对应表的column
2.建立实体类

package com.atguigu.yygh.model.hosp;

import com.atguigu.yygh.model.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * <p>
 * HospitalSet
 * </p>
 *
 * @author qy
 */
@Data
@ApiModel(description = "医院设置")
@TableName("hospital_set")
public class HospitalSet extends BaseEntity {
	
	private static final long serialVersionUID = 1L;

	@ApiModelProperty(value = "医院名称")
	@TableField("hosname")
	private String hosname;

	@ApiModelProperty(value = "医院编号")
	@TableField("hoscode")
	private String hoscode;

	@ApiModelProperty(value = "api基础路径")
	@TableField("api_url")
	private String apiUrl;

	@ApiModelProperty(value = "签名秘钥")
	@TableField("sign_key")
	private String signKey;

	@ApiModelProperty(value = "联系人姓名")
	@TableField("contacts_name")
	private String contactsName;

	@ApiModelProperty(value = "联系人手机")
	@TableField("contacts_phone")
	private String contactsPhone;

	@ApiModelProperty(value = "状态")
	@TableField("status")
	private Integer status;

}

接下来我们需要做的就是书写对应的接口,其实就是很简单的实现了mapper一起的操作

package com.atguigu.yygh.hosp.mapper;

import com.atguigu.yygh.model.hosp.HospitalSet;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface HospitalSetMapper extends BaseMapper<HospitalSet> {

}

那么我们进入这个BaseMapper<HospitalSet>进去看看到底写了什么

package com.baomidou.mybatisplus.core.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;

public interface BaseMapper<T> extends Mapper<T> {
    int insert(T entity);

    int deleteById(Serializable id);

    int deleteByMap(@Param("cm") Map<String, Object> columnMap);

    int delete(@Param("ew") Wrapper<T> wrapper);

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    int updateById(@Param("et") T entity);

    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

    T selectById(Serializable id);

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

    T selectOne(@Param("ew") Wrapper<T> queryWrapper);

    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}

这里面就已经帮我们封装好了对应的方法,我们只需要继承他,然后把实例放进去就可以了,然后我们进行的操作就是在Service里面进行一个继承

public interface HospitalSetService extends
 IService<HospitalSet> {
}

接下来就是在实现类中再进行一个继承

package com.atguigu.yygh.hosp.service.impl;

import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import com.atguigu.yygh.hosp.mapper.HospitalSetMapper;
import com.atguigu.yygh.hosp.service.HospitalSetService;
import com.atguigu.yygh.model.hosp.HospitalSet;
import com.atguigu.yygh.vo.order.SignInfoVo;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.management.Query;

@Service
public class HospitalSetServiceImpl extends ServiceImpl<HospitalSetMapper, HospitalSet> implements HospitalSetService {


}

但是,不知道大家发现没有,假如我们要进行分页的查询,该怎么半呢,如果是使用mybatis的话,那么书写起来还算方便,但是使用这个mp的话,我们就需要自己来进行构造,在这里面,我们需要明白的一个东西就是抽象类的一个构造,这个就是Wrapper

3.3如何实现一些特殊的sql语句呢?

样例1:
比如说我们在书写特殊的,例如根据传递过来的实体,来返回对应的另外的实体的时候,我们该怎么半呢,这个时候,我们只需要做的操作就是引入Wrapper,这里面我暂时收集了两个,分别是QuerryWrapper(查询)和updateWrapper(更新),好了,我们现在就开始


    //2 根据传递过来医院编码,查询数据库,查询签名
    @Override
    public String getSignKey(String hoscode) {
        QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>();
        wrapper.eq("hoscode",hoscode);
        HospitalSet hospitalSet = baseMapper.selectOne(wrapper);
        return hospitalSet.getSignKey();
    }


    @Override
    public SignInfoVo getSignInfoVo(String hoscode) {
        QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>();
        wrapper.eq("hoscode",hoscode);
        HospitalSet hospitalSet = baseMapper.selectOne(wrapper);
        if(null == hospitalSet) {
            throw new YyghException(ResultCodeEnum.HOSPITAL_OPEN);
        }
        SignInfoVo signInfoVo = new SignInfoVo();
        signInfoVo.setApiUrl(hospitalSet.getApiUrl());
        signInfoVo.setSignKey(hospitalSet.getSignKey());
        return signInfoVo;
    }

这里面的代码需要你仔细研读当发送过来的东西满足条件的时候,我们就可以进行一个返回。
样例2:
接下来,我们根据分页查询的语句

List<User> userList = userMapper.selectPage(  
        new Page<User>(1, 10),  
        new EntityWrapper<User>().eq("name", "张三")  
                .eq("sex", 0)  
                .between("age", "18", "50")  
); 

也可以根据Page来进行定义

//传递Page对象 之后可以动态的获取所有的分页数据
    IPage<Item> iPage = new Page<>(page, rows);
    QueryWrapper<Item> queryWrapper = new QueryWrapper<Item>();
    //降序排列
    queryWrapper.orderByDesc("updated");
    iPage = itemMapper.selectPage(iPage, queryWrapper);
    //1.获取记录总数
    int total = (int) iPage.getTotal();
    List<Item> itemList = iPage.getRecords();
    return new EasyUITable(total, itemList);
}

//将整合对象 ,交给spring容器管理
@Bean
public PaginationInterceptor  paginationInterceptor() {        
    return new PaginationInterceptor();
}
//3 条件查询带分页
    @PostMapping("findPageHospSet/{current}/{limit}")
    public Result findPageHospSet(@PathVariable long current,
                                  @PathVariable long limit,
                                  @RequestBody
(required = false) HospitalSetQueryVo hospitalSetQueryVo) {
        //创建page对象,传递当前页,每页记录数
        Page<HospitalSet> page = new Page<>(current,limit);
        //构建条件
        QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>();
        String hosname = hospitalSetQueryVo.getHosname();//医院名称
        String hoscode = hospitalSetQueryVo.getHoscode();//医院编号
        if(!StringUtils.isEmpty(hosname)) {
            wrapper.like("hosname",hospitalSetQueryVo.getHosname());
        }
        if(!StringUtils.isEmpty(hoscode)) {
            wrapper.eq("hoscode",hospitalSetQueryVo.getHoscode());
        }
        //调用方法实现分页查询
        Page<HospitalSet> pageHospitalSet = hospitalSetService.page(page, wrapper);
        //返回结果
        return Result.ok(pageHospitalSet);
    }


4.总结

总的来说,Mybatis-plus是mybatis的一个升华,我们在使用的过程中也应当谨慎使用,好啦,这一期的技术分享就到这里吧,明怀我肯定还有很多地方总结的不够好,还希望大家能够多多指正!

相关文章

暂无评论

暂无评论...