Spring Reposetory NullPointerException

问题描述 投票:0回答:4

我正在尝试使用Spring Data JPA保存对象。不幸的是我总是得到一个NullPointerException。但我不明白为什么。我遵循了这个教程:https://www.callicoder.com/spring-boot-jpa-hibernate-postgresql-restful-crud-api-example/我不需要CRUD API,因此我遗漏了属于它的东西。

我收到以下错误:

java.lang.NullPointerException
    at com.niclas.elitedangerousapi.handler.SystemPopulatedHandler.insertIntoDB(SystemPopulatedHandler.java:39)
    at com.niclas.elitedangerousapi.Main.main(Main.java:19)
[main] ERROR c.n.e.h.SystemPopulatedHandler - null

更新我想填充我的数据库,但随后我想要。最后应该是每天晚上下载文件然后存储在数据库中。后来我想通过API访问数据。我想在开始和每x个小时执行这个方法(systemPopulatedHandler.insertIntoDB())。

SystemPopulated.class

@Data
@Entity
@Table(name = "systems_populated")
@JsonIgnoreProperties(ignoreUnknown = true)
public class SystemPopulated {

    @Id
    @Column(name = "id")
    private int id;

    @Column(name = "edsm_id")
    private long edsm_id;

    @Column(name = "name")
    private String name;

    @Column(name = "x")
    private double x;

    @Column(name = "y")
    private double y;

    @Column(name = "z")
    private double z;

    @Column(name = "population")
    private long population;

    @Column(name = "is_populated")
    private boolean is_populated;

    @Column(name = "government_id")
    private long government_id;

    @Column(name = "government")
    private String government;

    @Column(name = "allegiance_id")
    private int allegiance_id;

    @Column(name = "allegiance")
    private String allegiance;

    @Column(name = "security_id")
    private int security_id;

    @Column(name = "security")
    private String security;

    @Column(name = "primary_economy_id")
    private int primary_economy_id;

    @Column(name = "primary_economy")
    private String primary_economy;

    @Column(name = "power")
    private String power;

    @Column(name = "power_state")
    private String power_state;

    @Column(name = "power_state_id")
    private int power_state_id;

    @Column(name = "needs_permit")
    private boolean needs_permit;

    @Column(name = "updated_at")
    private long updated_at;

    @Column(name = "controlling_minor_faction_id")
    private int controlling_minor_faction_id;

    @Column(name = "controlling_minor_faction")
    private String controlling_minor_faction;

    @Column(name = "reserve_type_id")
    private int reserve_type_id;

    @Column(name = "reserve_type")
    private String reserve_type;
}

我的SystemPopulatedReposetory.class

@Repository
public interface SystemPopulatedRepository extends JpaRepository<SystemPopulated, Integer> {
}

我的类我想要InsertIntoDB SystemPopulatedHandler.class

@Slf4j
public class SystemPopulatedHandler {

    @Autowired
    private SystemPopulatedRepository systemPopulatedRepository;

    public void insertIntoDB() {

        BufferedReader reader;
        try {
            reader = new BufferedReader( new FileReader(DOWNLOAD_SAVE_PATH + FILE_NAME_SYSTEMS_POPULATED) );
            String line = reader.readLine();
            while( line != null ){

                ObjectMapper mapper = new ObjectMapper();

                systemPopulatedRepository.save( mapper.readValue( line, SystemPopulated.class ) );

                line = reader.readLine();
            }
            reader.close();
        }
        catch( Exception e ) {
            e.printStackTrace();
            log.error( e.getLocalizedMessage() );
        }
    }

}

我的Main.class

@SpringBootApplication
@EnableJpaRepositories
public class Main {
    public static void main( String[] args ) {
        SpringApplication.run( Main.class, args );

        SystemPopulatedHandler systemPopulatedHandler = new SystemPopulatedHandler();
        systemPopulatedHandler.insertIntoDB();
  }
}
spring spring-boot spring-data-jpa
4个回答
1
投票

问题是你自己创建SystemPopulatedHandler

SystemPopulatedHandler systemPopulatedHandler = new SystemPopulatedHandler();

这样Spring就不会将存储库注入到您的类中,因为只有在spring创建类时它才有效。

但是如果你想在启动时填充一个数据库(至少看起来你试图这样做)你应该检查flyway(或者在本文档中为85.5:https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html

如果由于某种原因无法使用flyway,可以将以下代码添加到主类:

@Bean
public SystemPopulatedHandler systemPopulatedHandler(SystemPopulatedRepository repository) {
    SystemPopulatedHandler systemPopulatedHandler = new SystemPopulatedHandler(repository);
    systemPopulatedHandler.insertIntoDB()
    return systemPopulatedHandler;
}

然后将构造函数添加到SystemPopulatedHandler类:

public SystemPopulatedHandler(SystemPopulatedRepository systemPopulatedRepository) {
    this.systemPopulatedRepository = systemPopulatedRepository;
}

并删除@Autowired注释。

更新

您还需要添加此答案中提到的缺失注释:https://stackoverflow.com/a/55767393/2248239

更新2

如果你想定期做这个动作你可以使用调度(就像在本指南中https://spring.io/guides/gs/scheduling-tasks/)实际上这很简单:

除了添加缺少的注释之外,不要执行上面提到的更改,只需执行以下操作:

@Component添加到SystemPopulatedHandler

@Scheduled添加到insertIntoDB()SystemPopulatedHandler

并将@EnableScheduling添加到主类

对于@Scheduled,只需阅读指南,它描述了您可以使用注释做什么。


0
投票

这是因为你自动连接的存储库没有连接bean。

请使用@Repository注释您的存储库并在主类中指定@EnableJpaRepository。

有关更多详细信息,请参阅spring数据JPA文档


0
投票

问题是您在不使用ApplicationContext或BeanFactory的情况下实例化SystemPopulatedHandler bean,因此它不是由IOC容器维护的。

要在SpringBoot应用程序中使用DI,只需在控制器或服务中自动连接SystemPopulatedHandler,然后就可以调用insert Into DB()方法。

由于您使用的是Spring引导,并且示例非常简单,因此您无需为bean单独配置。

@Controller
public class SystemPopulatedController {

    @Autowired
    private SystemPopulatedHandler systemPopulatedHandler;

    @RequestMapping("/")
    public void insertIntoDB() {

      systemPopulatedHandler.insertIntoDB();
    }

}

0
投票

非常感谢你们所有人。我已经解决了以下问题:

SystemPopulatedReposetory.class

@Repository
public interface SystemPopulatedRepository extends JpaRepository<SystemPopulated, Integer> {
}
´´´

SystemPopulatedHandler.class

@Slf4j
@Component
public class SystemPopulatedHandler {

    @Autowired
    private SystemPopulatedRepository systemPopulatedRepository;

    @PostConstruct
    @Scheduled(cron = "0 0 0 * * *")
    public void insertIntoDB() {

        BufferedReader reader;
        try {
            reader = new BufferedReader( new FileReader(DOWNLOAD_SAVE_PATH + FILE_NAME_SYSTEMS_POPULATED) );
            String line = reader.readLine();
            while( line != null ){

                ObjectMapper mapper = new ObjectMapper();

                systemPopulatedRepository.save( mapper.readValue( line, SystemPopulated.class ) );

                line = reader.readLine();
            }
            reader.close();
        }
        catch( Exception e ) {
            e.printStackTrace();
            log.error( e.getLocalizedMessage() );
        }
    }
}

´´´

Main.class

@SpringBootApplication
@EnableJpaRepositories
@EnableScheduling
public class Main {
    public static void main( String[] args ) {
        SpringApplication.run( Main.class, args );

        FileHandler fileHandler = new FileHandler();

    }
}

© www.soinside.com 2019 - 2024. All rights reserved.