我有perconamysql服务器和java客户机与自定义orm。在db中,我有一个表:
CREATE TABLE `PlayerSecret` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`created` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
`secret` binary(16) NOT NULL,
`player_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `PlayerSecret_secret_unique` (`secret`),
KEY `PlayerSecret_player_id` (`player_id`)
) ENGINE=InnoDB AUTO_INCREMENT=141 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
我找到了那个问题 SELECT PlayerSecret.player_id FROM PlayerSecret WHERE PlayerSecret.secret = ?
当参数由提供时返回空结果集 java.sql.PreparedStatement#setBytes
方法,并按预期工作 java.sql.PreparedStatement#setBinaryStream
. 我启用了mysql通用日志,发现在这个日志中两个查询是相同的,我在hex模式下检查了这个。
一般来说,它看起来像:
SELECT PlayerSecret.player_id FROM PlayerSecret WHERE PlayerSecret.secret = '<96>R\Ø8üõA\í¤Z´^E\Ô\ÊÁ\Ö'
十六进制模式下常规日志的查询参数: 2796 525c d838 fcf5 415c eda4 5ab4 055c d45c cac1 5cd6 27
数据库中的值:
mysql> select hex(secret) from PlayerSecret where id=109;
+----------------------------------+
| hex(secret) |
+----------------------------------+
| 9652D838FCF541EDA45AB405D4CAC1D6 |
+----------------------------------+
1 row in set (0.00 sec)
问题是我的orm正在执行这个查询 setBytes
方法,我认为这是正确的方法 BINARY
数据类型,但它不工作。
部分 my.cnf
使用编码设置(可能很重要):
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
general_log = on
general_log_file=/var/log/mysql/mysqld_general.log
require_secure_transport = ON
init-connect = SET collation_connection = utf8mb4_unicode_ci
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
java代码:
var uuid = UUID.fromString("9652d838-fcf5-41ed-a45a-b405d4cac1d6");
var array = ByteBuffer.allocate(16).putLong(uuid.getMostSignificantBits()).putLong(uuid.getLeastSignificantBits()).array();
// works
stmt.setBinaryStream(index, new ByteArrayInputStream(array));
// don't works
stmt.setBytes(index, array);
我不明白这两种情况有什么区别,以及如何解决这个问题 setBytes
变体。也许有人能澄清这一点,或者给我指出一些重要的地方?
我的环境:
开放JDK 11
hicaricp 3.1.0版
mysql连接器/j 8.0.13
percona 5.7.24-26-log percona服务器(gpl),版本'26',修订版'c8fe767'
1条答案
按热度按时间jfgube3f1#
我终于明白了。问题出在
character_set_client=utf8
而不是utf8mb4
.此查询显示预期值和实际线程值之间的差异(认为这是一个非常方便的查询):
当我替换
init-connect = SET collation_connection = utf8mb4_unicode_ci
与init_connect='SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
在my.cnf
问题消失了,尽管如此setBytes
开始按预期工作。为什么它适用于
setBinaryStream
也不适用于setBytes
-因为在第一种情况下com.mysql.cj.ServerPreparedQueryBindings#setBinaryStream(int, java.io.InputStream, int)
:重要的是
binding.resetToType(MysqlType.FIELD_TYPE_BLOB
-驱动程序注意到这个数据BLOB
在第二种情况下com.mysql.cj.ServerPreparedQueryBindings#setBytes(int, byte[])
包含: