Squeryl如何支持MySQL的utf8mb4编码插入4字节UTF-8字符串
我之前也踩过MySQL utf8的坑——它居然只支持3字节字符,要存emoji这类4字节的UTF-8字符,必须用utf8mb4。结合你不能改数据库配置的情况,咱们从JDBC连接和Squeryl的连接初始化入手来解决:
1. 修正JDBC连接URL参数
别再用characterEncoding=UTF-8了,直接把它替换成utf8mb4,同时确保你的MySQL驱动版本足够新(mysql-connector-java 5.1.47+ 或者 8.x版本),不然旧驱动可能不识别这个参数。完整的URL示例如下:
jdbc:mysql://your-host:3306/your-db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC
useUnicode=true还是要保留,配合characterEncoding=utf8mb4就能让JDBC连接全程用utf8mb4编码通信。
2. 通过连接池初始化连接时执行SET NAMES utf8mb4
如果上面的URL设置还不生效(比如某些旧驱动兼容性问题),可以利用连接池的连接初始化SQL功能,每次获取连接时自动执行SET NAMES utf8mb4;。比如用HikariCP连接池的话,配置代码可以这么写:
HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://你的数据库地址/库名"); config.setConnectionInitSql("SET NAMES utf8mb4;"); // 其他配置:用户名、密码、连接池大小等... DataSource dataSource = new HikariDataSource(config);
然后把这个配置好的数据源传给Squeryl的SessionFactory:
import org.squeryl.Session import org.squeryl.adapters.MySQLAdapter import javax.sql.DataSource SessionFactory.concreteFactory = Some(() => Session.create(dataSource, new MySQLAdapter))
这样每次Squeryl获取数据库连接时,都会自动执行SET NAMES utf8mb4,强制连接使用utf8mb4编码。
3. 确保表和列的字符集是utf8mb4
这一步绝对不能忘!如果你的表还是用utf8字符集,哪怕连接配置对了,插入4字节字符还是会报错。
- 如果是新建表:可以在Squeryl的Schema创建逻辑里,添加修改字符集的语句:
import org.squeryl.Schema class YourAppSchema extends Schema { val yourTable = table[YourEntity] override def create { super.create // 创建表后修改为utf8mb4字符集 execute("ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") } }
- 如果是已存在的表:可以手动执行ALTER语句,或者通过Squeryl的
execute方法在应用启动时执行一次。
4. 验证连接编码是否生效
可以在代码里加个小查询,确认当前连接的字符集是否正确:
Session.currentSession.executeQuery("SHOW VARIABLES LIKE 'character_set_connection';") { rs => if (rs.next()) { println(s"当前连接字符集: ${rs.getString(2)}") } }
如果输出是utf8mb4,就说明连接配置已经生效了。
这套操作全程在应用层完成,不用改数据库全局配置,应该就能顺利插入4字节UTF-8字符了。
内容的提问来源于stack exchange,提问作者Minh Thai

