2011-10-20 44 views
1

我試着用Spring創建一個小例子,休息,休眠。爲了讓會話在編組完成時打開,我在web.xml中添加了過濾器org.springframework.orm.hibernate3.support.OpenSessionInViewFilterJava - Spring,Hibernate:沒有會話綁定到線程

但是,現在我被嚴重卡住了,這可能是因爲我非常喜歡AOP。我面對會話沒有打開,當發送請求的問題:

20.10.2011 17:26:40 org.apache.catalina.core.StandardWrapperValve invoke 
SCHWERWIEGEND: Servlet.service() for servlet mvc-dispatcher threw exception 
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here 
    at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) 
    at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:685) 

我認爲這是在Spring + Hibernate with annotations: No Hibernate Session bound to thread描述,但我不明白它的工作同樣的問題。

web.xml中:

<web-app id="WebApp_ID" version="2.4" 
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 

<display-name>Spring Web MVC Application</display-name> 

<filter> 
    <filter-name>SessionPerRequest</filter-name> 
    <filter-class> 
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 
    </filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>SessionPerRequest</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

<servlet> 
    <servlet-name>mvc-dispatcher</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
<servlet-mapping> 
    <servlet-name>mvc-dispatcher</servlet-name> 
    <url-pattern>/rest/*</url-pattern> 
</servlet-mapping> 

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

</web-app> 

MVC-調度-servlet.xml中:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
xmlns:aop="http://www.springframework.org/schema/aop" 
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

<context:annotation-config /> 

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/test" /> 
    <property name="username" value="backend"/> 
    <property name="password" value="bUWGRysbbzYuXsbq" /> 
</bean> 
<tx:annotation-driven transaction-manager="transactionManager" /> 

<context:component-scan base-package="de.company.springtest" /> 

<mvc:annotation-driven /> 

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="configurationClass"> 
     <value>org.hibernate.cfg.AnnotationConfiguration</value> 
    </property> 
</bean> 


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

<tx:advice id="txAdvice"> 
    <tx:attributes> 
     <tx:method name="*" propagation="REQUIRED" /> 
    </tx:attributes> 
</tx:advice> 

<!-- <aop:config> --> 
<!--  <aop:advisor pointcut="execution(* de.company.springtest..*.*(..))" advice-ref="txAdvice" /> --> 
<!-- </aop:config> --> 


</beans> 

如果AOP部分未被註釋(這是在其他線程中的溶液)時,它拋出以下例外時,它是啓動:

INFO: Destroying singletons in org.s[email protected]46e06703: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,dataSource,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,JSONController,hibernateConfiguration,org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,sessionFactory,transactionManager,txAdvice,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0,sessionFactoryBean]; root of factory hierarchy 
20.10.2011 17:37:04 org.springframework.web.context.ContextLoader initWebApplicationContext 
SCHWERWIEGEND: Context initialization failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAdvisor': Cannot resolve reference to bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' while setting bean property 'transactionAttributeSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:452) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) 

其餘的控制器,但尚未被調用。因此,在函數的開始處的斷點不會被調用。

package de.company.springtest.controller; 

import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.hibernate.classic.Session; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 

import de.company.springtest.Item; 
import de.company.springtest.Order; 


@Controller 
@RequestMapping("/user") 
// localhost:8080/RESTfulTest/rest/user/abc 
public class JSONController { 

@Autowired 
private SessionFactory sessionFactory; 

@RequestMapping(method = RequestMethod.POST) 
public @ResponseBody 
Order postOrderInJSON() { 

    Session session = sessionFactory.getCurrentSession(); 
    Transaction transaction = session.beginTransaction(); 
    Order order = new Order(); 
    order.getItems().add(new Item()); 
    session.save(order); 
    // session.flush(); 
    transaction.commit(); 
    // session.close(); 
    return order; 

} 


@RequestMapping(value = "get/{id}", method = RequestMethod.GET) 
public @ResponseBody 
Order getUserInJSON(/* @PathVariable Long id */) { 

    Session session = sessionFactory.getCurrentSession(); 
    Transaction transaction = session.beginTransaction(); 
    Order order = new Order(); 
    order.getItems().add(new Item()); 
    session.save(order); 
    // session.flush(); 
    transaction.commit(); 
    // session.close(); 

    return order; 

} 

} 

HibernateConfiguration.java

package de.company.springtest; 

import java.util.Properties; 

import javax.sql.DataSource; 

import org.hibernate.dialect.MySQLDialect; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.orm.hibernate3.HibernateTransactionManager; 
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean; 

@Configuration 
public class HibernateConfiguration { 

@Value("#{dataSource}") 
private DataSource dataSource; 

@Bean 
public AnnotationSessionFactoryBean sessionFactoryBean() { 
    Properties props = new Properties(); 
    props.put("hibernate.dialect", MySQLDialect.class.getName()); 
    props.put("hibernate.current_session_context_class", "thread"); 
    props.put("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory"); 
    props.put("hibernate.format_sql", "true"); 

    AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean(); 
    bean.setAnnotatedClasses(new Class[]{Item.class, Order.class});  
    bean.setHibernateProperties(props); 
    bean.setDataSource(this.dataSource); 
    bean.setSchemaUpdate(true); 
    return bean; 
} 

@Bean 
public HibernateTransactionManager transactionManager() { 
    HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager(sessionFactoryBean().getObject()); 
    return hibernateTransactionManager; 
} 

} 

你有什麼提議在那裏我可以繼續我的搜索?

回答

0

nested exception is java.lang.NoClassDefFoundError: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException

您需要將aspectJ(aspectjweaver.jar)與您的應用程序一起部署。

如果你用maven比添加到您的POM:

<dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjweaver</artifactId> 
     <version>1.6.9</version> 
    </dependency> 
    <dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjrt</artifactId> 
     <version>1.6.9</version> 
    </dependency> 

如果你不使用Maven的,不是手工添加此兩瓶。

+0

謝謝!它最終非常簡單... –

2

取消部件註釋時的錯誤很可能是由類路徑中缺少aspectj引起的。

或者,您可以在DAO中使用@Transactional批註,或者在開始/結束事務適合您的應用程序設計的任何位置使用,因爲鏈接線程中的第一條評論指出了這一點。你需要讓這兩者中的任何一個啓動一個事務(或手動執行) - 僅僅配置一個事務管理器是不夠的。

+0

(+1)失蹤的AspectJ – Ralph

0

你整個配置/接線看起來很「原始」。這個異常的原因=>你的「服務層」沒有被執行,因此Hibernate抱怨。

不要把@Transactional放在DAO級別,因爲有人認爲=>它是錯誤的。您應該始終在服務層中的業務單位=>上進行交易。

看看example project(只是克隆它),它將Spring和Hibernate集成在一起。

實際上有一個HibernateSessionNotBoundToThreadIntegrationTest顯示此例外的原因。

這裏是通過Spring AOP的正確TX配置的example

<?xml version="1.0" encoding="UTF-8"?> 
<beans ...> 

    <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> 

</beans> 
相關問題