使用shardingsphere對(duì)SQLServer坑的解決
背景:最近一個(gè)使用SQLServer的項(xiàng)目,業(yè)務(wù)量太大,開始對(duì)業(yè)務(wù)有影響了,因此用戶要求升級(jí)改造,技術(shù)上采用shardingsphere進(jìn)行分庫(kù)分表。
經(jīng)過(guò)一系列調(diào)研,設(shè)計(jì)。。。哐哐一頓操作之后開始動(dòng)刀改造。pom依賴如下:
<!--sharding-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>改造后查詢和寫入都各種報(bào)錯(cuò):
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
核心錯(cuò)誤:Caused by: java.sql.SQLFeatureNotSupportedException: setNString
問(wèn)題分析:
網(wǎng)上尋了千百度,驀然回首,還是沒(méi)有找到問(wèn)題,(┭┮﹏┭┮) 最后debug斷點(diǎn)跟了源碼發(fā)現(xiàn):
操作數(shù)據(jù)庫(kù)的PreparedStatement 是ShardingPreparedStatement

然后setNString支持SQLServerPreparedStatement 不支持ShardingPreparedStatement(改造前沒(méi)問(wèn)題,改造后出問(wèn)題的原因)

問(wèn)題解決:
找到問(wèn)題了,下面就是解決問(wèn)題了,既然沒(méi)有setNString的實(shí)現(xiàn),那就實(shí)現(xiàn)一個(gè)唄;
第一步 實(shí)現(xiàn)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 轉(zhuǎn)成 varchar sharingJDBC不支持nvarchar
* 主要是NStringTypeHandler中,沒(méi)有setNString()
*/
@MappedJdbcTypes(JdbcType.NVARCHAR)
public class NVarcharTypeHandler extends BaseTypeHandler<String> {
@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);
}
}第二步 實(shí)現(xiàn)加入數(shù)據(jù)庫(kù)配置:
由于我是代理實(shí)現(xiàn)的數(shù)據(jù)庫(kù),所有在代碼中加入即可
@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();
}
// ******* 其他實(shí)現(xiàn)
}PS:如果是配置只修要在mybatis-config.xml中配置一下
<typeHandlers> <typeHandler handler="cn.preserve.config.mybatis.NVarcharTypeHandler"/> </typeHandlers>
配置完成后,測(cè)試以前功能全部正常(#^.^#)
如果嫌麻煩,有另外一種解決方案:將mapper.xml中的NVARCHAR替換從VARCHAR也可以哦
到此這篇關(guān)于使用shardingsphere對(duì)SQLServer坑的解決的文章就介紹到這了,更多相關(guān)shardingsphere SQLServer內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring事件監(jiān)聽機(jī)制之@EventListener實(shí)現(xiàn)方式詳解
這篇文章主要介紹了Spring事件監(jiān)聽機(jī)制之@EventListener實(shí)現(xiàn)方式詳解,ApplicationContext的refresh方法還是初始化了SimpleApplicationEventMulticaster,發(fā)送事件式還是先獲取ResolvableType類型,再獲取發(fā)送監(jiān)聽列表,需要的朋友可以參考下2023-12-12
Java使用continue語(yǔ)句的實(shí)例詳解
這篇文章主要介紹了Java使用continue語(yǔ)句的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家掌握使用方法,需要的朋友可以參考下2017-10-10
IDEA錯(cuò)誤:找不到或無(wú)法加載主類的完美解決方法
使用IDEA開始就一直在搭建java環(huán)境,許久沒(méi)有使用過(guò)java,剛開始有些生疏,先建了一個(gè)最簡(jiǎn)單的類可是運(yùn)行的時(shí)候出現(xiàn)錯(cuò)誤:找不到或無(wú)法加載主類,下面這篇文章主要給大家介紹了關(guān)于IDEA錯(cuò)誤:找不到或無(wú)法加載主類的完美解決方法,需要的朋友可以參考下2022-07-07
springboot使用Logback把日志輸出到控制臺(tái)或輸出到文件
這篇文章給大家介紹springboot項(xiàng)目使用日志工具Logback把日志不僅輸出到控制臺(tái),也可以輸出到文件的操作方法,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-10-10
java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):順序隊(duì)列和循環(huán)隊(duì)列
下面小編就為大家分享一篇java隊(duì)列實(shí)現(xiàn)方法(順序隊(duì)列,循環(huán)隊(duì)列),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-08-08

