-->

Spring + Hibernate = “manual” transactions how-to

2020-07-28 03:30发布

问题:

My webapp (Spring3 + Hibernate3) always worked with services class-annotated with @Transactional and this configuration:

<tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory" />
    </bean>

Now... I'm on Google AppEngine. For some nasty reason I don't know yet, @Transactional does not work. It uses some class in javax.naming, which is not whitelisted. It ends up with:

Error creating bean with name 'mySessionFactory': Post-processing of the FactoryBean's object failed; nested exception is java.lang.SecurityException: Unable to get members for class org.hibernate.impl.SessionFactoryImpl

Please don't ask me why.... :-\

Using Spring's HibernateTemplate instead of my dao (which uses raw session factory) solved the problem, but I know it's a little obsolete.

So, I want to try using manual old style transactions. Questions:

  • where? I'd like to keep the transactions in the service layer.
  • how?

回答1:

SessionFactoryImpl dependency is not in Google App Engine whitelist. There is a number of Google hits discussing it.

As far as "what to do", you have options:

  • Depend on on another JPA provider

  • Don't use ORM at all, and go native with Spring's JdbcTemplate (my favorite)

  • I am not sure why you need to use a programmatic transaction management since Hibernate is the root of your problem, but if you just like to know how, here is a draft:

public class SomeService implements SomeInterface {

   private SomeDao thisDaoWrapsJdbcTemplate;
   private PlatformTransactionManager transactionManager;

   public void setTransactionManager( PlatformTransactionManager transactionManager ) {
      this.transactionManager = transactionManager;
   }

   public void doBusiness( Business: business ) {

      TransactionDefinition def = new DefaultTransactionDefinition();
      TransactionStatus status = transactionManager.getTransaction( def );

      try {

         // do business here
         Money money = Money.LOTS_OF
         ...
         // wire the money in..
         thisDaoWrapsJdbcTemplate.depositLotsOfMoney( money )

         transactionManager.commit( status );

      } catch ( DataAccessException dae ) {

         transactionManager.rollback( status );
         throw dae;
      }
      return;
   }