2015-01-20 3 views
2

Рассмотрим я следующей весной бобыPropagate весной сделка двойников называют

CompositeService:

@Service 
public class CompositeService { 

    @Resource 
    private ServiceA serviceA; 

    @Resource 
    private ServiceB serviceB; 

    public ResultBean compositeMethod() { 
     ResultBean result = new ResultBean(); 
     result.setA(serviceA.getA()); 
     result.setB(serviceB.getB()); 
     return result; 
    } 

} 

ServiceA:

@Service 
public class ServiceA { 

    @Transactional 
    @Cacheable 
    A getA() { 
     // calls DAO layer and makes a query to the database 
    } 

} 

ServiceB:

@Service 
public class ServiceB { 

    @Transactional 
    @Cacheable 
    B getB() { 
     // calls DAO layer and makes a query to the database 
    } 

} 

кэшируемым аспект имеет более высокий порядок

Проблема с этим кодом является то, что он начнет две операции (и принять два соединения из пула) в случае кэш-промаха в обеих службах. Могу ли я настроить Spring для использования той же транзакции в этом случае? I.E. распространять транзакцию от ServiceA до CompositeService и после этого до ServiceB?

Я не могу установить CompositeService в транзакционных, потому что я не хочу, чтобы начать транзакцию (и заимствовать соединение с бассейном) в случае кэш-хит как в ServiceA и ServiceB

+0

Он будет работать только в том случае, если метод включения (в 'CompositeService') является транзакционным. Почему было бы проблемой проверить соединение на пару миллисекунд, если это то, о чем вас беспокоит ИМХО, вы беспокоитесь о неправильных вещах. –

+0

@ M.Deinum в моем конкретном случае база данных развернута в центре обработки данных в другом регионе с задержкой в ​​300 мс между Java-приложением и базой данных – bedrin

+0

Итак? У вас есть пул соединений, поэтому соединения уже существуют. Единственное, что происходит, - это подключение, извлеченное из пула. Ничего больше. Это должно просто взять ~ 1 мс ... –

ответ

1

Весна будет распространять транзакцию только в том случае, если все находится под одной и той же транзакцией. Поэтому короткий ответ заключается в том, что вы должны аннотировать свой CompositeService с помощью @Transactional.

@Service 
public class CompositeService { 

    @Transactional 
    public ResultBean compositeMethod() { 
     ResultBean result = new ResultBean(); 
     result.setA(serviceA.getA()); 
     result.setB(serviceB.getB()); 
     return result; 
    } 
} 

Как правило, это достаточно быстро, поскольку он выполняет проверку только в базовом пуле подключений. Однако, если вы испытываете латентность или не всегда нуждаетесь в соединении, вы можете обернуть свой фактический DataSource в LazyConnectionDataSourceProxy. Это при необходимости получит Connection.

0

Что вы можете сделать это, вы можете аннотировать compositeMethod с @Transactional. Уровень распространения по умолчанию для транзакции установлен в значение Обязательно

Поддержка текущей транзакции, создайте новую, если она не существует.

Так что, хотя это не совсем то, что вы просили, демаркация транзакций начинается с составного метода, но это должна быть именно семантика, которую вы хотите.

+0

Я не могу установить CompositeService как транзакцию, потому что я не хочу запускать транзакцию (и заимствовать соединение из пула) в случае попадания в кеш как в ServiceA, так и в ServiceB – bedrin

+2

mhm, ваша проблема гораздо интереснее, что она встречает взгляд на первый взгляд –

Смежные вопросы