Quartz作业抛出InvalidDataAccessApiUsageException:没有事务在进行中。

时间:2019-04-29 21:17:37

标签: java spring quartz-scheduler

我有一个非常简单的石英作业,正在尝试从数据库中获取打印机记录,
我收到此错误:

org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; 
nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
javax.persistence.TransactionRequiredException: no transaction is in progress

这是应用程序的代码:

@SpringBootApplication
@ComponentScan(basePackages="com.xerox.printhub") 
@EntityScan("com.xerox.printhub*")
@EnableTransactionManagement
@EnableJpaRepositories(basePackages ={"com.xerox.printhub.repository"})
@Import({ SchedulerConfig.class })
public class PrinterVerificationApp extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(PrinterVerificationApp.class, args);
    }
}

这是Quartz作业的代码:

package com.xerox.printhub.quartz.jobs;

import javax.transaction.Transactional;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;



public class PrinterVerificationJob implements Job{

    @Transactional
    public void execute(JobExecutionContext jobExecutionContext) {

    private static final Logger logger = LoggerFactory.getLogger(PrinterVerificationJob.class);

    @Autowired
    Gson g;

       @Autowired
       PrinterInfoRepository printerRepo;   

        logger.debug("Trying to fetch an available printer...");

        PrinterInfo printerInfo=null;
        try {
            printerInfo = printerRepo.findOneAndLock(PrinterStatus.NEW.name());
            } catch (Exception e1) {
            logger.debug("Error!",e1);
            }

    }

更新:在我的应用程序中,此Rest控制器与PrinterInfoRepository一起正常工作

package com.xerox.printhub.controllers;

import java.text.ParseException;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class PrinterAPIController {

    @Autowired 
    PrinterInfoRepository printerRepo;


    @PostMapping(value = "/SubmitPrinterData")
    public PrinterInfo submitPrinterData(
            @RequestBody PrinterInfoJason printerInfo) {
            //THIS METHOD IS WORKING FINE.
    }

我尝试了两个注释:

import javax.transaction.Transactional;
import org.springframework.transaction.annotation.Transactional;

然后我尝试使用@service注释PrinterVerificationJob
我还添加了EnableTransactionManagement

但是没有帮助。
知道我在做什么错吗?

更新
我找到了罪魁祸首,
当我不使用LockModeType.PESSIMISTIC_WRITE时,我可以读到... 当我尝试使用LockModeType.PESSIMISTIC_WRITE访问时,出现异常:

 @Lock(LockModeType.PESSIMISTIC_WRITE)//locking it to prevent other workers to access it.
 @Query("SELECT p FROM PrinterInfo p where p.statusCd = :status")
 PrinterInfo findOneAndLock(@Param("status")String status);

1 个答案:

答案 0 :(得分:3)

从您的日志中可以明显看出-为什么?因为如果事务处于活动状态,则您将在两次调用之间进行代理调用,就像在存储库上调用方法时一样。在同一日志中可见。

C

未检测到您的PrinterVerificationJob。这意味着您的@Transactional注释不起作用。您需要在春季之前对Bean进行管理,以使@Transactional批注生效。您可以做什么来将execute方法的内容隔离到服务中,然后将其注入到JOB中。然后,您可以使用@Transctional注释此类或此类的方法。该bean将被检测,并且@Transactional注释将生效。

   at com.xerox.printhub.quartz.jobs.PrinterVerificationJob.getPrinter(PrinterVerificationJob.java:158)

    at com.xerox.printhub.quartz.jobs.PrinterVerificationJob.execute(PrinterVerificationJob.java:189)

    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)

如果您想按原样保留应用程序逻辑。您可以做的是使用已经在spring中初始化的@PlatformTransactionManager,并将其自动关联到您的工作。使用此事务管理器,您可以手动启动事务。有了它,您可以初始化TransactionTemplate并执行以下操作:

@Service
PrinterVerificationService {

@Transactional
public void verifyPrinter(yuor parameters here)

}

public class PrinterVerificationJob implements Job{
@Autowire
PrinterVerificationService verificationService;

public void execute(JobExecutionContext jobExecutionContext) {
    service.verifyPrinter(your prameters here)
}