在分表后mybatis-plus删除操作失效等问题处理
mybatis-plus
旧系统重构遇到的种种问题
在这三篇文章中,我花了近1个月时间重构了28个微服务,当中遇到的一些问题,但是发布到pretest环境,却还有启动问题,看来系统重构不是那么简单。
8 批量操作有问题
本地是没有这个问题,部署到生产在批量插入的时候却报错,原因视为&allowMultiQueries=true
,这个要加上
完成如下
?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
check_value: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update acc_assisting_accounting
SET name = '行政部',
' at line 6(str)
assert_method: regex_match
7 提示缺少字段,但数据库添加后,重启服务仍然没有效果
出现这个问题是因为分库后,两个库都需要加上这个字段,只有一个库加了,另外一个库没有加,也是有问题的。
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'accAccountSet.tax_declare_account' in 'field list'
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Unknown column 'accAccountSet.tax_declare_account' in 'field list'
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:239)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:91)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)
at com.sun.proxy.$Proxy161.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForMany(MybatisMapperMethod.java:166)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:77)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
at com.sun.proxy.$Proxy199.selectByAccountUserExample(Unknown Source)
6 SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
解决方案如下,问题出现原因是log相关jar冲突
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
exclusion>
<exclusion>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
exclusion>
exclusions>
dependency>
5 No servers available for service: einv-user-server
网关为什么没有找到对应得服务呢?其他得服务都是好的,当前得这个服务有什么特别得地方呢?
出现下面得原因有很多种,有的是jar冲突,有的是如我遇到得情况
因为我拿到代码不是自己写的,所以不清楚情况,
2023-08-09 09:24:11.178 WARN 18516 --- [oundedElastic-5] o.s.c.l.core.RoundRobinLoadBalancer : No servers available for service: einv-user-server
当register-enabled
设置为false
,服务没有被发现,因此才出现上面得问题,设置为true
就没有问题了。
spring:
application:
name: einv-user-server
cloud:
nacos:
config:
server-addr: ${nacos.server-addr}
file-extension: yml
namespace: ${nacos.namespace}
discovery:
server-addr: ${nacos.server-addr}
namespace: ${nacos.namespace}
register-enabled: true
weight: 10000
4 Class path contains multiple SLF4J bindings.
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/repository/ch/qos/logback/logback-classic/1.2.11/logback-classic-1.2.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.17.2/log4j-slf4j-impl-2.17.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
3 java.lang.IllegalArgumentException: Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required
在重构的过程中,有两个服务器起不了,提示下面的错误,配置什么基本是一致的,为什么这两个应用会出错呢?
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-08-06 10:00:19 ERROR org.springframework.boot.SpringApplication Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accAccountSetController': Unsatisfied dependency expressed through field 'accSaesAccountSetExtService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accSaesAccountSetExtServiceImpl': Unsatisfied dependency expressed through field 'extAccSaesAccountSetMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'extAccSaesAccountSetMapper' defined in file [D:\appworks\javawork\tywork\sae\saes\acc-saes-data\target\classes\com\whty\acc\saes\dao\ExtAccSaesAccountSetMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
调试一下,看看正常的是怎么运行的
下图就可以看到可以读取到sqlsessionfactory属性
但是错误的是没有sqlsessionfactory和sqlsessiontemplate这两项
可以看到下面的缺少了
<groupId>com.baomidougroupId>
<artifactId>dynamic-datasource-spring-boot-starterartifactId>
<version>3.3.6version>
在datasource下面添加sqlSessionFactory
,
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.whty.acc.setting.config.DynamicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class,
SpringBootConfiguration.class})
public class DataSourceConfig {
/**
* 动态数据源配置项
*/
@Resource
private DynamicDataSourceProperties properties;
/**
* shardingjdbc有四种数据源,需要根据业务注入不同的数据源
* 1. 未使用分片, 脱敏的名称(默认): shardingDataSource;
*
2. 主从数据源: masterSlaveDataSource;
*
3. 脱敏数据源:encryptDataSource;
*
4. 影子数据源:shadowDataSource
*/
// @Lazy
// @Resource(name = "shardingDataSource")
// private AbstractDataSourceAdapter shardingDataSource;
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
return new AbstractDataSourceProvider() {
@Override
public Map<String, DataSource> loadDataSources() {
Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
return dataSourceMap;
}
};
}
/**
* 将动态数据源设置为首选的
* 当spring存在多个数据源时, 自动注入的是首选的对象
* 设置为主要的数据源之后,就可以支持shardingjdbc原生的配置方式了
*/
@Primary
@Bean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception
{
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dynamicDataSource);
return sessionFactoryBean.getObject();
}
}
解决这个问题是因为项目中复用了组件,而组件里面增加datasource的配置
解决的办法是搞一个配置开关即可
提示新的错误
Parameter 0 of method sqlSessionFactory in com.whty.acc.saes.server.config.DataSourceConfig required a bean named 'hikariDataSourceForAcc' that could not be found.
下面这个问题,是因为当前工程不需要分表,
于是将sharding-jdbc-spring-boot-starter
排除在外即可
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shardingDataSource' defined in class path resource [org/apache/shardingsphere/shardingjdbc/spring/boot/SpringBootConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'shardingDataSource' threw exception; nested exception is java.lang.IllegalArgumentException: Data sources cannot be empty.
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
2 java.nio.charset.MalformedInputException: Input length = 1
原因为下图,解决方案有两个
一、启动命令采用java -jar -Dfile.encoding=utf-8 acc-transfer-server.jar
二、就是将下图中project encoding改成utf-8
cloud-context-3.1.6.jar!/:3.1.6]
at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:604) [spring-boot-2.7.9.jar!/:2.7.9]
at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:373) [spring-boot-2.7.9.jar!/:2.7.9]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:306) [spring-boot-2.7.9.jar!/:2.7.9]
at com.whty.acc.transfer.server.TransferServerApplication.main(TransferServerApplication.java:23) [classes!/:2.0.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_211]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_211]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_211]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_211]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [acc-transfer-server.jar:2.0.0]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) [acc-transfer-server.jar:2.0.0]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [acc-transfer-server.jar:2.0.0]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) [acc-transfer-server.jar:2.0.0]
Caused by: java.nio.charset.MalformedInputException: Input length = 1
at java.nio.charset.CoderResult.throwException(Unknown Source) ~[na:1.8.0_211]
at sun.nio.cs.StreamDecoder.implRead(Unknown Source) ~[na:1.8.0_211]
at sun.nio.cs.StreamDecoder.read(Unknown Source) ~[na:1.8.0_211]
at java.io.InputStreamReader.read(Unknown Source) ~[na:1.8.0_211]
at org.yaml.snakeyaml.reader.UnicodeReader.read(UnicodeReader.java:125) ~[snakeyaml-1.30.jar!/:na]
at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:183) ~[snakeyaml-1.30.jar!/:na]
... 38 common frames omitted
1 org.springframework.beans.factory.UnsatisfiedDependencyException
在windows还原同样的环境,也是这样的错误
就其原因是因为
翻看历史记录,mybatis没有这个配置,因为mybatis通过方式来实现。