1、刷新模式的问题,FlushMode.MANUAL
Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
org.springframework.orm.hibernate5.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1165)
org.springframework.orm.hibernate5.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:643)
org.springframework.orm.hibernate5.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:640)
org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:359)
org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:326)
org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:640)
这里主要的是因为使用的是getCurrentSession获取的Session对象,在整合到Srping中的时候会遇到。FlushMode.MANUAL只读,所以进行增删改的时候就会抛出该异常。
解决方案:亲测靠谱
OpenSessionInViewFilter这个过滤器的源码:
protected Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
try {
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
return session;
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException(“Could not open Hibernate Session”, ex);
}
}
就是会将Session的刷新模式设置,这样就导致了新增、修改、删除时无法操作。
我们只需要重写该过滤器的openSession方法覆盖原来的方法即可
SetSessionFlushModel类
public class SetSessionFlushModel extends OpenSessionInViewFilter{
//覆盖父类中创建Session的方式,因为父类总创建Session,默认设置Session的setFlushMode为FlushMode.MANUAL就是只读模式
@Override
protected Session openSession(SessionFactory factory) throws DataAccessResourceFailureException {
// TODO Auto-generated method stub
Session session=factory.openSession();
session.setFlushMode(FlushModeType.AUTO);//设置刷新模式也就是什么时候将sql语句发送到数据库
return session;
}
}
然后在web.xml中进行过滤器的注册
再次运行我们的整合项目就可以了。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>My_SH</display-name>
<!--开启Spring的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置Spring的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置过滤器,解决session的flushMode的问题 -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.qf.web.filter.SetSessionFlushModel</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
2、事物未开启
getHibernateFlushMode is not valid without active transaction; nested exception is org.hibernate.HibernateException: getHibernateFlushMode is not valid without active transaction
rg.springframework.orm.hibernate5.HibernateSystemException: getHibernateFlushMode is not valid without active transaction; nested exception is org.hibernate.HibernateException: getHibernateFlushMode is not valid without active transaction
org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:296)
org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:362)
org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:326)
org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:640)
明明配置了事物,而且aop切面也没有什么问题,可是就是出现这种问题。原来罪魁祸首是
<prop key="hibernate.current_session_context_class">thread</prop>
这个搞的鬼,在Hibernate的确是这样配置的,目的是使用getCurrentSession.
可是在整合的时候,必须使用这个:
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</prop>
这样就好了。