我有一个非常简单的石英作业,正在尝试从数据库中获取打印机记录,
我收到此错误:
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);
答案 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)
}