信创国产化替换如何推动企业自主创新与市场竞争力提升
1220
2022-10-14
使用shardingsphere对SQLServer坑的解决
背景:最近一个使用SQLServer的项目,业务量太大,开始对业务有影响了,因此用户要求升级改造,技术上采用shardingsphere进行分库分表。
经过一系列调研,设计。。。哐哐一顿操作之后开始动刀改造。pom依赖如下:
改造后查询和写入都各种报错:
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~