我有一个Web服务DocGenerationServiceImpl,它使用DocRepository在表中插入(对于每种格式)一条记录,并将表示该记录的对象表示为DocFileDO。在for循环中,我可以获取在表中创建的记录的ID。对于每条记录,我将调用执行程序的execute方法,其中DocGenTask将在给定ID的情况下搜索记录。但是,例如,有3种格式,DocGenTask只能获取最后一条记录。它找不到前两个。尽管它使用的是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);
    }
}

最佳答案

几件事


不要使用HibernateTemplate,它应该从Hibernate 3.0.1(在2006年某个地方发布)开始就被弃用。直接使用SessionFactory并使用getCurrentSession()方法来使休眠的Session可以运行。
您没有事务设置(从摘要中判断),要使用数据库,您需要适当的事务设置。
您的控制器正在做很多事情,所有这些都应该放在服务内部。


第一个重构您的存储库

@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转换为某种事物的内部表示,然后在某处启动服务/业务方法。服务/业务方法也是您的事务性工作单元,它要么全部成功,要么全部失败。

10-08 03:51