千家信息网

怎么使用shardingsphere对SQLServer坑进行解决

发表于:2024-10-02 作者:千家信息网编辑
千家信息网最后更新 2024年10月02日,这篇"怎么使用shardingsphere对SQLServer坑进行解决"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能
千家信息网最后更新 2024年10月02日怎么使用shardingsphere对SQLServer坑进行解决

这篇"怎么使用shardingsphere对SQLServer坑进行解决"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"怎么使用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 JdbcType 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)
at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:87)
... 47 common frames omitted
Caused 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.setNonNullParameter(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);    }  }

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

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

@Configurationpublic 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也可以哦

以上就是关于"怎么使用shardingsphere对SQLServer坑进行解决"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。

0