论坛首页 Java版 Spring

Spring2.5新特性使用出现的问题

浏览 742 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2008-04-09 关键字: spring2.5新特性
以前为了项目开发协作方便,放弃了bean在xml中直接配置的方式,改用注释加XDoclet来程序生成xml配置,最后导入。
如我定义了一个Dao接口:
package com.test.dao;

public interface CoreDao
{
    void create(Object obj);
}

然后基于hibernate做了实现:
package com.test.dao.hibernate;

/**
 * 
 * @spring.bean name="coreDao"
 */
public class CoreDaoImpl implements CoreDao 
{
    protected HibernateTemplate hibernateTemplate;

    /**
      * @spring.property ref="hibernateTemplate"
      */
    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) 
    {
        this.hibernateTemplate = hibernateTemplate;
    }

    @Override
    public void create(Object obj)
    {
        hibernateTemplate.save(obj);
    }
} 

另外,我定义了事务类接口CoreService:
package com.test.service;

import org.springframework.transaction.annotation.Transactional;

@Transactional
public interface CoreService
{
    void create(Object obj);
}

注意上面代码中用@Transactional进行了事务边界定义。
最后,对CoreService写了实现类CoreServiceImpl.java。
/**
 *
 * @spring.bean name="coreService"
 */
public class CoreServiceImpl implements CoreService 
{
    private CoreDao coreDao;

    /**
      * 
      * @spring.property ref="coreDao"
      */
    public void setCoreDao(CoreDao coreDao) 
    {
	this.coreDao = coreDao;
    }

    @Override
    public void create(Object obj)
    {
        coreDao.create(obj);
    }
}

大家可以看到上面的CoreDaoImpl.java和CoreServiceImpl.java中,增加了bean的定义注释,这些注释会通过XDoclet来生成.xml文件,最终我会在spring的配置文件中,使用"<import resource="core-services-import-beans.xml"/>"的方式进行XML配置信息导入。
按照以上的配置方式,create()方法调用成功。事务也是正确的。

为了进一步简化Spring的配置过程,我目前使用了Spring2.5的新特性@Component和@Autowired。
主要将这两个新特性用于更改CoreDaoImpl.java和CoreServiceImpl.java。如下:
package com.test.dao.hibernate;

@Component
public class CoreDaoImpl implements CoreDao 
{
    @Autowired
    protected HibernateTemplate hibernateTemplate;


    @Override
    public void create(Object obj)
    {
        hibernateTemplate.save(obj);
    }
} 

@Component
public class CoreServiceImpl implements CoreService 
{
    @Autowired
    private CoreDao coreDao;


    @Override
    public void create(Object obj)
    {
        coreDao.create(obj);
    }
}

大家可以看出来,这样配置极大地简单了配置过程。但是问题出现了。
我在如下Controller类中调用create()方法报错:
package com.test.web;

@Component("/demo/TestDemo.html")
public class TestDemo implements Controller
{
    @Autowired
    private CoreService coreService;

    public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		User user = new User();
		user.setName("小离");
		coreService.create(user);
		Map map = new HashMap();
		map.put("alertinfo", "successfully");
		return new ModelAndView("TreeDemo.vm", map);
    }
}

程序在执行到coreService.create(user)的时候报错,报错信息如下:
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
	org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1112)
	org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:641)
	org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:373)
	org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:639)
	com.forlink.framework.dao.hibernate.CoreDaoImpl.create(CoreDaoImpl.java:33)
	com.forlink.framework.service.impl.CoreServiceImpl.create(CoreServiceImpl.java:22)
	com.forlink.mofile.web.demo.TreeDemo.handleRequest(TreeDemo.java:25)
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:431)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	com.forlink.framework.web.core.FrameworkFilter.doFilter(FrameworkFilter.java:28)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75)


如果按照以前注释的方式,最后在执行hibernateTemplate.save(obj)是正常的。不知道谁碰到过这个问题的。
个人判断是这里的事务配置失效了,才会造成session不会按照需要调整为FlushMode.COMMIT/AUTO模式。但是又不知道错在哪里。采用注解方式将事务配置在接口类CoreService.java中@Transactional以前都没问题。谢谢。
   
最后更新时间:2008-04-09
原因找到了。确实是事务配置失效了。将xxx-service.xml文件中的"<tx:annotation-driven transaction-manager="transactionManager"/>"配置到
xxx-servlet.xml文件中就没问题了。实质原因我继续查的。
   
0 请登录后投票
论坛首页 Java版 Spring

跳转论坛:
JavaEye推荐