mysql模糊查询unicode编码的字段的解决方案——mybatis查数据库mysql时对unicode支持问题

1.mysql数据库里的nickname字段内容是经过unicode编码处理后存储的,

如:\u73\u74\u61\u72\u7a\u6d\ud83d\udc7f\u20\ud83d\ude04\u20\ud83d\ude03\u20\ud83d\ude13

实际明文:starzm? ? ? ?

每个字符都是以\u开头的,后面跟上2或4位的16进制表示的字符。

注意:有些转义识别工具,在遇到2位带字母(大小超过十进制10)的16进制字符,会出错,需要在16进制数字前补足两个0,达到4位16进制数,才能正常识别解码,如:

https://www.css-js.com/tools/unicode.html    和    http://tool.chinaz.com/tools/unicode.aspx

但是mysql中对unicode识别时没有此要求。

 

2.目标是使用模糊匹配按nickname模糊查找

(1)在使用mybatis查mysql数据库之前对nickname处理:

//加密成mysql数据库能识别的unicode码
	public static String encodeToMysqlUnicode(String string) {
		StringBuffer unicode = new StringBuffer();  
		
		for (int i = 0; i < string.length(); i++) {  
			
			// 取出每一个字符  
			char c = string.charAt(i);  
			// 转换为unicode
			unicode.append("\\u" + Integer.toHexString(c)); 
			  
		}  
		
		return unicode.toString();  
	}

(2)直接在navicat(连mysql的客户端)测试时发现,where条件中需要

nickname like concat('%',"\u73\\\\u74\\\\u61\\\\u72\\\\u7a\\\\u6d",'%')

才能正常查出数据。

其中\u73表示starzm中的字一个字符s,表示后续其他字符unicode编码则需要多层转义,带4个反斜杠。

此外,\u73也可使用双斜杠即\\u73,也即

nickname like concat('%',"\\u73\\\\u74\\\\u61\\\\u72\\\\u7a\\\\u6d",'%')

完整sql

select * from tab_user_fans where  
 nickname like concat('%',"starzm",'%') or nickname like concat('%',"\u73\\\\u74\\\\u61\\\\u72\\\\u7a\\\\u6d",'%') 
 order by REGIST_TIME desc limit 0,10

(此sql只支持navicat直接查mysql数据库,但不支持程序通过mybatis查数据库)

 

(3)但是在程序里使用此sql查不出数据,但是上一步在navicat同样的sql能查出数据,奇怪!

项目框架Struts+Spring+mybatis,sql写在xml配置文件里

猜测也应该是mybatis连mysql后使用此sql查的时候,有编码转义之类的,导致查不出来数据。

解决办法

把反斜杠\改成下划线_

改入库查出之前对nickname处理逻辑,把\\u改成_u即可

//加密成mysql数据库能识别的unicode码
	public static String encodeToMysqlUnicode(String string) {
		StringBuffer unicode = new StringBuffer();  
		
		for (int i = 0; i < string.length(); i++) {  
			
			// 取出每一个字符  
			char c = string.charAt(i);  
			// 转换为unicode
			unicode.append("_u" + Integer.toHexString(c)); 
			  
		}  
		
		return unicode.toString();  
	}

 

新的sql:

select * from tab_user_fans where
nickname like concat('%',"starzm",'%') or nickname like concat('%',"_u73_u74_u61_u72_u7a_u6d",'%') 
order by REGIST_TIME desc limit 0,10

此sql即支持navicat直接查mysql数据库,也支持程序通过mybatis查mysql数据库!

完美解决!

应该是mybatis底层编码支持问题,直接使用navicat查mysql数据库就没有上述unicode编码问题。

<think>嗯,用户的问题是关于在Spring Boot项目中,使用Druid和MyBatis连接Oracle多数据源编码格式不一致导致的问题,需要确保插入和查询都用UTF-8编码。首先,我需要回忆一下相关的配置步骤以及可能出问题的地方。 首先,用户提到的是多数据源配置,所以应该检每个数据源的URL是否正确设置了字符编码。根据引用中的例子,比如引用3里的MySQL配置,URL里加了useUnicode和characterEncoding参数。Oracle可能也有类似的参数需要设置。不过Oracle的JDBC驱动参数可能和MySQL不同,需要确认正确的参数名称。 然后,用户使用Druid作为连接池,所以每个数据源的配置应该在application.yml中分别指定,特别是URL部分。引用1和引用2提到多数据源的配置,其中引用1的例子中URL里有characterEncoding=utf8,但用户的问题可能出现在Oracle的配置中没有正确设置这些参数。 接下来,Oracle数据库本身的字符集也需要确认是否是AL32UTF8或者UTF8,否则即使应用层设置了,数据库存储可能还是会转换。这可能需要DBA的协助,但应用配置同样重要。 MyBatis的配置部分,可能需要检XML映射文件中是否有正确的参数设置,比如在插入指定jdbcType,或者在全局配置中设置useUnicode和characterEncoding。另外,MyBatis的SQL会话工厂是否关联了正确配置的数据源,确保每个数据源都正确应用了编码设置。 还有,连接池的配置,比如Druid,是否在连接初始化执行了修改编码的SQL语句,比如ALTER SESSION SET NLS_LANGUAGE=AMERICAN等,来确保会话级别的编码正确。引用1中的例子有类似的初始化SQL,用户可能需要为Oracle数据源添加这样的设置。 另外,检应用的全局字符编码过滤器,比如Spring的CharacterEncodingFilter,确保请求和响应的编码都是UTF-8。有候,虽然数据库和JDBC配置正确,但应用层没有正确处理字符编码,也会导致乱码。 还有可能的问题点包括:数据库表结构的字段是否使用NVARCHAR2等支持Unicode的类型,而不仅仅是VARCHAR2;JDBC驱动版本是否过旧,可能需要升级到支持更好编码处理的版本。 综合这些步骤,解决方案应该包括检并正确配置每个Oracle数据源的URL参数,设置Druid的初始化SQL,验证数据库和服务器的字符集,配置MyBatis和全局过滤器,以及确保字段类型正确。此外,测试插入和查询操作,使用日志或工具监控实际传输的编码是否正确,也是必要的验证步骤。</think>### 分步解决方案 #### 1. **配置Oracle数据源URL参数** 在Spring Boot的`application.yml`中为每个Oracle数据源添加`useUnicode`和`characterEncoding`参数,确保连接强制使用UTF-8编码: ```yaml datasource: oracle1: url: jdbc:oracle:thin:@//host:port/service_name?useUnicode=true&characterEncoding=UTF-8 username: "特殊账号" # 特殊符号需单引号包裹[^1] driver-class-name: oracle.jdbc.OracleDriver oracle2: url: jdbc:oracle:thin:@//host:port/service_name?useUnicode=true&characterEncoding=UTF-8 ``` > **注意**:Oracle官方驱动对`characterEncoding`的支持有限,需配合其他参数使用[^3]。 --- #### 2. **设置Druid连接池初始化SQL** 在Druid配置中添加初始化SQL命令,强制会话级编码: ```yaml druid: oracle1: connection-init-sqls: - "ALTER SESSION SET NLS_LANGUAGE=AMERICAN" - "ALTER SESSION SET NLS_TERRITORY=AMERICA" - "ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'" ``` 此配置可统一日期、语言等字符集相关参数。 --- #### 3. **验证数据库服务器字符集** 通过SQL检Oracle服务器字符集: ```sql SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET'); ``` 确保结果包含`AL32UTF8`或`UTF8`。若为`ZHS16GBK`等,需联系DBA修改数据库字符集。 --- #### 4. **配置MyBatis参数** 在MyBatis的XML映射文件中明确指定`jdbcType`: ```xml <insert id="insertData"> INSERT INTO table (content) VALUES (#{content,jdbcType=VARCHAR}) </insert> ``` 同,在`mybatis-config.xml`中全局配置: ```xml <settings> <setting name="jdbcTypeForNull" value="NULL"/> <setting name="defaultStatementTimeout" value="30"/> </settings> ``` --- #### 5. **应用层全局编码过滤器** 添加Spring的`CharacterEncodingFilter`: ```java @Bean public FilterRegistrationBean<CharacterEncodingFilter> encodingFilter() { FilterRegistrationBean<CharacterEncodingFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new CharacterEncodingFilter()); bean.addInitParameter("encoding", "UTF-8"); bean.addInitParameter("forceEncoding", "true"); bean.addUrlPatterns("/*"); return bean; } ``` --- #### 6. **字段类型与驱动验证** - 数据库字段类型应使用`NVARCHAR2`代替`VARCHAR2`以支持完整Unicode - 升级Oracle JDBC驱动至最新版本(如ojdbc8.jar) --- #### 验证步骤 1. 插入包含中文和特殊符号的测试数据 2. 直接查询数据库确认存储结果 3. 通过MyBatis查询后检返回结果 4. 使用`Wireshark`或`JDBC日志`监控实际传输编码 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值