Spring Boot中如何动态向@ColumnTransformer注入配置变量
解决方案
Java注解的属性值要求为编译期常量,Spring的配置占位符无法直接解析注解内部的字符串,因此'${psql.key}'会被识别为普通字符串传入SQL,以下是两种可行的实现方案:
方案1:最小改动,复用原有@ColumnTransformer逻辑
该方案不需要修改实体类的注解代码,仅调整连接池配置即可实现密钥注入:
- 保留原有实体类上的
@ColumnTransformer配置,继续使用current_setting('encrypt.key')读取密钥 - 在
application.properties中添加连接初始化SQL配置,在每个数据库连接创建时自动设置会话级的encrypt.key参数,以默认的Hikari连接池为例:
# 配置加密密钥 psql.key=你的实际加密密钥 # 连接初始化时执行SET命令注入密钥,仅对当前连接生效 spring.datasource.hikari.connection-init-sql=SET encrypt.key = '${psql.key}'
如果使用Druid等其他连接池,替换为对应连接池的初始化SQL配置项即可。
该方案优势:完全复用PostgreSQL原生pgcrypto加解密能力,代码改动量极低,无需调整RDS实例配置,会话级参数不会影响其他数据库连接。
方案2:Java层加解密,不依赖数据库扩展
如果不想依赖PostgreSQL的pgcrypto扩展,可以使用JPA的AttributeConverter在应用层面实现加解密,直接注入配置密钥:
- 实现自定义加解密转换器:
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.persistence.AttributeConverter; // 你需要自行实现PgpUtil工具类,保证加解密逻辑与pgp_sym_encrypt/pgp_sym_decrypt兼容 @Component public class PgpEncryptConverter implements AttributeConverter<String, byte[]> { @Value("${psql.key}") private String encryptKey; @Override public byte[] convertToDatabaseColumn(String rawContent) { return PgpUtil.encrypt(rawContent, encryptKey); } @Override public String convertToEntityAttribute(byte[] encryptedContent) { return PgpUtil.decrypt(encryptedContent, encryptKey); } }
- 在实体类字段上绑定转换器即可:
@Convert(converter = PgpEncryptConverter.class) @Column(columnDefinition = "bytea") private String test;
该方案优势:不依赖数据库特定功能,迁移数据库时无需调整加解密逻辑;缺点是需要自行实现与PG兼容的加解密逻辑。
内容的提问来源于stack exchange,提问作者Hikaru Shindo
相关产品推荐
相关产品推荐

