求解:SessionFactory.getCurrentSession()的異常問題


做了一個Spring4和hibernate4的一個集成的例子,通過一個BasicHibernateDaoImpl.java構建基本的DAO處理類,代碼片段如下:

 1 package org.craig.dao.impl.base;
 2 
 3 import java.io.Serializable;
 4 import java.util.List;
 5 import org.craig.dao.iface.base.IBasicDao;
 6 import org.hibernate.Query;
 7 import org.hibernate.Session;
 8 import org.hibernate.SessionFactory;
 9 
10 public abstract class BasicHibernateDaoImpl<T> implements IBasicDao<T> {
11     // DAO組件進行持久化操作底層依賴的SessionFactory組件
12     private SessionFactory sessionFactory;
13     
14     // 根據ID加載實體
15     @Override
16     @SuppressWarnings("unchecked")
17     public T get(Class<T> entityClazz, Serializable id) {
18         Session session = getSessionFactory().getCurrentSession();
19         return (T) session.get(entityClazz, id);
20     }
21 
22     // 保存實體
23     @Override
24     public Serializable save(T entity) {
25         return getSessionFactory().getCurrentSession().save(entity);
26     }
27 
28     // 更新實體
29     @Override
30     public void update(T entity) {
31         getSessionFactory().getCurrentSession().saveOrUpdate(entity);
32     }
33 
34     // 刪除實體
35     @Override
36     public void delete(T entity) {
37         getSessionFactory().getCurrentSession().delete(entity);
38     }
39 
40     // 根據ID刪除實體
41     @Override
42     public void delete(Class<T> entityClazz, Serializable id) {
43         getSessionFactory()
44                 .getCurrentSession()
45                 .createQuery(
46                         "delete " + entityClazz.getSimpleName()
47                                 + " en where en.id = ?0").setParameter("0", id)
48                 .executeUpdate();
49     }
50 
51     // 獲取所有實體
52     @Override
53     public List<T> findAll(Class<T> entityClazz) {
54         return find("select en from " + entityClazz.getSimpleName() + " en");
55     }

 

在spring的配置中如下:

1 <bean id="abstractBasicDao" class="org.craig.dao.impl.base.BasicHibernateDaoImpl" abstract="true"
2         p:sessionFactory-ref="sessionFactory"/>    

接着是員工DAO:

 1 package org.craig.dao.impl;
 2 
 3 import org.craig.dao.iface.IEmployeeDao;
 4 import org.craig.dao.impl.base.BasicHibernateDaoImpl;
 5 import org.craig.pojo.Employee;
 6 
 7 public class EmployeeDaoImpl extends BasicHibernateDaoImpl<Employee> implements
 8         IEmployeeDao {
 9     
10 }

在spring中的配置如下:

1     <bean id="employeeDao" parent="abstractBasicDao" class="org.craig.dao.impl.EmployeeDaoImpl"/> 

 

接下來是spring和heibernate集成的配置

 1  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
 2         destroy-method="close"
 3         p:driverClass="com.mysql.jdbc.Driver"
 4         p:jdbcUrl="jdbc:mysql://localhost:3306/info"
 5         p:user="root"
 6         p:password="123456"
 7         p:maxPoolSize="40"
 8         p:minPoolSize="2"
 9         p:initialPoolSize="2"
10         p:maxIdleTime="30" />
11     <!-- 定義Hibernate的SessionFactory,SessionFactory需要依賴數據源,注入dataSource -->
12     <bean id="sessionFactory" 
13         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
14         p:dataSource-ref="dataSource">
15         <property name="annotatedClasses">
16            <list>
17                 <value>org.craig.pojo.Employee</value>
18             </list>
19           </property>
20         <!-- 定義Hibernate SessionFactory的屬性 -->
21         <property name="hibernateProperties">
22             <props>
23                 <!-- 指定Hibernate的連接方言 -->
24                 <prop key="hibernate.dialect">
25                     org.hibernate.dialect.MySQL5Dialect</prop>
26                 <prop key="hibernate.show_sql">true</prop>
27                 <prop key="hibernate.format_sql">true</prop>
28                   <prop key="hibernate.current_session_context_class">jta</prop>
29          
30                 <prop key="hibernate.connection.autocomit">false</prop>
31             
32             </props>
33         </property>
34     </bean>
35     
36     <!-- 增加事物 -->
37     <bean id="transactionManager" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
38         p:sessionFactory-ref="sessionFactory"/>
39     
40     <!-- AOP -->
41     <tx:advice id="txEmployee" transaction-manager="transactionManager">
42         <tx:attributes>
43             <tx:method name="*" propagation="REQUIRED" />
44         </tx:attributes>
45     </tx:advice>
46 
47     <aop:config>
48         <aop:advisor advice-ref="txEmployee" pointcut="execution(* org.craig.dao.impl.*.*(..))"/>
49     </aop:config>

在登錄的servlet代碼中有如下操作:

1 IEmployeeDao employeeDao = SpringUtil.getBean("employeeDao", IEmployeeDao.class);
2             Employee emp = employeeDao.get(Employee.class, name);

這里的employeeDao.get()方法會調用BasicHibernateDaoImpl.java中的get(),在Session session = getSessionFactory().getCurrentSession();這里會報錯誤。錯誤代碼如下:

 1 嚴重: Servlet.service() for servlet login threw exception
 2 org.hibernate.HibernateException: Unable to locate current JTA transaction
 3     at org.hibernate.context.internal.JTASessionContext.currentSession(JTASessionContext.java:92)
 4     at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
 5     at org.craig.dao.impl.base.BasicHibernateDaoImpl.get(BasicHibernateDaoImpl.java:18)
 6     at org.craig.manager.LoginServlet.doGet(LoginServlet.java:36)
 7     at org.craig.manager.LoginServlet.doPost(LoginServlet.java:49)
 8     at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
 9     at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
10     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
11     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
12     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
13     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
14     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
15     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
16     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
17     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
18     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
19     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
20     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
21     at java.lang.Thread.run(Thread.java:662)

但是如果用SessionFactory.openSession()替換掉getCurrentSession()是可以獲取到員工信息的。首先看了官方的說明,getCurrentSession()的前提是系統中擁有全局JTA事物,於是在tomcat中加入jotm的JTA事物管理,並且在啟動時,控制台顯示了JOTM TransactionManager的消息,並且在JSP頁面也能通過代碼獲得UerTransaction,此時的transactionmanager的配置如下:

1 <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
2         <property name="transactionSynchronizationRegistryName" value="java:comp/env/jta/jotmTransaction"></property>  
3         <property name="transactionManagerName" value="java:comp/UserTransaction" />  
4     </bean> 

但是依然報錯,錯誤信息跟上面的一樣。求高人指點!感謝了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM