Java SpringMVC 和 Hibernate:CannotCreateTransactionException:无法打开 Hibernate Session 进行事务;
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20261404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SpringMVC & Hibernate : CannotCreateTransactionException: Could not open Hibernate Session for transaction;
提问by Carlos Landeras
I'm trying to set up and Spring MVC + Hibernateproject but it's driving me nuts. I would also take in account suggestions to order the xml config files.
我正在尝试设置Spring MVC + Hibernate项目,但它让我发疯。我还会考虑订购 xml 配置文件的建议。
I have the following files:
我有以下文件:
web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <tx:annotation-driven/> <context:component-scan base-package="es.landesoft.mvctesting" /> <context:component-scan base-package="es.landesoft.mvctesting.service" /> <context:component-scan base-package="es.landesoft.mvctesting.dao" /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" /> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".jsp" /> </beans:bean> <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with username root and blank password. Change below if it's not the case --> <beans:bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <beans:property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> <beans:property name="url" value="jdbc:sqlserver://127.0.0.1:1433;databaseName=MyHome;instanceName=SQLEXPRESS;"/> <beans:property name="username" value="sa"/> <beans:property name="password" value="sarednal1"/> <beans:property name="validationQuery" value="SELECT 1"/> </beans:bean> <beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <beans:property name="dataSource" ref="myDataSource"/> <beans:property name="configLocation"> <beans:value>classpath:hibernate.cfg.xml</beans:value> </beans:property> <beans:property name="packagesToScan" value="es.landesoft.mvctesting" /> <beans:property name="hibernateProperties"> <beans:props> <beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</beans:prop> <beans:prop key="hibernate.show_sql">true</beans:prop> </beans:props> </beans:property> </beans:bean> <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <beans:property name="dataSource" ref="myDataSource" /> <beans:property name="sessionFactory" ref="sessionFactory" /> </beans:bean>
PersonController.java
package es.landesoft.mvctesting; import java.util.List; import java.util.Locale; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import es.landesoft.mvctesting.JavaBeans.Person; import es.landesoft.mvctesting.service.PersonService; /** * Handles requests for the application home page. */ @Controller public class PersonController { //private static final Logger logger = LoggerFactory.getLogger(PersonController.class); @Autowired private PersonService personService; @RequestMapping(value = "/person/json", method = RequestMethod.GET, produces="application/json") @ResponseBody public List<Person> getPersonJson() { return personService.listPerson(); } }
PersonDAO.java
package es.landesoft.mvctesting.dao;
import java.util.List; import es.landesoft.mvctesting.JavaBeans.Person; public interface PersonDAO { public void addContact(Person person); public List<Person> listPersons(); public void removePerson(Integer id); }
PersonDaoClass.java
package es.landesoft.mvctesting.dao; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import es.landesoft.mvctesting.JavaBeans.Person; @Repository public class PersonDaoClass implements PersonDAO { @Autowired private SessionFactory sessionFactory; @Transactional @Override public void addContact(Person person) { sessionFactory.getCurrentSession().save(person); } @Transactional @SuppressWarnings("unchecked") public List<Person> listPersons() { return sessionFactory.getCurrentSession() .createQuery("From Person").list(); } @Transactional public void removePerson(Integer id) { Person person = (Person) sessionFactory.getCurrentSession().load(Person.class, id); if (person != null) { sessionFactory.getCurrentSession().delete(person); } } }
PersonService.java
package es.landesoft.mvctesting.service; import java.util.List; import es.landesoft.mvctesting.JavaBeans.Person; public interface PersonService { public void addContact(Person person); public List<Person> listPerson(); public void removePerson(Integer id); }
PersonService.java
package es.landesoft.mvctesting.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import es.landesoft.mvctesting.JavaBeans.Person; import es.landesoft.mvctesting.dao.PersonDAO; @Service public class PersonServiceClass implements PersonService { @Autowired private PersonDAO personDAO; @Transactional public void addContact(Person person) { personDAO.addContact(person); } @Transactional public List<Person> listPerson() { return personDAO.listPersons(); } @Transactional public void removePerson(Integer id) { personDAO.removePerson(id); } }
web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <tx:annotation-driven/> <context:component-scan base-package="es.landesoft.mvctesting" /> <context:component-scan base-package="es.landesoft.mvctesting.service" /> <context:component-scan base-package="es.landesoft.mvctesting.dao" /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" /> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".jsp" /> </beans:bean> <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with username root and blank password. Change below if it's not the case --> <beans:bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <beans:property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> <beans:property name="url" value="jdbc:sqlserver://127.0.0.1:1433;databaseName=MyHome;instanceName=SQLEXPRESS;"/> <beans:property name="username" value="sa"/> <beans:property name="password" value="sarednal1"/> <beans:property name="validationQuery" value="SELECT 1"/> </beans:bean> <beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <beans:property name="dataSource" ref="myDataSource"/> <beans:property name="configLocation"> <beans:value>classpath:hibernate.cfg.xml</beans:value> </beans:property> <beans:property name="packagesToScan" value="es.landesoft.mvctesting" /> <beans:property name="hibernateProperties"> <beans:props> <beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</beans:prop> <beans:prop key="hibernate.show_sql">true</beans:prop> </beans:props> </beans:property> </beans:bean> <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <beans:property name="dataSource" ref="myDataSource" /> <beans:property name="sessionFactory" ref="sessionFactory" /> </beans:bean>
PersonController.java
package es.landesoft.mvctesting; import java.util.List; import java.util.Locale; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import es.landesoft.mvctesting.JavaBeans.Person; import es.landesoft.mvctesting.service.PersonService; /** * Handles requests for the application home page. */ @Controller public class PersonController { //private static final Logger logger = LoggerFactory.getLogger(PersonController.class); @Autowired private PersonService personService; @RequestMapping(value = "/person/json", method = RequestMethod.GET, produces="application/json") @ResponseBody public List<Person> getPersonJson() { return personService.listPerson(); } }
PersonDAO.java
包 es.landesoft.mvctesting.dao;
import java.util.List; import es.landesoft.mvctesting.JavaBeans.Person; public interface PersonDAO { public void addContact(Person person); public List<Person> listPersons(); public void removePerson(Integer id); }
PersonDaoClass.java
package es.landesoft.mvctesting.dao; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import es.landesoft.mvctesting.JavaBeans.Person; @Repository public class PersonDaoClass implements PersonDAO { @Autowired private SessionFactory sessionFactory; @Transactional @Override public void addContact(Person person) { sessionFactory.getCurrentSession().save(person); } @Transactional @SuppressWarnings("unchecked") public List<Person> listPersons() { return sessionFactory.getCurrentSession() .createQuery("From Person").list(); } @Transactional public void removePerson(Integer id) { Person person = (Person) sessionFactory.getCurrentSession().load(Person.class, id); if (person != null) { sessionFactory.getCurrentSession().delete(person); } } }
PersonService.java
package es.landesoft.mvctesting.service; import java.util.List; import es.landesoft.mvctesting.JavaBeans.Person; public interface PersonService { public void addContact(Person person); public List<Person> listPerson(); public void removePerson(Integer id); }
PersonService.java
package es.landesoft.mvctesting.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import es.landesoft.mvctesting.JavaBeans.Person; import es.landesoft.mvctesting.dao.PersonDAO; @Service public class PersonServiceClass implements PersonService { @Autowired private PersonDAO personDAO; @Transactional public void addContact(Person person) { personDAO.addContact(person); } @Transactional public List<Person> listPerson() { return personDAO.listPersons(); } @Transactional public void removePerson(Integer id) { personDAO.removePerson(id); } }
I am getting this stacktrace error:
我收到此堆栈跟踪错误:
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/mvctesting] threw exception [Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.UnsupportedOperationException] with root cause
java.lang.UnsupportedOperationException
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:136)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:447)
at org.hibernate.service.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:141)
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:214)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157)
at org.hibernate.internal.SessionImpl.connection(SessionImpl.java:550)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:354)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy30.listPerson(Unknown Source)
at es.landesoft.mvctesting.PersonController.getPersonJson(PersonController.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
In addition, I would be glad if someone can give me some tips to help me organize the xml config files. I am .NET developer and all this maven + xml configurations are something new for me.
另外,如果有人能给我一些提示来帮助我组织 xml 配置文件,我会很高兴。我是 .NET 开发人员,所有这些 maven + xml 配置对我来说都是新的。
Thanks
谢谢
采纳答案by Carlos Landeras
My solution was changing the bean class in Datasource from:
我的解决方案是从以下位置更改数据源中的 bean 类:
<beans:bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
to the spring Framework class:
到 spring 框架类:
<beans:bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
回答by Augusto
I have the feeling you're using a version of commons-dbcp which is not compatible with the version of hibernate you're using... or that you have 2 versions of the commons-dbcp in your classpath.
我感觉您使用的 commons-dbcp 版本与您使用的 hibernate 版本不兼容……或者您的类路径中有 2 个版本的 commons-dbcp。
Why?
为什么?
Looking at the code from org.apache.commons.dbcp.PoolingDataSource, you can see that the method getConnetion(String uname, String passwd)
only throws an exception (in the version in the link, the line is 127 rather than 136).
查看org.apache.commons.dbcp.PoolingDataSource中的代码,可以看到该方法getConnetion(String uname, String passwd)
仅抛出异常(在链接中的版本中,该行是 127 而不是 136)。
And from org.apache.commons.dbcp.BasicDataSource, you can see that it never calls PoolingDataSource.getConnection(username, password)
从org.apache.commons.dbcp.BasicDataSource,你可以看到它从不调用PoolingDataSource.getConnection(username, password)
solution
解决方案
- Check that you have only one copy of the classes above in your classpath
- Try using commons-dbcp version 1.4
- 检查您的类路径中是否只有上述类的一个副本
- 尝试使用 commons-dbcp 1.4 版