项目集成seata和mybatis-plus冲突问题解决方案:(分页插件失效, 自动填充失效, 自己注入的id生成器失效 找不到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; } }