mybatis-plus supports combined primary key and Invalid bound statement (not found): xxxMapper.selectByMultiId solution

1. Problem background


        mybatis-plus provides many common methods, which can meet the basic needs of addition, deletion, modification and query, eliminating the need to write xml, mapper and service, and there is no need to worry about entity mapping, which is very convenient.
        However, combined primary keys are often used in actual development. Mybatis-plus does not originally support combined primary keys, and handwriting SQL and methods is troublesome. Mybatis-plus can be enhanced through third-party jar packages to be suitable for combined primary key scenarios.


2. Code implementation


1.Introduce dependencies

        Mybatis-plus has been integrated by default, and jeffreyning has been introduced to support combined primary keys.

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


2. Startup class

        Add @EnableMPP annotation to startup class

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. Entity class

        Use the @MppMultiId annotation to modify the primary key field. In the combined primary key scenario, @TableId is not applicable.

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

        Inherit from 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

        Inherit 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

        Inherit from 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

        Directly call the xxxByMultiId() method inherited from IMppService, and the combined primary key will take effect.

    /**
     * 收藏
     * @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. Run the test

        The following is the sql typed on the console, and the combined primary key has been executed.


3. Problems and Solutions


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

        During the debugging process of this project, the error Invalid bound statement (not found): xxxMapper.selectByMultiId occurs due to the following two situations.


(1) Customize SqlSessionFactory

        Check whether the custom SqlSessionFactory is implemented. If the custom SqlSessionFactory is implemented, you need to configure the injection of MppSqlInjector, otherwise an error Invalid bound statement (not found): xxxMapper.selectByMultiId will be reported .
        This project is developed based on the Ruoyi framework. Generally, when using mybatis-plus, you need to implement a custom SqlSessionFactory, check the MyBatisConfig configuration, and inject MppSqlInjector to solve the problem.

    @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 package conflict

Check whether different versions of jar packages have been introduced into the project at the same time. As shown in the figure below, there are two versions of mybatis-plus related jars. The jar package conflict causes an error of Invalid bound statement (not found): xxxMapper.selectByMultiId         when using the combined primary key .
        Since the jar package was introduced by different developers at different times, and the single primary key function is normal, this problem is not easy to find. Just check the pom file and delete or replace the reference to the incompatible version.

Guess you like

Origin blog.csdn.net/secretdaixin/article/details/132362220