spring4.0 整合时持久化对象出错。

J2EE 码拜 10年前 (2015-04-09) 1200次浏览 0个评论

业务:通过spring管理数据源,实现用户注册。
问题描述:执行hibernateTemplate.save(obj);时报错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.

错误分析:1.可能是sessionFactory的注入有问题
                    2.如错误所示FlushMode设置错误。
小弟这个问题已经困扰2天了,有点想拿头撞墙,扒光头发的感觉!求大神帮忙!代码如下~
spring配置文件:applicationContext2.xml

<?xml version="1.0" encoding="UTF-8"?>
	<!-- 定义数据源的信息 -->

	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<property name="driverClass" value="com.mysql.jdbc.Driver" />
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/project" />
		<property name="user" value="root" />
		<property name="password" value="gg123" />
		<property name="maxPoolSize">
			<value>80</value>
		</property>
		<property name="minPoolSize">
			<value>1</value>
		</property>
		<property name="initialPoolSize">
			<value>1</value>
		</property>
		<property name="maxIdleTime">
			<value>20</value>
		</property>
	</bean>

	<!--定义Hibernate的SessionFactory -->
	<!-- SessionFactory使用的数据源为上面的数据源 -->
	<!-- 指定了Hibernate的映射文件和配置信息 -->

	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref ="dataSource" />
		<property name="mappingResources">
			<list>
				<value>com/easi/beans/User.hbm.xml</value>
			</list>
		</property>

		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="show_sql">true</prop>
				<prop key="hibernate.jdbc.batch_size">20</prop>
			</props>
		</property>
	</bean>


	<bean id="baseDao" class="com.easi.daoImpl.UserDao">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!--用户注册业务逻辑类 -->
	<bean id="userManager" class="com.easi.serviceImpl.UserManagerImpl">
		<property name="dao">
			<ref bean="baseDao" />
		</property>
	</bean>

	<!-- 用户注册的Action -->
	<bean id="regAction" class="com.easi.action.RegisterAction">
		<property name="userManager">
			<ref bean="userManager" />
		</property>
	</bean>

//hibernateTemplate注入
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
  		<property name="sessionFactory" ref="sessionFactory"></property>
  	</bean>

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

	</bean>
</beans>

Registeraction.java  由struts拦截的action处理类

public class RegisterAction extends ActionSupport {
	private static final long serialVersionUID = 1L;
//UserForm类是bean类,作用是接受前台的orm中的注册信息
	private UserForm user;
	public UserForm getUser() {
		return user;
	}
	public void setUser(UserForm user) {
		this.user = user;
	}
	 private UserManager userManager; 	 
	 public void setUserManager(UserManager userManager) {  
	        this.userManager = userManager;  
	    }  
	public String execute() {
		try {
			userManager.regUser(user);
			return SUCCESS;
		} catch (Exception e) {
			e.printStackTrace();
			return ERROR;
		}
	}
}

UserManagerImpl 业务实现类

public class UserManagerImpl implements UserManager {
	private BaseDao dao;  
	public void setDao(BaseDao dao) {  
        this.dao = dao;  
    }  
	@Override 
	public void regUser(UserForm userForm) {
		User user = new User();
//此方法将userForm中的值传给user
		BeanUtils.copyProperties(userForm,user);  
		System.out.println("接受到的用户名:"+user.getUserName());
		System.out.println("接受到的密码:"+user.getPassword());
		System.out.println("接受到的性别:"+user.getGender());
        dao.saveObject(user); 
	}
}

UserDao.java

public class UserDao implements BaseDao  {

        //让spring自己注入
	@Autowired
	private HibernateTemplate hibernateTemplate;


@Override
public void saveObject(Object obj) throws HibernateException {  
	//想设置session的FlushMode但是报错Could not obtain transaction-synchronized Session for current thread
	//Session session=hibernateTemplate.getSessionFactory().getCurrentSession();
	//session.setFlushMode(FlushMode.ALWAYS);
    //System.out.println("flush设置成功");

	//这里报错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.
    hibernateTemplate.save(obj);
    System.out.println("运行到这里le ");

} 
}

错误为dao层错误,其他层应该没有什么问题。查了很多Turn your Session into FlushMode.COMMIT/AUTO错误的解决方案,80%都说的OpenSessionInViewFilter配置问题,可是我根本没用OpenSessionInViewFilter!也没配置OurOpenSessionInViewFilter。求大神一定帮我解答!非常感谢!

ps:国外网站也查了一些,有一个说加入下面的代码。但是加入到spring配置文件后,项目启动都不能。。不懂aop。。
 <aop:config>       
        <aop:advisor id=”managerTx” advice-ref=”txAdvice” pointcut=”execution(* *..service.manager.*Manager.*(..))” 
        order=”1″/>
    </aop:config>

    <tx:advice id=”txAdvice”>
        <tx:attributes>
            <tx:method name=”*” propagation=”REQUIRED” read-only=”true”/>
            <tx:method name=”create*” propagation=”REQUIRED” read-only=”false” />
            <tx:method name=”save*” propagation=”REQUIRED” read-only=”false” />
            <tx:method name=”update*” propagation=”REQUIRED” read-only=”false” />
            <tx:method name=”delete*” propagation=”REQUIRED” read-only=”false” />
        </tx:attributes>
    </tx:advice>

spring4.0 整合时持久化对象出错。
40分
<tx:method name="*" propagation="REQUIRED" read-only="true"/>

Hibernate4已经是全部用了自己的事务处理框架,Spring集成事务层必须打开事务放行。

spring4.0 整合时持久化对象出错。
引用 1 楼 zhangjihao 的回复:
<tx:method name="*" propagation="REQUIRED" read-only="true"/>

Hibernate4已经是全部用了自己的事务处理框架,Spring集成事务层必须打开事务放行。

请问加上这段代码就行了么?在spring实物层(applicationContext2.xml)中添加就行?

spring4.0 整合时持久化对象出错。
尝试了一下配置事务

<!-- 事务 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="create*" propagation="REQUIRED" read-only="false" />
            <tx:method name="save*" propagation="REQUIRED" read-only="false" />
            <tx:method name="reg*" propagation="REQUIRED" read-only="false" />
            <tx:method name="update*" propagation="REQUIRED" read-only="false" />
            <tx:method name="delete*" propagation="REQUIRED" read-only="false" />
        </tx:attributes>
    </tx:advice>
     <aop:config>       
        <aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(com.eai.serviceImpl.*.*(..))" 
        order="1"/>
    </aop:config>

但是启动项目的时候报错,java.lang.IllegalStateException: BeanFactory not initialized or already closed – call “”refresh”” before accessing beans via the ApplicationContext。
不知道我离成功越来越近还是越来越远了。。。。

spring4.0 整合时持久化对象出错。
问题已经解决了。
问题就如异常所述,是flushmode属性问题。
对数据库的操作都属于事务的操作,而数据库默认是读已提交 read-only=”true”形式
 当读写操作时会调用DAO方法,而操作DAO的核心业务是Service,即 Spring,然而Spring
要对调用DAO的方法加以控制,所以就产生了切面(advice)
新增配置如下:
<bean id=”transactionManager”
class=”org.springframework.orm.hibernate4.HibernateTransactionManager”>
<property name=”sessionFactory” ref=”sessionFactory” />
</bean>
    <tx:advice id=”txAdvice” transaction-manager=”transactionManager”>
        <tx:attributes>
            <tx:method name=”*” propagation=”REQUIRED” read-only=”true”/>
            <tx:method name=”create*” propagation=”REQUIRED” read-only=”false” />
            <tx:method name=”save*” propagation=”REQUIRED” read-only=”false” />
            //实际只用到reg这个连接点。
            <tx:method name=”reg*” propagation=”REQUIRED” read-only=”false” />
            <tx:method name=”update*” propagation=”REQUIRED” read-only=”false” />
            <tx:method name=”delete*” propagation=”REQUIRED” read-only=”false” />
        </tx:attributes>
    </tx:advice>
     <aop:config>       
        <aop:advisor id=”managerTx” advice-ref=”txAdvice” pointcut=”execution(* com.easi.serviceImpl.*.*(..)))” 
        order=”1″/>
    </aop:config>

报错需要导入aop的一些包,根据错误提示缺什么导什么就行了。

虽然异常解决了,但是我觉得这种方式不好,其实根本原因就是readonly=fale所以不能写入数据源。只要单独设置数据源readonly属性即可,不需要引入切面。

当然引入切面好处是以后逻辑业务多了,spring可以可以通过切面连接点很好的保护数据源。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明spring4.0 整合时持久化对象出错。
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!