java - 如何为每个计划方法分配一个 Hibernate session

标签 java spring hibernate spring-scheduled

我有以下设置:

@Component
public class Scheduler {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    BatchService batchService;

    @Scheduled(cron = "0 */1 * ? * *")
    void tick() {
        logger.info("Beginning of a batch tick");
        batchService.refundNotAssignedVisits();
        logger.info("End of the batch tick");
    }
}

BatchService 包含以下内容:

@Service
public class BatchServiceImpl implements BatchService {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    VisitService visitService;

    @Override
    @Transactional
    public void refundNotAssignedVisits() {
        logger.info("Start automatic refund of past visits being assigned");

        Set<Visit> visits = visitService.findRefundableVisits();

        if(visits != null && visits.size() != 0) {
            logger.info("Found " + visits.size() + " visits to refund with IDs: " + visits.stream().map(x -> x.getId().toString()).collect(Collectors.joining(", ")));
            visits.forEach(x -> {
                logger.info("Refunding visit with ID: " + x.getId());
                try {
                    visitService.cancel(x);
                    logger.info("Visit successfully refunded!");
                }
                catch(Exception e) {
                    logger.error("Error while refunding visit...", e);
                }
            });
        }
        else {
            logger.info("Found no visit to refund.");
        }

        logger.info("End of automatic refund");
    }
}

cancel 方法定义如下:

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Visit cancel(Visit visit) throws Exception {
    // Some business logic
}

出于商业目的,我需要 cancel 方法每次调用处理一笔事务,目前,refundNotAssignedVisits@Transactional为了启用 Hibernate session ,以便我能够在 cancel 方法中对相关实体使用延迟加载。

这会导致重复提交等问题,我想知道什么是实现我想要的效果的好模式:有一个 @Scheduled 方法来启用 Hibernate session ,以便多次调用另一个 session 每次调用一次事务的方法。

最佳答案

@TransactionalREQUIRES_NEW 将创建另一个新的 Hibernate session ,因此 cancel() 内的 session 将与用于加载对我来说似乎很尴尬的实体。通常,我们使用相同的 session 来加载和管理事务中的相同实体。

我将代码重构为以下内容:

VisitService:

//Cannel by visitorId and load the Visitor by Id in a new transaction
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Visit cancel(Integer visitorId) throws Exception {
    Visit visit=  session.get(Visit.class , visitorId); 
    cancel(visit); 
}

@Override
public Visit cancel(Visit visit) throws Exception {
    // Some business logic
}

//Add method to return the IDs only
@Transactional(readOnly=true)
public Set<Integer> findRefundableVisitId(){

}

批量服务:

//@Transactional  (Do not require anymore)
public void refundNotAssignedVisits() {
    logger.info("Start automatic refund of past visits being assigned");

    Set<Integer> refundVisitIds = visitService.findRefundableVisitId();
    refundVisitIds.forEach( id-> {
           try {
                visitService.refund(id);
                logger.info("Visit successfully refunded!");
            }
            catch(Exception e) {
                logger.error("Error while refunding visit...", e);
            }        
     });
}    

通过这种方式,每个退款都在自己的事务中执行,并且用于加载退款访问者的事务不需要等待所有退款完成才能提交,并且不再有“重复提交”。

关于java - 如何为每个计划方法分配一个 Hibernate session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53986684/

相关文章:

java - 发生 Firebase 身份验证 FirebaseNetworkException : A network error (such as timeout, 中断连接或无法访问的主机)

java - Axis2 客户端无法在 Tomcat 7.0.42 上启动第二个 https 调用

spring - 无法使用 Spring MockMvc 将正文附加到我的 POST 请求

java - 为什么 HikariCP 在关闭前一个数据库后不建立新的数据库连接?

java - Spring Data JPA - 为现有集合模拟 "create + join"查询

hibernate - 如何使用 hibernate.reveng.xml 更改自引用多对多集的名称?

java - java中的数学分数计算

java - 来自 Thread 的警报对话框 - Android

Spring boot 无法创建多个兔子连接工厂

java - 如何从实例初始化 block 调用注入(inject)的 bean 方法