@transactional仅在一个方法上

zpqajqem  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(288)

我需要创建一个@scheduled方法,它有一个模式列表,对于每个模式,从两个表中删除行。

@Scheduled(fixedDelay = 10000)
public void scheduleFixedDelayTask() {
    List<String> presentSchemas = getPresentSchemas();
    for (String schema : presentSchemas) {
        deleteFromCustomerTables(schema);
    }
}

我将deletefromcustomertables定义为@transactional(propagation=propagation.requires_new),并在其中使用entitymanager从2个表中删除行。
为了让它工作,我需要将@transactional添加到schedulefixeddelaytask,否则我会收到transactionrequiredexception。
我的问题是,我不希望整个调度程序是@transactional的,如果某个模式出错,我不希望回滚所有模式。
我也尝试过不使用@transactional和:

Session session = entityManager.unwrap(Session.class);
    Transaction t = session.beginTransaction();
    //exec delete
    t.commit();
    session.close();

但我还是收到了transactionrequiredexception。你有解决办法吗?

j0pj023g

j0pj023g1#

必须确保事务管理器的配置如下:

@Configuration
@EnableTransactionManagement
public class TransactionConfig {

  @Bean
  @Primary
  public PlatformTransactionManager transactionManager() {
    return new JpaTransactionManager();
  }
}

必须确保deletefromcustomertables方法不在同一个组件中,如下所示:

@Component
class Component1 {
   void scheduleFixedDelayTask(){...}
}

@Component
class Component2 {
   void deleteFromCustomerTables(){...}
}

但是在非常高的级别上,spring为类创建代理,这些类在类本身或成员上声明@transactional。代理在运行时基本上是不可见的。它为spring提供了一种将方法调用之前、之后或前后的行为注入被代理对象的方法。事务管理只是可以连接的行为的一个例子。安全检查是另一回事。你也可以提供你自己的,比如日志记录。因此,当您使用@transactional注解一个方法时,spring会动态创建一个代理,该代理实现与您所注解的类相同的接口。当客户机对您的对象进行调用时,调用将被拦截,行为将通过代理机制注入。

相关问题