若依框架集成mybatis换成mybatis-plus记录

6,880 阅读3分钟

文章用于记录自己更改若依框架集成mybatis换成mybatis-plus的一些些问题,最重要的是怎么在最小的代价下不影响原有代码的情况下,进行自己的开发,同时方便后续的更改。

1. mybatis与mybatis-plus能否共存

mybatis是SqlSessionFactoryBean,而mybatis-plus是MybatisSqlSessionFactoryBean,所以一般最好是项目中使用一个最好,当然想要共存也可以,mybatis-plus的版本最好要高。

2.修改yml,当使用mybatis或者mybatis-plus时,配置文件只需要出现一个就行。

这是原本的配置直接注解掉 因为yml中的Configuration和mybatis-config文件的configruation配置是不能共存的。否则会报以下错误

Property 'configuration' and 'configLocation' can not specified with together

# # MyBatis配置
# mybatis:
# # 搜索指定包别名
    # typeAliasesPackage: org.bf.**.domain
# # 配置mapper的扫描,找到所有的mapper.xml映射文件
    # mapperLocations: classpath*:mapper/**/*Mapper.xml
# # 加载全局的配置文件
    # configLocation: classpath:mybatis/mybatis-config.xml

这是需要新增的

mybatis-plus:
# 配置要扫描的xml文件目录,classpath* 代表所有模块的resources目录 classpath 不加星号代表当前模块下的resources目录
    mapper-locations: classpath*:mapper/**/*Mapper.xml
# 实体扫描,*通配符
    typeAliasesPackage: org.bf.**.domain

3.导入mybatis-plus的包

在父pom.xml中新增mybatis-plus的jar包,当然你也可以去maven仓库选择对应版本,同时也有lombok的jar包

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

然后在common模块下的pom.xml引入

<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

因为我不想影响原有代码运行,所以我是新增了一个模块,在新增的模块需要引入common模块

4.代码注释

原因:诺依中ruoyi-framework模块有对mybatis的配置类,而mybatis的sql工厂和mybatis-plus的sql工厂不同,否则会报以下错:(所以需要将这个配置类的相关代码注释即可)

mybatis-plus  Invalid bound statement (not found): com.ruoyi.file.mapper.UserfileMapper.selectCount

673249b4f1200c41e3d82f5108eebc5c.jpeg

673249b4f1200c41e3d82f5108eebc5e.jpeg

当然到这里是集成了,但怎么用呢?

5.首先先改一波自动生成代码

1677207529560.jpg

也就是如图所示的.vm代码模板,当然为了不改的面目全非,我备份了一份原有的文件出来即myVm这个文件夹,这个文件夹没有做任何更改,同时修改这个模块的VelocityUtils类中的getTemplateList方法,即获取模板方法,

1677207807789.jpg

原本长这样

1677207925746.jpg

你加个判断让他读你自己的,判断条件,从yml拿,或者直接写true都行

1677207950486.jpg

Controller.java.vm,上面导包有些是我自己的路径记得修改,例如org.bf.common.annotation.Log;等等

package ${packageName}.controller;

import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.bf.common.annotation.Log;
import org.bf.common.core.controller.BaseController;
import org.bf.common.core.domain.AjaxResult;
import org.bf.common.enums.BusinessType;
import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service;
import org.bf.common.utils.poi.ExcelUtil;
#if($table.crud || $table.sub)
import org.bf.common.core.page.TableDataInfo;
#elseif($table.tree)
#end

/**
 * ${functionName}Controller
 * 
 * @author ${author}
 */
@RestController
@RequestMapping("/${moduleName}/${businessName}")
public class ${ClassName}Controller extends BaseController
{
    @Autowired
    private I${ClassName}Service ${className}Service;

    /**
     * 查询${functionName}列表
     */
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
    @GetMapping("/list")
#if($table.crud || $table.sub)
    public TableDataInfo list(${ClassName} ${className})
    {
        startPage();
        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
        return getDataTable(list);
    }
#elseif($table.tree)
    public AjaxResult list(${ClassName} ${className})
    {
        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
        return success(list);
    }
#end

    /**
     * 导出${functionName}列表
     */
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
    @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ${ClassName} ${className})
    {
        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
        ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
        util.exportExcel(response, list, "${functionName}数据");
    }

    /**
     * 获取${functionName}详细信息
     */
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
    @GetMapping(value = "/{${pkColumn.javaField}}")
    public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
    {
        return success(${className}Service.getById(${pkColumn.javaField}));
    }

    /**
     * 新增${functionName}
     */
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ${ClassName} ${className})
    {
        return toAjax(${className}Service.saveOrUpdate(${className}));
    }

    /**
     * 修改${functionName}
     */
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ${ClassName} ${className})
    {
        return toAjax(${className}Service.saveOrUpdate(${className}));
    }

    /**
     * 删除${functionName}
     */
    @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
   @DeleteMapping("/{${pkColumn.javaField}s}")
    public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
    {
        return toAjax(${className}Service.removeByIds(Arrays.asList(${pkColumn.javaField}s)));
    }
}

domain.java.vm,额外加lombok.Data、com.baomidou.mybatisplus.annotation.TableName、org.bf.common.core.domain.MyBaseEntity这三个包

package ${packageName}.domain;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableName;
import org.bf.common.core.domain.MyBaseEntity;
#foreach ($import in $importList)
import ${import};
#end
import org.bf.common.annotation.Excel;
#if($table.crud || $table.sub)
#elseif($table.tree)
#end

/**
 * ${functionName}对象 ${tableName}
 * 
 * @author ${author}
 */
#if($table.crud || $table.sub)
#set($Entity="MyBaseEntity")
#elseif($table.tree)
#set($Entity="TreeEntity")
#end
@Data
@TableName("${tableName}")
public class ${ClassName} extends ${Entity}
{
    private static final long serialVersionUID = 1L;
#foreach ($column in $columns)
#if(!$table.isSuperColumn($column.javaField))
    /** $column.columnComment */
#if($column.list)
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)

    #set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($parentheseIndex != -1)
    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
#elseif($column.javaType == 'Date')
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
#else
    @Excel(name = "${comment}")
#end
#end
    private $column.javaType $column.javaField;
#end
#end

#if($table.sub)
    /** $table.subTable.functionName信息 */
    private List<${subClassName}> ${subclassName}List;

#end

}

MyBaseEntity是我自定义的基类,因为原有基类,不是很满足需求,同时全项目都继承了,不便更改

在/common/core/domain/目录下新增MyBaseEntity.java 当然的当然,这些字段在你构建的表中一定要有,除了@TableField(exist = false)注解的params请求参数

1677208750871.jpg

/**
 * Entity基类
 * 
 * @author
 */
@Data
public class MyBaseEntity implements Serializable
{
    private static final long serialVersionUID = 1L;

    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;

    /** 逻辑删除 */
    @TableLogic //逻辑删除
    @TableField(fill = FieldFill.INSERT)
    private int deleted;

    /** 创建者 */
    @TableField(fill = FieldFill.INSERT)
    private String createBy;

    /** 创建时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    /** 更新者 */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateBy;

    /** 更新时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    /** 备注 */
    private String remark;

    /** 请求参数 */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @TableField(exist = false)
    private Map<String, Object> params;


    public Map<String, Object> getParams()
    {
        if (params == null)
        {
            params = new HashMap<>();
        }
        return params;
    }

}

mapper.java.vm

package ${packageName}.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import ${packageName}.domain.${ClassName};
#if($table.sub)
import ${packageName}.domain.${subClassName};
#end

/**
 * ${functionName}Mapper接口
 * 
 * @author ${author}
 */
@Mapper
public interface ${ClassName}Mapper extends BaseMapper<${ClassName}>
{

}

service.java.vm,这里保留了原有的select${ClassName}List接口,为了方便你自己添加查询条件

package ${packageName}.service;

import java.util.List;
import ${packageName}.domain.${ClassName};
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * ${functionName}Service接口
 * 
 * @author ${author}
 */
public interface I${ClassName}Service extends IService<${ClassName}>
{
    /**
     * 查询${functionName}列表
     *
     * @param ${className} ${functionName}
     * @return ${functionName}集合
     */
    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
}

serviceImpl.java.vm,在实现类使用了构造器去查询

package ${packageName}.service.impl;

import java.util.List;
#foreach ($column in $columns)
#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
import org.bf.common.utils.DateUtils;
#break
#end
#end
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#if($table.sub)
import java.util.ArrayList;
import org.bf.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import ${packageName}.domain.${subClassName};
#end
import ${packageName}.mapper.${ClassName}Mapper;
import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
 * ${functionName}Service业务层处理
 * 
 * @author ${author}
 */
@Service
public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper,${ClassName}> implements I${ClassName}Service
{

    /**
     * 查询${functionName}列表
     *
     * @param ${className} ${functionName}
     * @return ${functionName}
     */
    @Override
    public List<${ClassName}> select${ClassName}List(${ClassName} ${className})
    {
        QueryWrapper<${ClassName}> queryWrapper = new QueryWrapper<>();
        return baseMapper.selectList(queryWrapper);
    }

}

当然修改完成你可以去自带的自动生成生成对应的代码了,但是还需要一点点配置,在之前MyBaseEntity基类中配置了 @TableField(fill = FieldFill.INSERT)逻辑删除、@TableField(fill = FieldFill.INSERT)更新插入、 @TableField(fill = FieldFill.INSERT_UPDATE)更新修改插入都需要对应配置

6.配置MetaObjectHandler

如图在/org/bf/framework/下新建了myBatisPlus文件夹和MyMetaObjectHandler.java类

1677209597559.jpg

package org.bf.framework.myBatisPlus;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.bf.common.utils.SecurityUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * bf
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    public static final String CREATE_BY = "createBy";
    public static final String CREATE_TIME = "createTime";
    public static final String UPDATE_BY = "updateBy";
    public static final String UPDATE_TIME = "updateTime";
    public static final String DELETED = "deleted";

    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
//        log.info("start intsert fill ....");
        //strictInsertFill(MetaObject metaObject, String fieldName, Class<T> fieldType, E fieldVal)
        // 起始版本 3.3.0(推荐使用)
        this.setFieldValByName(CREATE_BY, SecurityUtils.getUsername(),metaObject);
        this.setFieldValByName(CREATE_TIME,formatDate(metaObject.getSetterType(CREATE_TIME)),metaObject);
        this.setFieldValByName(UPDATE_BY, SecurityUtils.getUsername(),metaObject);
        this.setFieldValByName(UPDATE_TIME,formatDate(metaObject.getSetterType(CREATE_TIME)),metaObject);
        this.setFieldValByName(DELETED, 0,metaObject);
    }

    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
//        log.info("start update fill ....");
        this.setFieldValByName(UPDATE_BY, SecurityUtils.getUsername(),metaObject);
        this.setFieldValByName(UPDATE_TIME,formatDate(metaObject.getSetterType(CREATE_TIME)),metaObject);
    }


    /**
     * 处理特殊日期
     * @param setterType 参数类型
     * @return 日期类型
     */
    private Object formatDate(Class<?> setterType){
        if (Date.class.equals(setterType)){
            return new Date();
        } else if (LocalDateTime.class.equals(setterType)) {
            return LocalDateTime.now();
        } else if (Long.class.equals(setterType)) {
            return System.currentTimeMillis();
        }
        return null;
    }

}

到这算是完成基本配置可以完成crud,并且不大量修改原有代码,原有代码也是依然正常。(当然,也可能有遗漏,出现问题可以参考以下文档)

最后非常感谢以下作者提供的文档,给了我很大帮助!!!

诺依集成mybatis换成mybatis-plus(完美解决)

 MyBatis-Plus中文网

Mybatis plus配置MetaObjectHandler

若依3.6.0使用Mybatis-plus分页失效以及完美替换Pagehelper

MyBatis: No MyBatis mapper was found in '[xx.mapper]' package. Please check your configuration.