使用shardingsphere对SQLServer坑的解决

网友投稿 374 2022-08-17


使用shardingsphere对SQLServer坑的解决

背景:最近一个使用SQLServer的项目,业务量太大,开始对业务有影响了,因此用户要求升级改造,技术上采用shardingsphere进行分库分表。

经过一系列调研,设计。。。哐哐一顿操作之后开始动刀改造。pom依赖如下:

org.apache.shardingsphere

sharding-jdbc-spring-boot-starter

4.0.1

com.alibaba

druid-spring-boot-starter

1.2.8

改造后查询和写入都各种报错:

Caused by: org.apache.ibatis.type.TypeException: Error setting non null for parameter #2 with JdbcTyhttp://pe NVARCHAR . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.sql.SQLFeatureNotSupportedException: setNString    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:75)   &nbPQFJiplsp;at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87)    ... 47 common frames omittedCaused by: java.sql.SQLFeatureNotSupportedException: setNString    at org.apache.shardingsphere.shardingjdbc.jdbc.unsupported.AbstractUnsupportedOperationPreparedStatement.setNString(AbstractUnsupportedOperationPreparedStatement.java:57)    at org.apache.ibatis.type.NStringTypeHandler.setNonNullParameter(NStringTypeHandler.java:31)    at org.apache.ibatis.type.NStringTypeHandler.setNonNullParamethttp://er(NStringTypeHandler.java:26)    at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:73)    ... 48 common frames omitted

核心错误:Caused by: java.sql.SQLFeatureNotSupportedException: setNString

问题分析:

网上寻了千百度,蓦然回首,还是没有找到问题,(┭┮﹏┭┮)  最后debug断点跟了源码发现:

操作数据库的PreparedStatement 是ShardingPreparedStatement

然后setNString支持SQLServerPreparedStatement 不支持ShardingPreparedStatement(改造前没问题,改造后出问题的原因)

问题解决:

找到问题了,下面就是解决问题了,既然没有setNString的实现,那就实现一个呗;

第一步 实现NVarcharTypeHandler:

package cn.preserve.config.mybatis;

import org.apache.ibatis.type.BaseTypeHandler;

import org.apache.ibatis.type.JdbcType;

import org.apache.ibatis.type.MappedJdbcTypes;

import org.apache.ibatis.type.TypeException;

import java.sql.CallableStatement;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

/**

* 将 nvarchar 转成 varchar sharingJDBC不支持nvarchar

* 主要是NStringTypeHandler中,没有setNString()

*/

@MappedJdbcTypes(JdbcType.NVARCHAR)

public class NVarcharTypeHandler extends BaseTypeHandler {

@Override

public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {

if(parameter == null) {

if(jdbcType == null) {

throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");

}

try {

ps.setNull(i, jdbcType.TYPE_CODE);

} catch (SQLException var7) {

throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " + "Cause: " + var7, var7);

}

} else {

try {

this.setNonNullParameter(ps, i, parameter, jdbcType);

} catch (Exception var6) {

throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different configuration property. " + "Cause: " + var6, var6);

}

}

}

/**

* 这里使用setNString而不是setString

* @param ps

* @param i

* @param parameter

* @param jdbcType

* @throws SQLException

*/

@Override

public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {

ps.setString(i, parameter);

}

@Override

public String getNullableResult(ResultSet rs, String columnName) throws SQLException {

return rs.getString(columnName);

}

@Override

public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

return rs.getString(columnIndex);

}

@Override

public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

return cs.getString(columnIndex);

}

}

第二步 实现加入数据库配置:

由于我是代理实现的数据库,所有在代码中加入即可

@Configuration

public class DataSourceConfig {

@Bean(name = "sqlSessionFactory")

@Primary

public SqlSessionFactory memberDb1SqlSessionFactory(DataSource dataSource)

throws Exception {

SqlSessionFactoryBean bean = getSqlSessionFactoryBean(dataSource);

bean.setTypeHandlers(new TypeHandler[] {new NVarcharTypeHandler()});

return bean.getObject();

}

// ******* 其他实现

}

PS:如果是配置只修要在mybatis-config.xml中配置一下

配置完成后,测试以前功能全部正常(#^.^#)

如果嫌麻烦,有另外一种解决方案:将mapper.xml中的NVARCHAR替换从VARCHAR也可以哦


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:深入了解SparkSQL的运用及方法
下一篇:java高级用法之JNA中使用类型映射
相关文章

 发表评论

暂时没有评论,来抢沙发吧~