代码之家  ›  专栏  ›  技术社区  ›  Flarosa

如何在Hibernate/JPA中控制事务?

  •  -1
  • Flarosa  · 技术社区  · 3 年前

    我正在一个使用JPA的Spring Boot项目中工作。我有一个使用@scheduled注释创建的计划任务。

    此任务调用方法A,方法A调用方法B。方法B具有@Transactional注释,并对实体执行一些操作。不幸的是,当我尝试访问延迟加载的属性时,方法B抛出了一个LazyInitializationException,声称“无法初始化代理-无会话”。

    我以前见过这个问题,并通过向方法中添加@Transactional注释来解决它,但在这种情况下,注释就在那里,我仍然看到它。

    如果我用@Transaction注释方法A,错误就会消失。但这不是我想要的。方法A做一些长时间运行的工作(发送电子邮件和推送通知),我不希望这些工作发生在事务内部,因为这可能会使数据库锁定很长一段时间。

    为什么我不能将交易仅限于方法B?

    谢谢 直率的

    0 回复  |  直到 3 年前
        1
  •  0
  •   Gavin King    3 年前

    我的意思是,你到底在问什么?

    • 您是否在询问如何在Hibernate和标准JPA中控制事务和持久性上下文的生命周期?(如您的问题标题所示。)
    • 或者您在询问如何控制中的交易 春天 .

    因为春天是它自己的野兽。

    如果你想知道如何在标准JPA中进行,简单的答案是: createEntityManager() 创建持久性上下文,以及 close() 当你想清理的时候。

    或者,如果您使用标准的JPA注释来注入 EntityManager 您使用:

    @PersistenceContext(type=EXTENDED)
    EntityManager entityManager;
    

    以注入扩展的持久性上下文。然后,该PC的生存期最终由它被注入的bean的生存期决定,如EJB或CDI或其他什么定义的。

    当然,Spring不遵循JPA规范,也不遵循CDI标准,而是以自己的方式完成所有工作。(与接受标准的Hibernate不同,Spring拒绝标准的历史由来已久。)

        2
  •  0
  •   Jens Schauder    3 年前

    注释的方法 B 如果 B 是一个bean(即它是由Spring注入的,而不是由代码实例化的,并且该方法是公共的。

    如果你不想改变 B 得到构造或其方法的可见性,您可以使用 TransactionTemplate 以显式地控制事务。

        3
  •  0
  •   Flarosa    3 年前

    谢谢你的建议。我现在对此有了更好的理解。如果从同一类中的另一个方法调用一个方法,我认为注释不起作用。

    我通过让我的顶级方法分别调用A和B而不是A调用B来修复它。在这种情况下,它很有效,但我期待下次使用TransactionTemplate。

    多年前(2005年),我在Hibernate中做了很多工作,当时可能理解了这一点,但忘记了。在此期间,我主要在JDBC之上使用自己的框架。

    直率的