Репозиторий Spring NullPointerException - PullRequest
0 голосов
/ 19 апреля 2019

Я пытаюсь сохранить объект с помощью 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

UPDATE Я хочу заполнить свою базу данных, но потом, когда захочу. В конце должно быть так, что каждую ночь файл загружается и затем сохраняется в базе данных. Позже я хочу сделать данные доступными через API. Я хочу выполнить этот метод (systemPopulatedHandler.insertIntoDB ()) в начале и каждые x часов.

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> {
}

Мой класс, куда я хочу вставитьIntoDB 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() );
        }
    }

}

Мой главный класс

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

        SystemPopulatedHandler systemPopulatedHandler = new SystemPopulatedHandler();
        systemPopulatedHandler.insertIntoDB();
  }
}

Ответы [ 4 ]

1 голос
/ 19 апреля 2019

Проблема в том, что вы создаете SystemPopulatedHandler сами с помощью

SystemPopulatedHandler systemPopulatedHandler = new SystemPopulatedHandler();

Таким образом Spring не внедряет хранилище в ваш класс, потому что это работает, только если Spring создает класс.

Но если вы хотите заполнить базу данных при запуске (по крайней мере, кажется, что вы пытаетесь это сделать), вы должны проверить пролет (или 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 голосов
/ 20 апреля 2019

Большое спасибо всем вам. Я решил проблему следующим образом:

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();

    }
}

0 голосов
/ 19 апреля 2019

Проблема в том, что вы создаете экземпляр компонента SystemPopulatedHandler без использования ApplicationContext или BeanFactory, поэтому он не поддерживается контейнером IOC.

Чтобы использовать DI в приложении SpringBoot, все, что вам нужно, это просто автоматически подключить SystemPopulatedHandler к вашему контроллеру или службе, а затем вызвать метод insertIntoDB ().

Поскольку вы используете весеннюю загрузку, а пример очень прост, вам не нужно создавать отдельную конфигурацию для bean-компонентов.

@Controller
public class SystemPopulatedController {

    @Autowired
    private SystemPopulatedHandler systemPopulatedHandler;

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

      systemPopulatedHandler.insertIntoDB();
    }

}
0 голосов
/ 19 апреля 2019

Это связано с тем, что у вас автоматически подключено хранилище, не подключающее компонент.

Пожалуйста, анонсируйте свой репозиторий с помощью @Repository И в основном классе укажите @EnableJpaRepository.

Подробнее о документах JPA для пружин см.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...