HibernateTemplate在通过TaskExecutor调用时没有获取对象

时间:2013-11-27 06:31:37

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

我有一个Web服务DocGenerationServiceImpl,它使用DocRepository和表示记录为DocFileDO的对象在表中插入(对于每种格式)记录。在for循环中,我可以获取在表中创建的记录的id。对于每条记录,我将调用执行程序的execute方法,其中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);
    }
}

1 个答案:

答案 0 :(得分:1)

一些事情

  1. 不要使用HibernateTemplate从Hibernate 3.0.1(2006年某处发布)开始,它应被视为已弃用。直接使用SessionFactory并使用getCurrentSession()方法获取休眠Session进行操作。

  2. 您没有设置交易(从代码段开始判断),要使用数据库,您需要正确的交易设置。

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

  4. 第一个重构您的存储库

    @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转换为某种内部表示,然后在某处启动服务/业务方法。这种服务/业务方法也是您的交易工作单元,无论是成功还是全部失败。