关于Could not obtain transaction-synchronized Session for current thread 这个异常。
Could not obtain transaction-synchronized Session for current thread 这个异常之前非常让我头大。对于网上的各种说法都试了一下反正都不行。现在终于使这个异常消失了,但是现在(2017-7-8)还搞不清真正的原因。
这是异常的一部分。
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:988)
at com.zcd.ssh.dao.impl.BaseDao.getSession(BaseDao.java:14)
at com.zcd.ssh.dao.impl.DepartmentDaoImpl.save(DepartmentDaoImpl.java:16)
at com.zcd.ssh.test.SSHTest.testCRUD(SSHTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
现在先把我猜测的原因写下来,之后如果有新发现再来这里更新这篇文章。
一、当我整合 Spring 和 Hibernate 的时候先配置好 IOC 容器的 applicationContext.xml 文件中的部分内容,创建实体类 Employee 类和Department类, Dao层的EmployeeDao类和DepartmentDao类等等,进行JUnit测试。
==========================================================================
applicationContext.xml 文件的部分内容。连接数据库需要的 db.properties 文件就不贴出来。
<!-- 扫描包 -->
<context:component-scan base-package="com.zcd.ssh"></context:component-scan> <!-- 导入资源文件: db.properties文件 -->
<context:property-placeholder location="classpath:db.properties"/> <!-- 配置数据源,使用c3p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<property name="minPoolSize" value="${minPoolSize}"></property>
<property name="initialPoolSize" value="${initialPoolSize}"></property>
<property name="acquireIncrement" value="${acquireIncrement}"></property>
</bean> <!-- 配置SessionFactory 使用LocalSessionFactoryBean-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
<property name="mappingLocations" value="classpath:com/zcd/ssh/beans/*.hbm.xml"></property>
</bean>
==========================================================================
BaseDao类
/**
* 其他Dao类通用的方法。
* @author ZCD
*/
@Repository
public class BaseDao
{
@Autowired
private SessionFactory sessionFactory; /**
* 获取当前线程的Session。
* @return 返回当前线程的Session
*/
public Session getSession()
{
return sessionFactory.getCurrentSession();
}
}
==========================================================================
DepartmentDaoImpl类。
@Repository
public class DepartmentDaoImpl extends BaseDao implements DepartmentDao
{
@Override
public boolean save(Department department)
{
getSession().save(department); return true;//暂时返回true。
} @Override
public boolean delete(Integer id)
{
String hql = "DELETE FROM Department d WHERE d.id = ?"; getSession().createQuery(hql).setInteger(0, id); return true; //暂时返回true。
} @Override
public Department getDepartment(Integer id)
{
String hql = "FROM Department d WHERE d.id = ?"; Department department = (Department)getSession().createQuery(hql).setInteger(0, id); return department;
} @Override
public ArrayList<Department> getDepartments()
{
String hql = "FROM Department d"; ArrayList<Department> departments = (ArrayList<Department>)getSession().createQuery(hql).list(); return departments;
}
}
==========================================================================
@Repository
public class EmployeeDaoImpl extends BaseDao implements EmployeeDao
{ @Override
public boolean save(Employee employee)
{
getSession().save(employee); return true; //暂时返回true。
} @Override
public boolean delete(Integer id)
{
String hql = "DELETE FROM Employee e WHERE e.id = id"; getSession().createQuery(hql).setInteger(0, id).executeUpdate(); return true; //暂时返回true。
} @Override
public Employee getEmployee(Integer id)
{
String hql = "FROM Employee e WHERE e.id = ?"; Employee employee = (Employee) getSession().createQuery(hql).setInteger(0, id).uniqueResult(); return employee;
} @Override
public ArrayList<Employee> getEmployees()
{
String hql = "FROM Employee e"; ArrayList<Employee> employees = (ArrayList<Employee>) getSession().createQuery(hql).list(); return employees;
}
}
==========================================================================
进行单元测试时出现了异常。
public class SSHTest
{
private ApplicationContext ac;
private DataSource dataSource;private DepartmentDao departmentDao; {
ac = new ClassPathXmlApplicationContext("applicationContext.xml"); dataSource = ac.getBean(DataSource.class); departmentDao = ac.getBean(DepartmentDao.class);
} /*
* 测试是否能正常连接数据库,并且自动生成数据表。
*/
@Test
public void testConnection() throws SQLException
{
System.out.println(dataSource.getConnection().getClass().getName());
} /*
* 测试DepartmentDao类的增删改查功能。
* 当我测试一下保存一个部门对象时,就抛出了上述异常。
*/
@Test
public void testCRUD()
{
departmentDao.save(new Department(102, "财务部"));
}
}
==========================================================================
二、当我完善了我的 applicationContext.xml文件,并且创建Service层等等后,在进行上述单元测试时就能够正常执行操作。
在applicationContext.xml中添加了一下内容。
<!-- 使用Spring的声明式事务 --> <!-- 1、配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean> <!-- 2、配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice> <!-- 3、配置事务切点,并且将事务切点和事务通知关联起来。 -->
<aop:config>
<aop:pointcut expression="execution(* com.zcd.ssh.service.*.*(..))" id="txPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
==========================================================================
Service层的 OperateDepartmentService 类其实和Dao层的 DepartmentDao 类基本没区别。为了使这个项目的结构完整才添加了。
@Service
public class OperateDepartmentService
{
@Autowired
private DepartmentDao departmentDao; /**
* 保存部门对象。保存新建的部门或修改的部门对象。
* @param department 被保存的部门对象。
* @return 保存成功返回true,否则返回false。
*/
public boolean save(Department department)
{
boolean success = departmentDao.save(department); return success;
} /**
* 根据部门id删除部门对象。
* @param id 部门id.
* @return 删除成功返回true,否则返回false。
*/
public boolean delete(Integer id)
{
boolean success = departmentDao.delete(id); return success;
} /**
* 根据部门id查询部门对象。
* @param id 部门id。
* @return 返回一个部门对象。
*/
public Department getDepartment(Integer id)
{
Department department = departmentDao.getDepartment(id); return department;
} /**
* 查询所有部门对象。
* @return 返回所有部门对象。
*/
public ArrayList<Department> getDepartments()
{
ArrayList<Department> departments = departmentDao.getDepartments(); return departments;
}
}
==========================================================================
再次进行单元测试就能正常进行操作了。
@Test
public void testCRUD()
{
operateDepartmentService.save(new Department(101, "销售部"));
}
==========================================================================
新发现
==========================================================================
三、在 Spring 整合 Hibernate 后进行单元测试什么都没有出现问题。但是加入SpringMVC后感觉自己写的代码都没有错误。
==========================================================================
下面是SpringMVC的配置文件。
<!-- 扫描包 -->
<context:component-scan base-package="com.zcd.ssh" use-default-filters="true">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan> <!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean> <mvc:default-servlet-handler/> <mvc:annotation-driven></mvc:annotation-driven>
==========================================================================
web.xml 文件。
<!-- 配置contextConfigLocation -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param> <!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<!-- 拦截所有请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping> <filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<!-- 拦截所有请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
==========================================================================
jsp页面的请求。
<a href="employees">所有员工</a>
==========================================================================
@Controller
public class EmployeeController
{
@Autowired
private OperateEmployeeService employeeService; @RequestMapping(value="/employees", method=RequestMethod.GET)
public String list(Map<String, Object> map)
{
ArrayList<Employee> employees = employeeService.getEmployees();
map.put("employees", employees); return "employees";
}
}
我以上的代码感觉都没有问题。但却总是抛出异常。真正的原因就是加入SpringMVC后,我又配置了一个SpringMVC的IOC容器文件:springmvc.xml 。此时有两个IOC容器的配置文件。一个是SpringMVC的,一个是Spring的。这两个文件都对bean进行了自动扫描。
springmvc.xml 文件扫描的代码如下。这里是只扫描@Controller 注解的类。
<!-- 扫描包 -->
<context:component-scan base-package="com.zcd.ssh">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
applicationContext.xml 文件的扫描的代码如下。这是除了@Controller 注解的类都扫描。看似很完美。刚好所有的bean都扫描完了,每个bean都只会创建一个实例。
<!-- 扫描包 -->
<context:component-scan base-package="com.zcd.ssh">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
但是真的只会创建一个实例吗?在每个bean的无参构造器都打印一句话,然后运行程序。发现,除了 @Controller 注解的类,其他的类都创建了两个实例。也就是说我们在Spring IOC容器里声明的SessionFactory这个bean也创建了两个实例。问题可能就是因为创建了两个SessionFactory的实例,所以不能获取当前线程的Session。
此时只要在springmvc.xml扫描<context:component-scan>节点加上use-default-filters="false" 这个属性。就可以了。因为不加这个它还是会使用默认的过滤器。还是会扫描到其他的Spring IOC容器中的bean。具体修改如下
<!-- 扫描包 --><!-- 加上 use=default-filters="false" 这个属性就可以了-->
<context:component-scan base-package="com.zcd.ssh" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
====================================================================
2017-09-25
四、总结
观察了一下,会出现上述异常原因:
一、因为没有通过Service层来访问数据库,更准确的说没有使用声明式事务。因为Hibernate 使用Spring的声明式事务,事务的切点是在Service层里的所有类的所有方法。所以如果直接通过Dao层操作数据库就相当于没有使用事务,如果事务切点配置错误也有可能出现异常。还有,如果一个业务层(Service层)中的某一个类已经使用@Service注解,但是事务切点没有作用在这个类的方法上,那么也就相当于没有使用事务,也会出现上述异常。
以上猜测不知道正不正确,反正异常消失了。^o^
关于Could not obtain transaction-synchronized Session for current thread 这个异常。的更多相关文章
- Hibernate4中使用getCurrentSession报Could not obtain transaction-synchronized Session for current thread
架个spring4+hibernate4的demo,dao层直接注入的sessionFactory,然后用getCurrentSession方法获取session,然后问题来了,直接报错: Could ...
- 关于Hibernate Could not obtain transaction-synchronized Session for current thread
转载自 http://blog.csdn.net/flyjiangs/article/details/51537381 最近几年一直再搞android,最近闲下来了,顺便玩一下web. 整了个最新版本 ...
- 记一次bug思考过程:HibernateException: Could not obtain transaction-synchronized Session for current thread
场景:把从客户端提交的任务放到线程池执行 异常:HibernateException: Could not obtain transaction-synchronized Session for cu ...
- Could not obtain transaction-synchronized Session for current thread原因及解决方案
在开发中,碰到到了Could not obtain transaction-synchronized Session for current thread异常,因此特意记录下. 一.问 ...
- org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
spring与hibernate整合报错 org.hibernate.HibernateException: Could not obtain transaction-synchronized Ses ...
- Hibernate Could not obtain transaction-synchronized Session for current thread问题处理
项目通过Hibernate查询时报出如下错误: Hibernate Could not obtain transaction-synchronized Session for current thre ...
- Could not obtain transaction-synchronized Session for current thread 错误的解决方法!
BsTable bsTable = new BsTable(); // String time = request.getParameter("date"); String tim ...
- 关于spring3中No Session found for current thread!and Transaction的配置和管理(转)
今天我是特别的郁闷,本来项目做到一半,以前都好好的,结果下午就出现问题,苦逼的到现在才解决.它出现问题的时候都一声不坑, ,(天啦,现在才发现CSDN啥时候把QQ表情给整过来了)就在注册用户的时候,咦 ...
- Spring+Hibernate4 Junit 报错No Session found for current thread
论坛上有另外一篇更全面的帖子,jinnianshilongnian写的:http://www.iteye.com/topic/1120924 本文的环境是: spring-framework-3.1 ...
随机推荐
- 网络协议-HTTPS
转载:http://www.renfed.com/2017/02/03/https/ 一.解决问题 HTTPS解决的是中间人攻击 公网:域名解析--IP:所以中间站点抢答返回错误IP 局域网:路由器找 ...
- 公司管理系列--80% of Your Culture is Your Founder(FaceBook)
80% of Your Culture is Your Founder When Molly Graham joined Facebook in 2008, the company still ...
- 常用工具说明--Git和GitHub简明教程
一.Git的主要功能:版本控制 版本:想想你平时用的软件,在软件升级之后,你用的就是新版本的软件.你应该见过这样的版本号:v2.0 或者 1511(表示发布时为15年11月),如下图:那么如果你修改并 ...
- AngularJS中的动画实现
AngularJS 动画 AngularJS 提供了动画效果,可以配合 CSS 使用. AngularJS 使用动画需要引入 angular-animate.min.js 库. <script ...
- spring整合springmvc和mybatis
1.spring 1.1 jar包 1.2 spring基本配置,包扫描注解 <!-- 自动扫描 --> <context:component-scan base-package=& ...
- golang的xml、json解析
xml golang的xml处理主要应用Unmarshal.Marshal方法实现,解析一个xml到struct如下,首先是xml文件: <?xml version="1.0" ...
- [android] android通信协议
1.数据区分 手机端:常量存储 服务器端:数据库建表存储 2.数据来源 android,ios,pc,wap 3.数据采集,数据挖掘 IMEI:设备编号 IMSI:SIM卡编号 4.数据加密 4.1R ...
- 七、cent OS下干净卸载mysql
使用以下命令查看当前安装mysql的情况rpm -qa | grep -i mysql显示之前安装的东西,示例:MySQL-client-5.5.25a-1.rhel5MySQL-server-5.5 ...
- java swing画图片爱心
第一次用swing做一个可视化程序,写第一篇随笔,有写的不好的地方请多多见谅.上个星期三在网上看到一个画爱心的软件,就想着自己用java也实现一个程序,画爱心用到的数学函数知识在网上百度的,不是本人原 ...
- Android-多线程Handler
http://www.cnblogs.com/plokmju/p/android_Handler.html android不允许在主线程里做耗时操作,如网络操作,以此来避免ANR ANR(Applic ...