2014-09-25 87 views
4

我試圖使用春季開機和休眠。 它在我使用存儲庫時效果很好,但我試圖獲得一個Hibernate會話來創建一個DAO,而這個DAO並不是事務的一部分。春季開機和休眠,使用交易

這是測試代碼:

Application.java

@Configuration 
@ComponentScan 
@EnableAutoConfiguration 
@EnableTransactionManagement 
public class Application implements CommandLineRunner { 

    @Autowired 
    private UserBusiness userBusiness; 

    @Autowired 
    @Bean(name="sessionFactory") 
    public SessionFactory sessionFactory(HibernateEntityManagerFactory factory) { 
     return factory.getSessionFactory(); 
    }  

    @Override 
    public void run(String... arg0) throws Exception { 
     try { 
      userBusiness.createAdminUsers(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     System.out.println(userBusiness.listAll()); 
    } 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args).close(); 
    } 
} 

UserBusinessImpl.java:

@Service 
public class UserBusinessImpl implements UserBusiness { 

    @Autowired 
    private UserRepository userRepository; 

    @Autowired 
    private UserDao userDao; 

    @Transactional(rollbackFor=Exception.class) 
    public void createAdminUsers() throws Exception { 
     userRepository.save(new User("User1", "u1", "123")); 
     userRepository.save(new User("User2", "u2", "123")); 
     userDao.test(); 
     throw new Exception("Rollback"); 
    } 

    public List<User> listAll() { 
     return userRepository.findAll(); 
    } 
} 

UserRepository.java

public interface UserRepository extends JpaRepository<User, Long> { 
} 

userDAO的:

@Repository 
public class UserDao { 

    @Autowired 
    private SessionFactory sessionFactory; 

    public void teste() { 
     //current session does not exists and throws org.hibernate.HibernateException: No CurrentSessionContext configured! 
//  sessionFactory.getCurrentSession().save(new User("testDao", "dao", "123")); 
     sessionFactory.openSession().save(new User("testDao", "dao", "123")); 
    } 
} 

當我嘗試getCurrentSession()它會引發一個錯誤。 和openSession()從我的事務中分離出來,所以當Business拋出異常時Dao保存沒有回滾。另外兩個刀片被回滾。

在DAO中獲取currentSession的正確方法是什麼?

更新: 如果我做一個sessionFactory.openSession()它不會給出任何例外,但它不是交易的一部分。

如果我嘗試使用sessionFactory.getCurrentSession()這是堆棧跟蹤:

org.hibernate.HibernateException: No CurrentSessionContext configured! 
2014-09-26 11:00:28.488 TRACE 20938 --- [   main] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.data.jpa.repository.su[email protected]ff80080] for key [public abstract java.util.List org.springframework.data.jpa.repository.JpaRepository.findAll()] to thread [main] 
2014-09-26 11:00:28.488 DEBUG 20938 --- [   main] o.s.orm.jpa.JpaTransactionManager  : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; '' 
2014-09-26 11:00:28.489 DEBUG 20938 --- [   main] o.s.orm.jpa.JpaTransactionManager  : Opened new EntityManager [[email protected]] for JPA transaction 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1010) 
    at org.sparta.hibernatetest.UserDao.teste(UserDao.java:35) 
    at org.sparta.hibernatetest.business.UserBusinessImpl.createAdminUsers(UserBusinessImpl.java:44) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
    at com.sun.proxy.$Proxy48.createAdminUsers(Unknown Source) 
    at org.sparta.hibernatetest.Application.run(Application.java:33) 
    at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:677) 
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:695) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941) 
    at org.sparta.hibernatetest.Application.main(Application.java:42) 
+0

你得到了什麼異常,發佈整個堆棧跟蹤 – Chaitanya 2014-09-26 03:44:47

+0

'getCurrentSession()'只能在沒有它的事務邊界內工作,否則它將無法工作。所以基本上讓你的方法成爲交易的一部分。但是我想知道爲什麼你已經有一個可以使用JPA進行保存的存儲庫,那麼爲什麼你甚至需要一個普通的'SessionFactory'。 – 2014-09-26 05:55:10

+0

我不需要使用DAO進行保存。作爲一個例子,我把這個保存在DAO中。但我想要的是能夠編寫我的DAO,直接訪問Hibernate,使我能夠編寫我自己的Criterias,並且這由@Transactional管理 – 2014-09-26 15:05:50

回答

6

試試這個:

@Repository 
public class UserDao { 

    @PersistenceContext 
    EntityManager entityManager; 

    protected Session getCurrentSession() { 
     return entityManager.unwrap(Session.class); 
    } 

    public void test() { 
     Session session = getCurrentSession(); 
     session().save(new User("testDao", "dao", "123")); 
    } 
} 
+0

它的工作,謝謝。 – 2015-03-21 11:46:13

+0

也爲我工作,歡呼聲。 – jax 2015-04-29 07:09:54

1

你可以使用

entityManager.persist(new User("testDao", "dao", "123"))

(及其他EntityManager方法)而不是直接使用Hibernate Session。