Вы можете вызвать метод TransactionAspectSupport.currentTransactionStatus().isNewTransaction()
, чтобы узнать, является ли текущая транзакция новой (т.е. она не была передана из другого @Transactional
метода) или нет:
@Transactional
public void insertEntity(Entity entity){
if (!TransactionAspectSupport.currentTransactionStatus().isNewTransaction()) {
throw new IllegalStateException("Transaction is not new!");
}
persistence.save(entity);
}
Статический метод TransactionAspectSupport.currentTransactionStatus()
возвращает объект TransactionStatus
, который представляет статус транзакции текущего вызова метода .
Я написал минимальное веб-приложение Spring MVC для проверки вашего сценария (я опускаю классы и файлы конфигурации, а также объявления import
и package
s):
TestController.java
@RestController
public class TestController {
private static final Logger log = LoggerFactory.getLogger(TestController.class);
@Autowired
private ServiceOne serviceOne;
@Autowired
private ServiceTwo serviceTwo;
@GetMapping(path = "/test-transactions")
public String testTransactions() {
log.info("*** TestController.testTransactions() ***");
log.info("* Invoking serviceOne.methodOne()...");
try {
serviceOne.methodOne();
}
catch (IllegalStateException e) {
log.error("* {} invoking serviceOne.methodOne()!", e.getClass().getSimpleName());
}
log.info("* Invoking serviceTwo.methodTwo()...");
try {
serviceTwo.methodTwo();
}
catch (IllegalStateException e) {
log.error("* {} invoking serviceTwo.methodTwo()!", e.getClass().getSimpleName());
}
return "OK";
}
}
ServiceOneImpl.java
@Service
public class ServiceOneImpl implements ServiceOne {
private static final Logger log = LoggerFactory.getLogger(ServiceOneImpl.class);
@Autowired
private ServiceTwo serviceTwo;
@PersistenceContext
private EntityManager em;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void methodOne() {
log.info("*** ServiceOne.methodOne() ***");
log.info("getCurrentTransactionName={}", TransactionSynchronizationManager.getCurrentTransactionName());
log.info("isNewTransaction={}", TransactionAspectSupport.currentTransactionStatus().isNewTransaction());
log.info("Query result={}", em.createNativeQuery("SELECT 1").getResultList());
log.info("getCurrentTransactionName={}", TransactionSynchronizationManager.getCurrentTransactionName());
log.info("isNewTransaction={}", TransactionAspectSupport.currentTransactionStatus().isNewTransaction());
serviceTwo.methodTwo();
}
}
ServiceTwoImpl.java
@Service
public class ServiceTwoImpl implements ServiceTwo {
private static final Logger log = LoggerFactory.getLogger(ServiceTwoImpl.class);
@PersistenceContext
private EntityManager em;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void methodTwo() {
log.info("*** ServiceTwo.methodTwo() ***");
log.info("getCurrentTransactionName={}", TransactionSynchronizationManager.getCurrentTransactionName());
log.info("isNewTransaction={}", TransactionAspectSupport.currentTransactionStatus().isNewTransaction());
if (!TransactionAspectSupport.currentTransactionStatus().isNewTransaction()) {
log.warn("Throwing exception because transaction is not new...");
throw new IllegalStateException("Transaction is not new!");
}
log.info("Query result={}", em.createNativeQuery("SELECT 2").getResultList());
log.info("getCurrentTransactionName={}", TransactionSynchronizationManager.getCurrentTransactionName());
log.info("isNewTransaction={}", TransactionAspectSupport.currentTransactionStatus().isNewTransaction());
}
}
А вот и журнал казни:
INFO test.transactions.web.TestController - *** TestController.testTransactions() ***
INFO test.transactions.web.TestController - * Invoking serviceOne.methodOne()...
INFO test.transactions.service.ServiceOneImpl - *** ServiceOne.methodOne() ***
INFO test.transactions.service.ServiceOneImpl - getCurrentTransactionName=test.transactions.service.ServiceOneImpl.methodOne
INFO test.transactions.service.ServiceOneImpl - isNewTransaction=true
INFO test.transactions.service.ServiceOneImpl - Query result=[1]
INFO test.transactions.service.ServiceOneImpl - getCurrentTransactionName=test.transactions.service.ServiceOneImpl.methodOne
INFO test.transactions.service.ServiceOneImpl - isNewTransaction=true
INFO test.transactions.service.ServiceTwoImpl - *** ServiceTwo.methodTwo() ***
INFO test.transactions.service.ServiceTwoImpl - getCurrentTransactionName=test.transactions.service.ServiceOneImpl.methodOne
INFO test.transactions.service.ServiceTwoImpl - isNewTransaction=false
WARN test.transactions.service.ServiceTwoImpl - Throwing exception because transaction is not new...
ERROR test.transactions.web.TestController - * IllegalStateException invoking serviceOne.methodOne()!
INFO test.transactions.web.TestController - * Invoking serviceTwo.methodTwo()...
INFO test.transactions.service.ServiceTwoImpl - *** ServiceTwo.methodTwo() ***
INFO test.transactions.service.ServiceTwoImpl - getCurrentTransactionName=test.transactions.service.ServiceTwoImpl.methodTwo
INFO test.transactions.service.ServiceTwoImpl - isNewTransaction=true
INFO test.transactions.service.ServiceTwoImpl - Query result=[2]
INFO test.transactions.service.ServiceTwoImpl - getCurrentTransactionName=test.transactions.service.ServiceTwoImpl.methodTwo
INFO test.transactions.service.ServiceTwoImpl - isNewTransaction=true