Announcement Announcement Module
Collapse
No announcement yet.
@Transactional and inherited methods Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @Transactional and inherited methods

    I'm working with two databases (MySQL and HSQL), so I need two transaction managers in my Spring app. Please have a look at this code:

    Code:
    public abstract class ClientService implements IClientService{
    public void doSomething(){
    }
    }
    
    public interface IClientService{
    void doSomething();
    }
    
    @Transactional("txManagerHSQL")
    public class ClientServiceHSQL extends ClientService{
    }
    
    @Transactional("txManagerMySQL")
    public class ClientServiceMySQL extends ClientService{
    }
    I want ClientServiceHSQL and ClientServiceMySQL to perform doSomething() on different databases, but I'm getting "org.hibernate.HibernateException: No Session found for current thread" exception. It seems that @Transactional annotation doesn't affect inherited methods. At this time I have to implement doSomething() in each @Transactional class to be able to call doSomething() with success, but for me this is not nice. Is there any way to make inherited methods also transactional?

  • #2
    I have the same or similar issue. I use spring-data-jpa for data access.
    Exception I get: org.springframework.dao.InvalidDataAccessApiUsageE xception: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
    If I put @Transactional("txManager1") on RepositoryBase - code works, the problem is Repository2 will have txManager1 in this case.

    Questions:
    1. What is wrong with my code?
    2. How to fix the issue in a nice way?


    Code:
    Code:
    @Transactional("txManager1")
    public interface Repository1 extends RepositoryBase {
    }
    
    @Transactional("txManager2")
    public interface Repository2 extends RepositoryBase {
    }
    
    @NoRepositoryBean
    public interface RepositoryBase extends JpaRepository<MyEntity, Long> {
        @Query("update MyEntity s set s.balance = :amount where s.id = :id")
        @Modifying
        int update(@Param("id") Long id, @Param("amount") long amount);
    }
    
    @Component
    public class MyImpl {
        @Inject
        private Repository1 repository;
    
    	public doUpdate(Long id, long amount) {
    		repository.update(id, amount);
    	}
    }
    p.s. 0 replies - is the answer too obvious or too complicated?

    ty
    Last edited by igorewka; Apr 8th, 2013, 04:34 AM.

    Comment


    • #3
      Workaround to the issue:

      Code:
      <tx:advice id="db1TxAdvice" transaction-manager="txManager1">
      	<tx:attributes>
      		<tx:method name="*"/>
      	</tx:attributes>
      </tx:advice>
      
      <tx:advice id="db2TxAdvice" transaction-manager="txManager2">
      	<tx:attributes>
      		<tx:method name="*"/>
      	</tx:attributes>
      </tx:advice>
      
      <aop:config>
      	<aop:pointcut id="repository1Pointcut"
      				  expression="execution(* com.my.Repository1.*(..))"/>
      	<aop:pointcut id="repository2Pointcut"
      				  expression="execution(* com.my.Repository2.*(..))"/>
      				  
      	<aop:advisor pointcut-ref="repository1Pointcut" advice-ref="db1TxAdvice"/>
      	<aop:advisor pointcut-ref="repository2Pointcut" advice-ref="db2TxAdvice"/>
      </aop:config>

      Comment

      Working...
      X