首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将自定义数据库会话变量添加到Spring查询中?

将自定义数据库会话变量添加到Spring查询中?
EN

Stack Overflow用户
提问于 2022-11-07 11:04:54
回答 1查看 42关注 0票数 1

我正在尝试将SET SESSION encrypt.key='some_key'设置为数据库查询或连接。

问题是我在我的模型类中有以下列定义

@Column转换器(forColumn= "first_name",read = "pgp_sym_decrypt(first_name,current_setting(‘encrypt.key’)“),read= "pgp_sym_encrypt(?,current_setting(‘encrypt.key’)”) @Column(name = "first_name",columnDefinition = "bytea")私有字符串firstName;

当我们在encrypt.key文件中直接设置postgres.conf文件时,上面的操作是有效的,但我们的需求是从spring属性文件中配置encrypt.key

我试过的东西。

自定义转换器类的

  1. AttributeConverter注释只适用于JPA,类似操作不受支持。
  2. I尝试了ContextEventListener,在应用程序启动时执行SET会话查询,但这只适用于很少的请求

@Override

代码语言:javascript
运行
复制
protected void prepareSynchronization(DefaultTransactionStatus status,TransactionDefinition definition) {
        super.prepareSynchronization(status, definition);
        if (status.isNewTransaction()) {
            final String query = "SET encrypt.key='" + encryptKey + "'";
            entityManager.createNativeQuery(query).executeUpdate();
        }
        log.info("Encrypt Key : {}", entityManager.createNativeQuery("SElECT current_setting('encrypt.key')").getSingleResult());
    }
}

当我调用普通的JPA方法时,上面的encrypt.key不起作用,并且在normal中,CustomTransactionManager类没有被设置为CustomTransactionManager类。

任何正确的指导都会对我有很大帮助。

EN

回答 1

Stack Overflow用户

发布于 2022-11-16 14:02:00

因为我创建了CustomTransactionManager扩展JpaTransactionManager

代码语言:javascript
运行
复制
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionStatus;

import javax.persistence.EntityManager;

@Component
@Slf4j
@Primary
@Qualifier(value = "transactionManager")
public class CustomTransactionManager extends JpaTransactionManager {
    @Autowired
    private EntityManager entityManager;

    @Value("${database.encryption.key}")
    private String encryptKey;

    @Override
    protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
        super.prepareSynchronization(status, definition);
        if (status.isNewTransaction()) {
            final String query = "SET SESSION encrypt.key='" + encryptKey + "'";
            entityManager.createNativeQuery(query).executeUpdate();
        }
    }
}

当我使用普通的方法时,上面并没有被调用。例如,

代码语言:javascript
运行
复制
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByFirstName(String firstName);

}

在Repository类中添加@Transactional确实覆盖了框架逻辑,该框架逻辑为所有存储库bean在后台创建共享事务。这使得即使使用存储库方法也可以调用我的CustomTransactionManager。

我最初认为添加事务注释是过分的,但发现它也是在框架级别自动创建的,因此手动添加它本身没有额外的内存占用空间,但是您在CustomTransactionManager类中编写的代码/查询将添加所需的请求占用空间。

因此,我最后在其域(表)具有加密列的所有存储库类上添加了@Transactional注释。

对于我的用例,这是使用Spring在Azure数据库服务上进行列级加密的最灵活的解决方案,因为我们不能从Azure在那里添加自定义环境变量,而且直接添加到postgres.conf文件也是不可能的,因为它是一个SAAS服务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74345585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档