Как указывало @hvgotcodes, транзакции управляются на уровне службы, а не на уровне постоянства. Это происходит из-за значения вещей, которые должны быть транзакционными =>, которые в большинстве случаев определяются бизнесом, следовательно, уровень обслуживания / домена.
Вот пример того, как выполнить ваш сервис через XML-конфигурацию Spring AOP:
<aop:config>
<aop:pointcut id="moneyMakingBusinessServiceMethods"
expression="execution(* org.gitpod.startup.service.MoneyMakingBusinessService.*(..))"/>
<aop:advisor advice-ref="moneyMakingAdvice"
pointcut-ref="moneyMakingBusinessServiceMethods"/>
</aop:config>
<tx:advice id="moneyMakingAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="makeMoney" propagation="REQUIRED"/>
<tx:method name="withdrawMoney" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
Этот подход хорош, потому что вам не нужно загрязнять свои услуги аннотациями @Transactional
, @SomethingElse
, а все управление / конфигурация вашего TX определяется в одном месте [это мое личное убеждение].
Эта служба займет один или два Дао / Репозитория и делегирует ему все постоянные работы:
public class CleverMoneyMakingBusinessService implements MoneyMakingBusinessService {
private MoneyRepository moneyRepository;
public void makeMoney( MoneyRoll money ) {
moneyRepository.make( money );
}
public MoneyRoll withdrawMoney( Long moneyRollId ) {
return moneyRepository.find( moneyRollId );
}
public void setMoneyRepository( MoneyRepository moneyRepository ) {
this.moneyRepository = moneyRepository;
}
}
Принимая во внимание, что репозиторий / DAO может выглядеть следующим образом (обратите внимание, что он не использует HibernateTemplate
, поскольку @Repository
выполняет все переводы исключений, а Hibernate SessionFactory
может и должен использоваться напрямую) :
@Repository
public class HibernateMoneyRepository implements MoneyRepository {
private SessionFactory sessionFactory;
public MoneyRoll find( Long rollId ) {
MoneyRoll moneyRoll = null;
Query query = getSession().getNamedQuery("find.moneyroll.by.id");
query.setParameter( "id", rollId );
List<MoneyRoll> moneyList = query.list();
if ( moneyList.size() != 0 ) {
moneyRoll = ( MoneyRoll )query.list().get( 0 );
}
return moneyRoll;
}
public void make( MoneyRoll moneyRoll ) {
getSession().save( moneyRoll );
}
public void takeOut( MoneyRoll moneyRoll ) {
getSession().delete( moneyRoll );
}
public void update(MoneyRoll money) {
Query query = getSession().getNamedQuery("update.moneyroll");
query.setParameter( "id", money.getId() );
query.setParameter( "amount", money.getAmount() );
query.setParameter( "currency", money.getCurrency() );
query.executeUpdate();
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Взгляните на проект по зарабатыванию денег , который я собрал в качестве примера, чтобы увидеть, как все это собирается и исполняется.