【问题标题】:Using EntityManager as an autowired field in a Spring Repository使用 EntityManager 作为 Spring 存储库中的自动装配字段
【发布时间】:2021-01-26 17:09:18
【问题描述】:

我正在处理遗留代码库,并在我们的自定义存储库中看到了一些令人不安的东西。 EntityManager 直接自动连接到存储库中。例如:

@Repository
public class OperationRepository {

    // Yikes
    private final EntityManager entityManager;

    private QOperation operation = QOperation.operation;

    @Autowired
    public OperationRepositoryImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public Optional<Operation> findOneByIdAndType(Long operationId, OperationType type) {
        JPAQuery<Operation> query = new JPAQuery<>(entityManager);
        QOperation qOperation = QOperation.operation;
        query.select(operation).from(operation)
                .where(
                        operation.type.eq(type),
                ...
    }
}

我的理解是这很危险,因为EntityManager 不是线程安全的,并且在这里作为一个字段进行管理。我在我们的任何配置文件中都没有看到明确的定义来提供EntityManager bean,所以我不确定 Spring 在这种情况下会做什么。

我将开始修复在此处使用 @PersistenceContext 的问题,但我想了解这么长时间在生产中对它的影响以及它可能带来的后果。

我们是否会将连接池大小限制为存储库 bean 中单个实体管理器的数量?是否还有其他可能造成的危险?还是我做的太多了?

【问题讨论】:

    标签: java spring dependency-injection spring-data-jpa thread-safety


    【解决方案1】:

    这真的取决于你的应用程序上下文的配置,如果你使用它,它可能会被 Spring Boot 配置,但一般来说,使用典型设置这不是问题。

    在这样的设置中,应用程序上下文不包含单个(或一组有限的)EntityManager 实例,而是一个EntityManagerFactory,它可以按需创建EntityManager 实例。 而且你也不会被注入一个普通的EntityManager,而是一个代理,它会在不同的调用时指向不同的实例,通常这样每个线程都有自己的EntityManager,并且在网络请求完成后,下一个请求由同一个线程得到一个新的实例。

    如果您仍然担心,我建议使用调试器检查 EntityManager 并确认它确实是一个代理,并且它为不同线程委托给不同的实际实例。

    您可能还想看看这个关于 Spring Scopes 的问题,这是它的底层抽象:Spring Bean Scopes

    【讨论】:

    • 我不知道代理模式。调试器显示:shared entitymanager proxy for target factory 用于 EntityManager
    • 非常有趣。所以OperationRepository 仍然是一个单例,但 EntityManager 是一个代理。在那种情况下,这是一个有效的模式还是应该切换到PersistenceContext,为什么?
    • 这是完全有效的。我不知道使用PersistenceContext 有什么好处
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 2015-02-22
    • 2015-07-28
    • 1970-01-01
    相关资源
    最近更新 更多