当前位置: 首页 > wzjs >正文

营口网站制作扬州seo优化

营口网站制作,扬州seo优化,公司名字大全3个字,不正规网站制作mysql8.0.17以下驱动导致blob映射String乱码问题分析与解决 一、问题复现二、问题深究三、解决方法方法1方法2 一、问题复现 1、docker安装mysql8.0,并创建测试数据库及测试数据表 CREATE DATABASE test DEFAULT CHARACTER SET utf8mb4; use test; CREATE TABLE t…

mysql8.0.17以下驱动导致blob映射String乱码问题分析与解决

  • 一、问题复现
  • 二、问题深究
  • 三、解决方法
    • 方法1
    • 方法2

一、问题复现

1、docker安装mysql8.0,并创建测试数据库及测试数据表

CREATE DATABASE `test` DEFAULT CHARACTER SET utf8mb4;
use test;
CREATE TABLE `test_content` (`id` int NOT NULL,`content` varchar(255) DEFAULT NULL,`b_content` blob,`lb_content` longblob,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2、使用mysql8.0.16驱动、mybatis、spring-boot搭建测试项目

2.1 实体类

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class TestContent {private int id;private String content;private String bContent;private String lbContent;
}

2.2 mapper

@Mapper
public interface TestContentMapper {@Select("select * from test_content where id = #{id}")TestContent selectOne(@Param("id") int id);@Select("select * from test_content where id = #{id}")Map<String, Object> selectOneMap(@Param("id") int id);@Update("update test_content set content=#{p.content}, b_content=#{p.bContent}, lb_content=#{p.lbContent} where id=#{p.id}")int update(@Param("p") TestContent p);@Insert("insert into test_content(id, content, b_content, lb_content) values (#{p.id}, #{p.content}, #{p.bContent}, #{p.lbContent})")int insert(@Param("p") TestContent p);}

2.3 配置文件

spring:datasource:type: com.zaxxer.hikari.HikariDataSourceurl: jdbc:mysql:///test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTCusername: rootpassword: YOUR_PASSWORDdriver-class-name: com.mysql.cj.jdbc.Driver
mybatis:configuration:map-underscore-to-camel-case: true

2.4 单元测试类

@SpringBootTest(classes = Application.class)
public class TestBlobConvert {@Resourceprivate TestContentMapper testContentMapper;@Testpublic void testBlobConvert() {int insert = testContentMapper.insert(TestContent.builder().id(1).content("红红火火恍恍惚惚aaa").bContent("红红火火恍恍惚惚aaa").lbContent("红红火火恍恍惚惚aaa").build());System.out.println("insert = " + insert);Map<String, Object> map = testContentMapper.selectOneMap(1);map.forEach((key, value) -> System.out.println("key = " + key+ ", value = " + value));TestContent testContent = testContentMapper.selectOne(1);System.out.println("testContent = " + testContent);testContent.setContent(testContent.getContent() + "q");int update = testContentMapper.update(testContent);System.out.println("update = " + update);TestContent testContent1 = testContentMapper.selectOne(1);System.out.println("testContent1 = " + testContent1);}
}

执行单元测试发现复现成功;控制台打印结果为:

insert = 1
key = b_content, value = [B@b5c6a30
key = lb_content, value = [B@3bfae028
key = id, value = 1
key = content, value = 红红火火恍恍惚惚aaa
testContent = TestContent(id=1, content=红红火火恍恍惚惚aaa, bContent=红红火火恍恍惚惚aaa, lbContent=红红火火恍恍惚惚aaa)
update = 1
testContent1 = TestContent(id=1, content=红红火火恍恍惚惚aaaq, bContent=红红火火恍恍惚惚aaa, lbContent=红红火火恍恍惚惚aaa)

二、问题深究

起初想法是直接自定义typeHandler一把梭,后来决定debug看一看发现,在驱动com.mysql.cj.jdbc.result.ResultSetImpl中public String getString(int columnIndex)时乱码就已经产生;
继续往下com.mysql.cj.protocol.a.result.TextBufferRow#getValue
然后是com.mysql.cj.protocol.result.AbstractResultsetRow#decodeAndCreateReturnValue
再然后com.mysql.cj.protocol.a.MysqlTextValueDecoder#decodeByteArray
最后com.mysql.cj.result.StringValueFactory#createFromBytes

public String createFromBytes(byte[] bytes, int offset, int length, Field f) {return StringUtils.toString(bytes, offset, length, f.getEncoding());
}

一看这个f.getEncoding()是ISO-8859-1
随后看了下8.0.17版本这个位置的代码,做了处理,使用url上的characterEncoding编码进行解码

public String createFromBytes(byte[] bytes, int offset, int length, Field f) {return StringUtils.toString(bytes, offset, length,f.getCollationIndex() == CharsetMapping.MYSQL_COLLATION_INDEX_binary ? this.pset.getStringProperty(PropertyKey.characterEncoding).getValue(): f.getEncoding());}

驱动改成8.0.17后清理数据执行一下看看

insert = 1
key = b_content, value = [B@5042e3d0
key = lb_content, value = [B@1c34365c
key = id, value = 1
key = content, value = 红红火火恍恍惚惚aaa
testContent = TestContent(id=1, content=红红火火恍恍惚惚aaa, bContent=红红火火恍恍惚惚aaa, lbContent=红红火火恍恍惚惚aaa)
update = 1
testContent1 = TestContent(id=1, content=红红火火恍恍惚惚aaaq, bContent=红红火火恍恍惚惚aaa, lbContent=红红火火恍恍惚惚aaa)

好的,这样我们就有了一种不用动代码的解决方法

三、解决方法

方法1

升级mysql驱动至8.0.17或以上版本

方法2

驱动不想或不能升级,那自定义typehandler是一个好的解决方法,在mybatis中debug发现,数据字段为blob、longblob、tinyblob时,JDBCType为JdbcType.LONGVARBINARY
以下是自定义TypeHandler

@MappedJdbcTypes(JdbcType.LONGVARBINARY)
@MappedTypes(String.class)
public class BlobToStringTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setBytes(i, parameter.getBytes(StandardCharsets.UTF_8));}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {return getStringFromBlob(rs.getBlob(columnName));}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return getStringFromBlob(rs.getBlob(columnIndex));}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return getStringFromBlob(cs.getBlob(columnIndex));}private String getStringFromBlob(Blob blob) throws SQLException {if (blob == null) return "";byte[] bytes = blob.getBytes(1, (int) blob.length());return new String(bytes, StandardCharsets.UTF_8);}
}

自定义后需要增加配置使其全局生效

mybatis:type-handlers-package: typeHandler所在包名

如果不想改配置文件,想通过代码的方式全局生效可以改一下sqlSessionFactory

@Configuration
public class MybatisConfig implements InitializingBean {@Autowiredprivate SqlSessionFactory sqlSessionFactory;@Overridepublic void afterPropertiesSet() {sqlSessionFactory.getConfiguration().getTypeHandlerRegistry().register("typeHandler所在包名");}
}

当然也可以在某个字段上单独生效,在查询的方法上增加

@Results(@Result(column = "b_content", property = "bContent",jdbcType = JdbcType.LONGVARBINARY, javaType = String.class,typeHandler = BlobToStringTypeHandler.class)
)







来点涩话
花点时间找找是否有更好的方法,结果会让你惊喜

http://www.dtcms.com/wzjs/414460.html

相关文章:

  • 网站建设制作报价方案厦门关键词排名seo
  • 廊坊网站建设方案最新报价知名网络软文推广平台
  • 做网站营销怎么去推广百度发布
  • 吴中区两学一做网站win优化大师怎么样
  • 上海网站建设公司招人黄山网站seo
  • 石家庄 外贸网站建设公司网页制作公司排名
  • 网站建设主要课程2023网站seo
  • 给公司建网站关键词排名靠前
  • 上海哪里有网站建设百度关键词点击工具
  • 做网站找哪家好seo网络营销推广公司深圳
  • wordpress怎么加标题百度seo 站长工具
  • 有一个网站自己做链接获取朋友位置职业培训网络平台
  • 杭州有哪些做网站的公司好yandx引擎入口
  • 做网站的调查问卷驻马店网站seo
  • 海南响应式网站建设方案点击器
  • 德阳做网站的公司seo长尾关键词排名
  • 公司做网站百度还是阿里今天新闻头条
  • 房产中介网站开发费用100种找客户的方法
  • 做有弹幕视频网站semantics
  • 桐城市住宅和城乡建设局网站bt磁力在线种子搜索神器下载
  • 广州建站服务商谷歌 翻墙入口
  • 互联网广告营销公司广州百度搜索优化
  • 有没有做古装衣服的网站网络推广与推广
  • 如何做招聘网站的数据分析广西seo
  • 网站建设与安全国家认可的教育培训机构
  • 建筑公司网站广告宣传语hao123网址导航
  • 网站建设便宜不可信搜索网站有哪几个
  • 找人做网站宁德市人口
  • 域名买好怎么开始做网站宁波seo营销平台
  • 分销网站有哪些老王搜索引擎入口