專案整合seata和mybatis-plus衝突問題解決方案:(分頁外掛失效, 自動填充失效, 自己注入的id生成器失效 找不到mapper檔案解決方案)

趕星而至發表於2021-12-15

專案整合seata和mybatis-plus,seata與mybatis-plus衝突問題(所有外掛失效,自動填充失效,找不到mapper檔案解決方案)

自動填充程式碼:

package com.from.mybatis.handler;
​
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
​
import java.util.Date;
​
@Component
public class MyBatisMetaObjectHandler implements MetaObjectHandler {
    /**
     * 自定義插入時填充規則
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        // 注意是類屬性欄位名稱,不是表欄位名稱
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("delFlag", 0, metaObject);
    }
​
    /**
     * 自定義更新時填充規則
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        String now = DateUtil.now();
        // 注意是類屬性欄位名稱,不是表欄位名稱
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
​
}
​

 

id生成器程式碼:

package com.from.mybatis.config;
​
import java.util.Date;
import java.util.UUID;
​
/**
 * compressed id generator, result id not great than 53bits before 2318-06-04.
 */
public class IdGenerator {
​
    private static IdGenerator instance = new IdGenerator(0);
​
    public static IdGenerator initDefaultInstance(int machineId) {
        instance = new IdGenerator(machineId);
        return instance;
    }
​
    public static IdGenerator getInstance() {
        return instance;
    }
​
    public static long generateId() {
        return instance.nextId();
    }
​
    // total bits=53(max 2^53-1:9007199254740992-1)
// private final static long TIME_BIT = 40; // max: 2318-06-04
    private final static long MACHINE_BIT = 5; // max 31
    private final static long SEQUENCE_BIT = 8; // 256/10ms
/**
     * mask/max value
     */
    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
​
    private final static long MACHINE_LEFT = SEQUENCE_BIT;
    private final static long TIMESTMP_LEFT = MACHINE_BIT + SEQUENCE_BIT;
​
    private long machineId;
    private long sequence = 0L;
    private long lastStmp = -1L;
​
    private IdGenerator(long machineId) {
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException(
                    "machineId can't be greater than " + MAX_MACHINE_NUM + " or less than 0");
        }
        this.machineId = machineId;
    }
​
    /**
     * generate new ID
     *
     * @return
     */
    public synchronized long nextId() {
        long currStmp = getTimestamp();
        if (currStmp < lastStmp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        }
​
        if (currStmp == lastStmp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0L) {
                currStmp = getNextTimestamp();
            }
        } else {
            sequence = 0L;
        }
​
        lastStmp = currStmp;
​
        return currStmp << TIMESTMP_LEFT //
                | machineId << MACHINE_LEFT //
                | sequence;
    }
​
    private long getNextTimestamp() {
        long mill = getTimestamp();
        while (mill <= lastStmp) {
            mill = getTimestamp();
        }
        return mill;
    }
​
    private long getTimestamp() {
        // per 10ms
        return System.currentTimeMillis() / 10;// 10ms
    }
​
    public static Date parseIdTimestamp(long id) {
        return new Date((id >>> TIMESTMP_LEFT) * 10);
    }
​
    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}
​

 

package com.from.mybatis.config;
​
​
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.springframework.stereotype.Component;
​
@Component
public class CustomerIdGenerator implements IdentifierGenerator {
    @Override
    public Long nextId(Object entity) {
        // 填充自己的Id生成器,
        return IdGenerator.generateId();
    }
}

 


具體代理配置:

package com.from.seata.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.from.mybatis.config.CustomerIdGenerator;
import com.from.mybatis.handler.MyBatisMetaObjectHandler;
import io.seata.rm.datasource.DataSourceProxy;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.io.IOException;
@Configuration
@EnableConfigurationProperties({MybatisPlusProperties.class})
public class DataSourcesProxyConfig {
    //自動填充注入
    @Bean
    public MyBatisMetaObjectHandler myBatisMetaObjectHandler() {
        return new MyBatisMetaObjectHandler();
    }
    //id生成器注入
    @Bean
    public CustomerIdGenerator customerIdGenerator() {
        return new CustomerIdGenerator();
    }
    //獲取資料來源
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }
​
    //配種資料來源
    @Primary//@Primary標識必須配置在程式碼資料來源上,否則本地事務失效
    @Bean
    public DataSourceProxy dataSourceProxy(DataSource druidDataSource) {
        return new DataSourceProxy(druidDataSource);
    }
​
    private MybatisPlusProperties properties;
​
    public DataSourcesProxyConfig(MybatisPlusProperties properties) {
        this.properties = properties;
    }
​
    //配置mybatisplus的資料來源,所有外掛會失效,所以注入進來,配置給代理資料來源
    @Bean
    public MybatisSqlSessionFactoryBean sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
        // 這裡必須用 MybatisSqlSessionFactoryBean 代替了 SqlSessionFactoryBean,否則 MyBatisPlus 不會生效
        MybatisSqlSessionFactoryBean sqlBean = new MybatisSqlSessionFactoryBean();
        sqlBean.setDataSource(dataSourceProxy);
        sqlBean.setTransactionFactory(new SpringManagedTransactionFactory());
        try {
            //注意:!!!!這個如果寫的有sql,須有該配置,try cach以下,開啟不捕獲異常的化,沒sql會報錯
            sqlBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                    .getResources("classpath:/mapper/**/*.xml"));
        } catch (IOException ignored) {
        }
        MybatisConfiguration configuration = this.properties.getConfiguration();
        if (configuration == null) {
            configuration = new MybatisConfiguration();
        }
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //向代理資料來源新增分頁攔截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        sqlBean.setPlugins(interceptor);
        //代理資料來源新增id生成器,欄位自動填充
        sqlBean.setGlobalConfig(new GlobalConfig()
                .setMetaObjectHandler(myBatisMetaObjectHandler())
                .setIdentifierGenerator(customerIdGenerator()));
        sqlBean.setConfiguration(configuration);
        return sqlBean;
    }
}

 

關於seata服務端和客戶端整合配置,可以看另一篇文章!

相關文章