@Nationalized 搭配Hibernate Envers时非英文字符审计异常问题
连接字符串中设置了sendStringParametersAsUnicode=false,会强制JDBC驱动以非Unicode(VARCHAR)编码发送所有字符串参数。主表的@Nationalized字段能正常存储非英文字符,是因为Hibernate会通过setNString方法显式以Unicode方式绑定参数;但Hibernate Envers默认未对审计字段的@Nationalized属性做特殊处理,依然使用普通的setString方法传递参数,导致非英文字符被转成问号存入NVARCHAR类型的审计表字段。
方案一:启用Envers对Nationalized类型的支持
在Spring Boot配置文件中添加以下Hibernate属性,让Envers识别@Nationalized注解并以Unicode方式处理审计字段的参数绑定:
spring.jpa.properties.hibernate.envers.use_nationalized_types=true
该配置会让Envers在生成审计数据插入语句时,针对@Nationalized字段使用setNString方法传递参数,即使全局sendStringParametersAsUnicode=false,也能保证这类字段的非英文字符正常存储。
方案二:调整连接字符串与字段定义
如果不需要全局关闭Unicode参数发送,可移除连接字符串中的sendStringParametersAsUnicode=false,同时对不需要Unicode支持的字段,显式指定非Unicode类型:
@Column(columnDefinition = "VARCHAR(255)") private String asciiOnlyField;
这样既保证@Nationalized字段(含审计表)以Unicode方式存储非英文字符,又能通过显式的VARCHAR定义优化纯ASCII字段的性能。
方案三:强制审计字段的参数类型
如果上述方案无效,可在实体类的@Nationalized字段上额外添加@Type注解,明确指定Unicode类型:
@Nationalized @Type(type = "org.hibernate.type.StringNVarcharType") private String myField;
这会强制Hibernate(包括Envers)在处理该字段时始终使用NVARCHAR类型的参数绑定,不受全局连接字符串参数影响。
内容的提问来源于stack exchange,提问作者MoSaleh

