当前位置: 首页 > 知识库问答 >
问题:

使用Spring JPA Hibernate对非事务性写入强制执行异常

司徒鸿文
2023-03-14

我们有一个使用JPA over Hibernate的Spring Boot REST应用程序(Spring Boot 2.0.x、spring-tx 5.0.x、Hibernate 5.2.x)。基础数据库是Oracle。

我们的体系结构不公开JPA实体,相反,服务层将实体转换为DTO模型类,这些类公开给REST控制器层。要进行更新,我们不使用自动刷新,但总是显式调用服务类CRUD方法,这些方法转换为存储库上的saveandflush()deletebyid()(分别用于创建/更新或删除)。

我们想要的是:

  1. 只读操作以非事务性方式执行
  2. 写入操作(单个或多个)在单个事务中执行
  3. 如果忘记在写操作中声明事务,则会发出警报。

为此,我们有:

>

  • 存储库超级接口使用@transactional(Propagation=supports,readonly=true)进行注释,它涵盖了第1点。

    服务类没有注释,服务写方法用`@transactional(propagation=required)注释,这涵盖了第2点。

    存储库saveandflush(entity)deletebyid(id)方法(当前唯一从服务调用的写入方法)使用@transactional(Propagation=manditory)进行注释,如果在事务上下文之外执行这些方法,则会引发异常。

    因此,关于第3点,如果有人定义了一个新的写入数据的服务方法,而忘记在其上应用@transactional,我们也没有问题:将引发异常。

    但是,如果有人使用另一个存储库方法来写入数据,而忘记在服务级别对其进行注释,那么它将不会从服务级别获得任何事务,而是在存储库的默认(类级别)事务性内执行,也就是说:support。在这种情况下,没有正在进行的事务,只读标志将被忽略,写入将以静默方式完成。

    请注意,当@transactional上的readonly标志被设置时,Hibernate的flushMode被设置为MANUAL。如果我们有required传播,则写入将被无人值守地忽略(这也是不可接受的),而在支持传播的上下文中,写入将被无人值守地执行。

    有没有什么方法可以设置Spring transactions/JPA/Hibernate,使存储库允许非事务性读取,但在写入任何数据时抛出异常,除非通过我们为声明@transactional(Propagation=mandition)而重写的方法之一?

    如上所述,readonly=true没有实现这一点,即使它设置了Hibernate的FlushMode。

  • 共有1个答案

    章威
    2023-03-14

    如果验证TransactionManager能做到这一点,那就试试看:https://info.michael-simons.eu/2018/09/25/validate-nested-transaction-settings-with-spring-and-spring-boot/

    import org.springframework.boot.autoconfigure.transaction.PlatformTransactionManagerCustomizer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.transaction.support.AbstractPlatformTransactionManager;
    
    @Configuration
    class TransactionManagerConfiguration {
    
        @Bean
        public PlatformTransactionManagerCustomizer<AbstractPlatformTransactionManager> transactionManagementConfigurer() {
            return (AbstractPlatformTransactionManager transactionManager) -> transactionManager
                .setValidateExistingTransaction(true);
        }
    }
    
     类似资料:
    • 问题内容: 我们的REST API接收一些JSON对象输入,其中某些字段必须不为null。这些可以是String / Integer,甚至可以是其他一些类实例作为参考。 我们正在尝试寻找一种方法来强制这些字段不为null,而不是在API中进行null检查的正确方法。当前: 我们想要的是这样的: 我们尝试了3件事: 1)升级到杰克逊2.0.6并使用注释com.fasterxml.jackson.an

    • 我正在查看一些现有的代码,并想知道在下面的场景中使用Spring的@Transactional注释会发生什么?考虑以下示例: 下面的updateDataBaseItem()方法是常见的,可以从其他非事务性方法和上面的方法调用:

    • 问题内容: 我需要向使用kso​​ap 2连接到Web服务的J2ME应用程序添加超时。 我已经尝试了在http://ksoap2.sourceforge.net/doc/api/org/ksoap2/transport/HttpTransport.html上描述为可能的伪超时的方法,但该方法似乎在此设备上不起作用。 我会在另一个线程上运行该连接,并在计时器触发时杀死它,但是按照http://dev

    • 在上面的代码中,ConstraintViolationException发生在saveTicket()方法内,saveTicket()内的dao甚至在捕获异常之前就已经回滚了它的事务(这是我所知道的),第一个没有回滚,因为它在另一个事务中。(这是我已经知道的行为)。 当我使用另一个事务性方法调用这两个预览方法(updateRequest()和saveTicket()),当saveTicket()方

    • 我想知道在使用TypeScript时,是否有任何工具或技术用于对对象数据进行低级验证。一个例子是HTTP服务上的POST请求的JSON主体。通常,我为预期的数据创建了一个接口,然后将数据强制转换到该接口,但我知道这是肤浅的。 结合静态和运行时类型检查以提高开发效率

    • 我们使用HiberNate作为JPA提供程序。当其中一个实体更新时,我需要对Quartz计划执行一些更新。目前,该代码是在该实体的更新方法中调用的。但是,Quartz更改只有在事务成功提交时才会生效。 我考虑过实现一个实体监听器,但是我只想在实体被特定方法修改时执行这些更新,并且我不确定JPA实体监听器是否支持依赖注入,我需要依赖注入来获取对Quartz调度器的引用。 有没有办法以编程方式附加活动