业务:通过spring管理数据源,实现用户注册。 错误分析:1.可能是sessionFactory的注入有问题 <?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。。 <tx:advice id=”txAdvice”> |
|
40分 |
<tx:method name="*" propagation="REQUIRED" read-only="true"/> Hibernate4已经是全部用了自己的事务处理框架,Spring集成事务层必须打开事务放行。 |
请问加上这段代码就行了么?在spring实物层(applicationContext2.xml)中添加就行? |
|
尝试了一下配置事务
<!-- 事务 --> <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。 |
|
问题已经解决了。
问题就如异常所述,是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可以可以通过切面连接点很好的保护数据源。 |