【问题标题】:HibernateTemplate not getting the object when called through TaskExecutor通过 TaskExecutor 调用 HibernateTemplate 时未获取对象
【发布时间】:2013-12-12 16:23:01
【问题描述】:

我有一个 Web 服务 DocGenerationServiceImpl,它使用 DocRepository 和将记录表示为 DocFileDO 的对象在表中插入(对于每种格式)记录。在 for 循环中,我可以获得在表中创建的记录的 id。对于每条记录,我将调用执行程序的执行方法,DocGenTask 将在其中搜索给定 id 的记录。但是,例如,有 3 种格式,DocGenTask 只能获取最后一条记录。前 2 个找不到。虽然它使用的是hibernateTemplate。可以请教吗?

@RestfulService
@Controller
@RequestMapping("/docs")
public class DocGenerationServiceImpl {

    @Autowired
    private TaskExecutor taskExecutor;

    @Autowired
    private DocRepository docRepository;

    @RequestMapping(value = "/generate", method = RequestMethod.POST)
    @ResponseBody
    public String generatedDocFile(DOCParam param) {

        for(String format : param.getFormatList()) {
                DocFileDO docFileDO = new DocFileDO();
                ...
                docRepository.saveDocFile(docFileDO);
                log.debug("docFileDO id = " + docFileDO.getId());

                DocGenTask task = new DocGenTask(docFileDO.getId());
                task.setDocRepository(docRepository);
                taskExecutor.execute(task);
        }
    }
}


@Repository
public class DocRepository {
    @Autowired
    private HibernateTemplate hibernateTemplate;

    public DocFileDO saveDocFile(DocFileDO docFile) {
        hibernateTemplate.save(docFile);
        hibernateTemplate.flush();
        return docFile;
    }
    public DocFileDO getDocFile(Long docFileId) {
        return hibernateTemplate.get(DocFileDO.class, docFileId);
    }

}

public class DocGenTask implements Runnable {
    public void run() {
        generate();
    }
    private void generate() {
        DocFileDO docFileObj = docRepository.getDocFile(docFileId);
    }
}

【问题讨论】:

    标签: java spring web-services hibernate scheduled-tasks


    【解决方案1】:

    几件事

    1. 不要使用HibernateTemplate,从 Hibernate 3.0.1(2006 年某个地方发布)开始,它应该被视为已弃用。直接使用SessionFactory,使用getCurrentSession()方法得到一个休眠的Session进行操作。

    2. 您没有事务设置(从 sn-ps 判断),要使用数据库,您需要正确的事务设置。

    3. 您的控制器正在做很多事情,所有这些都应该在服务中。

    第一次重构你的仓库

    @Repository     
    public class DocRepository {
        @Autowired
        private SessionFactory sf;
    
        public DocFileDO saveDocFile(DocFileDO docFile) {
            Session session = sf.getCurrentSession();
            session.save(docFile);
            return docFile;
        }
        public DocFileDO getDocFile(Long docFileId) {
            return sf.getCurrentSession().get(DocFileDO.class, docFileId);
        }
    
    }
    

    现在您的代码可能会由于交易设置不当而失败。将@Transactional 添加到所有需要事务的方法(或类)中(如saveDocFile 方法)。

    如前所述,您可能应该将控制器中的代码移动到服务中。控制器应该只是一个薄集成层,从 Web 转换为某事物的内部表示,然后在某处启动服务/业务方法。此服务/业务方法也是您的事务性工作单元,它要么全部成功,要么全部失败。

    【讨论】:

      猜你喜欢
      • 2012-09-13
      • 1970-01-01
      • 2018-06-20
      • 2011-07-14
      • 2021-08-19
      • 1970-01-01
      • 2012-07-01
      • 2020-07-30
      • 1970-01-01
      相关资源
      最近更新 更多