如何使用控制器外部的JPA存储库更新行值?

时间:2019-05-13 13:32:33

标签: java spring-boot jpa crud

我试图从控制器外部(在某些线程内部)更新表行数据,并始终获取'NullPointerException'。

线程代码:

public class S3Thread implements Runnable {

@Autowired  
private IAutomationService automationService;

@Override
public void run() { 
    Automation config = new Automation("user1","success");
    automationService.updateAutomation(config);
 }
}

NullPointer异常引发以下行: automationService.updateAutomation(config);

注意:我能够从控制器类创建/更新。仅在线程中。

4 个答案:

答案 0 :(得分:1)

好吧,这是经典的Why is my Spring @Autowired field null案例。您自己创建了S3Thread实例,因此,没有注入任何bean。

考虑到您只想在单独的线程中做某事,可以考虑使用@Async

@Async
public void updateAutomationConfiguration() {
    Automation config = new Automation("user1", "success");
    automationService.updateAutomation(config);
}

注释

  • 您必须将@EnableAsync批注添加到任何配置类(例如您的主类)中,以使这项工作生效。
  • Spring默认使用代理,这意味着您不能将此updateAutomationConfiguration()类添加到控制器本身。直接调用同一bean中的方法会绕过代理逻辑。解决方案是将该方法放在一个单独的bean中,该bean可以在控制器内自动装配和调用。我在this answer中提供了有关替代解决方案的更详细的答案。

Spring也有creating asynchronous methods的入门指南。


或者,还有一些执行asynchronous calls within controllers的方法,例如通过在控制器中使用CompletableFuture

@PutMapping("/automation/configuration")
public CompletableFuture<String> updateAutomationConfiguration() {
    return CompletableFuture.supplyAsync(() -> {
        Automation config = new Automation("user1", "success");
        return automationService.updateAutomation(config);
    });
}

相关:How to create a non-blocking @RestController webservice in Spring?

答案 1 :(得分:0)

Spring不会扫描您的可运行对象,因为它未使用@Component进行注释。请尝试使用@ Component / @ Service对其进行注释。 不过不要忘记设置范围必需的范围!

答案 2 :(得分:0)

有2种可能的解决方案来解决您的问题:

您需要通过使用S3Thread@Service对其进行注释,并在调用类上自动进行布线,从而使@Component类成为服务,或者可以使用构造函数来初始化{ {1}},例如automationService

答案 3 :(得分:0)

由于您的线程类不是由spring管理的,因此您将无法在S3Thread类中注入spring托管的bean。

为此,您需要创建一个类或工厂,该类或工厂应该与春季生命周期挂钩。

拥有该类的所有权后,您可以获取适当的bean,并将引用直接传递到S3Thread类上/或在S3Thread类中使用。像这样

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext appContext)
    {
        ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}
public class S3Thread implements Runnable {


@Override
public void run() { 
    Automation config = new Automation("user1","success");
 IAutomationService automationService= 
      ApplicationContextUtils.getApplicationContext().getBean(IAutomationService .class);
    automationService.updateAutomation(config);
 }
}