Spring @Transaction注解用于同一个类内部的方法调用时不起作用?

57 浏览
0 Comments

Spring @Transaction注解用于同一个类内部的方法调用时不起作用?

我初次接触Spring事务。我发现了一些非常奇怪的问题,可能我理解有问题。

我想在方法级别上使用事务,并且我在同一个类中有一个调用者方法,但似乎它不喜欢这样做,必须从另一个类中调用。我不明白这是如何可能的。

如果有人知道如何解决这个问题,我会非常感激。我想使用同一个类来调用注释事务方法。

这里是代码:

public class UserService {
    @Transactional
    public boolean addUser(String userName, String password) {
        try {
            // call DAO layer and adds to database.
        } catch (Throwable e) {
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
        }
    }
    public boolean addUsers(List users) {
        for (User user : users) {
            addUser(user.getUserName, user.getPassword);
        }
    } 
}

admin 更改状态以发布 2023年5月23日
0
0 Comments

在Java 8+中,还有另外一种可能性,出于以下原因,我更倾向于这种方法:

@Service
public class UserService {
    @Autowired
    private TransactionHandler transactionHandler;
    public boolean addUsers(List users) {
        for (User user : users) {
            transactionHandler.runInTransaction(() -> addUser(user.getUsername, user.getPassword));
        }
    }
    private boolean addUser(String username, String password) {
        // TODO call userRepository
    }
}
@Service
public class TransactionHandler {
    @Transactional(propagation = Propagation.REQUIRED)
    public  T runInTransaction(Supplier supplier) {
        return supplier.get();
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public  T runInNewTransaction(Supplier supplier) {
        return supplier.get();
    }
}

此方法具有以下优点:

  1. 可以应用于私有方法。因此,您不必将方法公开以满足Spring的限制,从而不必破坏封装性。
  2. 同一方法可以在不同的事务传播中被调用,且由调用者自行选择合适的传播。比较以下两行代码:
  3. transactionHandler.runInTransaction(() -> userService.addUser(user.getUserName, user.getPassword));

    transactionHandler.runInNewTransaction(() -> userService.addUser(user.getUserName, user.getPassword));

  4. 它是显式的,因此更易读。
0
0 Comments

这是Spring AOP(动态对象和cglib)的限制。

如果你配置Spring使用AspectJ来处理事务,你的代码就可以工作。

简单而可能最好的替代方案是重构你的代码。例如,一个处理用户的类和一个处理每个用户的类。然后默认的Spring AOP事务处理就可以工作。


有关使用AspectJ处理事务的配置技巧

要让Spring使用AspectJ处理事务,你必须将模式设置为AspectJ:


如果你使用的是版本低于3.0的Spring,你还必须将这个添加到你的Spring配置中:


    

0