mybatis-plus支持组合主键及Invalid bound statement (not found): xxxMapper.selectByMultiId解决方案

一.问题背景


        mybatis-plus提供了许多常用方法,能满足基本的增删改查需求,省去了xml、mapper、service的编写,也不用担心实体的映射,十分方便。
        但实际开发中很多时候会用到组合主键,mybatis-plus原本并不支持组合主键,手写sql和方法又觉得麻烦,可以通过三方jar包对mybatis-plus进行增强,以适用于组合主键的场景。


二.代码实现


1.引入依赖

        默认已经集成了mybatis-plus,引入jeffreyning支持组合主键

        <dependency>
            <groupId>com.github.jeffreyning</groupId>
            <artifactId>mybatisplus-plus</artifactId>
            <version>1.7.4-RELEASE</version>
        </dependency>


2.启动类

        启动类增加@EnableMPP注解

package com.bjtumem;

import com.github.jeffreyning.mybatisplus.conf.EnableMPP;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

/**
 * 启动程序
 * 
 * @author bjtumem
 */
@EnableMPP
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class BjtuMemApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(BjtuMemApplication.class, args);
    }
}


3.实体类

        用@MppMultiId注解修饰主键字段,在组合主键场景下@TableId就不适用了。

package com.bjtumem.system.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.bjtumem.common.utils.ValidatorGroup;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.jeffreyning.mybatisplus.anno.MppMultiId;
import lombok.Data;

import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;

/**
 * @author daixin
 * @version 1.0
 * @description: TODO
 * @date 2023/8/10 11:00
 */
@Data
@TableName("p_collect")
public class PCollect implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 布告id
     */
    @NotNull(groups = {ValidatorGroup.Insert.class}, message = "bulletinId is not null")
    @MppMultiId
    private Long bulletinId;

    /**
     * 用户id
     */
    @MppMultiId
    private Long userId;

    /**
     * 收藏时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(value = "create_time")
    private Date createTime;

}


4.Mapper

        继承MppBaseMapper

package com.bjtumem.system.mapper;

import com.bjtumem.system.domain.PCollect;
import com.github.jeffreyning.mybatisplus.base.MppBaseMapper;

/**
 * @author daixin
 * @version 1.0
 * @description: TODO
 * @date 2023/8/10 11:04
 */
public interface PCollectMapper extends MppBaseMapper<PCollect> {
}


5.Service

        继承IMppService

package com.bjtumem.system.service;

import com.bjtumem.system.domain.PCollect;
import com.github.jeffreyning.mybatisplus.service.IMppService;

/**
 * @author daixin
 * @version 1.0
 * @description: TODO
 * @date 2023/8/10 11:05
 */
public interface IPCollectService extends IMppService<PCollect> {
}


6.ServiceImpl

        继承MppServiceImpl

package com.bjtumem.system.service.impl;

import com.bjtumem.system.domain.PCollect;
import com.bjtumem.system.mapper.PCollectMapper;
import com.bjtumem.system.service.IPCollectService;
import com.github.jeffreyning.mybatisplus.service.MppServiceImpl;
import org.springframework.stereotype.Service;

/**
 * @author daixin
 * @version 1.0
 * @description: TODO
 * @date 2023/8/10 11:05
 */
@Service
public class PCollectServiceImpl extends MppServiceImpl<PCollectMapper, PCollect> implements IPCollectService {
}


7.Controller

        直接调用继承自IMppService的xxxByMultiId()方法,组合主键即可生效。

    /**
     * 收藏
     * @param pCollect
     * @return
     */
    @PostMapping(value = "/collect")
    public AjaxResult collect(@Validated({ValidatorGroup.Insert.class})PCollect pCollect)
    {
        pCollect.setUserId(getUserId());
        PCollect existPCollect = pCollectService.selectByMultiId(pCollect);
        if(existPCollect !=null){
            return AjaxResult.success();
        }
        pCollectService.save(pCollect);
        return AjaxResult.success();
    }

    /**
     * 取消收藏
     * @param pCollect
     * @return
     */
    @PostMapping(value = "/cancelCollect")
    public AjaxResult cancelCollect(@Validated({ValidatorGroup.Insert.class})PCollect pCollect)
    {
        pCollect.setUserId(getUserId());
        pCollectService.deleteByMultiId(pCollect);
        return AjaxResult.success();
    }

8.运行测试

        以下为控制台打出的sql,已经执行了组合主键。


三.问题与解决方案


1.Invalid bound statement (not found): xxxMapper.selectByMultiId

        本项目调试过程中报错Invalid bound statement (not found): xxxMapper.selectByMultiId的原因有如下两种情况。


(1)自定义SqlSessionFactory

        检查是否实现了自定义的SqlSessionFactory,如果实现了自定义的SqlSessionFactory则需要配置MppSqlInjector的注入,否则报错Invalid bound statement (not found): xxxMapper.selectByMultiId
        本项目基于若依框架开发,一般使用mybatis-plus都需要实现自定义SqlSessionFactory,检查MyBatisConfig配置,注入MppSqlInjector,问题解决。

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, MppSqlInjector mppSqlInjector, MybatisPlusProperties properties) throws Exception
    {
        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
        String mapperLocations = env.getProperty("mybatis.mapperLocations");
        String configLocation = env.getProperty("mybatis.configLocation");
        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
        VFS.addImplClass(SpringBootVFS.class);

        final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        GlobalConfig globalConfig = properties.getGlobalConfig();
        globalConfig.setSqlInjector(mppSqlInjector);
        sessionFactory.setGlobalConfig(globalConfig);
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
        return sessionFactory.getObject();
    }


(2)jar包冲突

        检查项目是否同时引入了不同版本的jar包,如下图,mybatis-plus相关jar都有两个版本,jar包冲突导致使用组合主键时报错Invalid bound statement (not found): xxxMapper.selectByMultiId
        由于jar包是由不同开发人员在不同时间引入,且单主键功能正常,所以这个问题不容易发现,检查pom文件,将不兼容版本的引用删掉或替换即可。

猜你喜欢

转载自blog.csdn.net/secretdaixin/article/details/132362220