Десериализация Json и сохранение в JPA при загрузке - PullRequest
1 голос
/ 28 июня 2019

Доброе утро, Я использую API в формате JSON, данные о последних курсах обмена.

Я хочу, чтобы эти данные были загружены мне в начале приложения и сохранены в базе данных. Я использую пружину JPA.

Проблема в том, что я не знаю, как мне это записать.

У меня есть класс, отвечающий за соединение, которое возвращает вывод в виде строки. Другой создает десериализацию.

У меня также есть два класса моделей, которые я могу использовать для загрузки данных.

Я не хочу создавать отдельный класс, в котором программа будет извлекать каждое значение отдельно. Я думал о карте, но не знаю, как это сделать.

Код:

Модель 1

@Data
@AllArgsConstructor
@Entity
public class CurrencyData {

    @Id
    @GeneratedValue( strategy = GenerationType.AUTO )
    private Long id;

    @SerializedName("rates")
    @Expose
    @Embedded
    private Rates rates;

    @SerializedName("base")
    @Expose
    @Embedded
    private String base;

    @SerializedName("date")
    @Expose
    @Embedded
    private String date;

}

Модель 2

@Data
@AllArgsConstructor
@Embeddable
public class Rates {

    protected Rates(){}

    @SerializedName("CAD")
    @Expose
    private Double cAD;
    @SerializedName("HKD")
}

ConnectService со строковым выходом API

private static final String REQUEST_CURRENCY = "https://api.exchangeratesapi.io/latest?base=USD";

public String connect() {

    String output = null;
    try {

        System.out.println("URL String : " + REQUEST_CURRENCY);

        URL url = new URL(REQUEST_CURRENCY);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Accept", "application/json");

        if (conn.getResponseCode() != 200) {
            throw new TODO("TODO : ", e.getMessage());
        } else {

            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            in.close();
            output = response.toString();
        }
    } catch (Exception e) {

        throw new OutputFromApiException("ConnectService CurrencyData-API: output is : ", e.getMessage());
    }

    return output;
}

GsonConvert - десериализация

public CurrencyData gsonCurrency(String answer) {

    Gson g = new Gson();
    CurrencyData currencyData = null;

    try {
         currencyData = g.fromJson(answer, CurrencyData.class);

    } catch (Exception e) {
       throw new OutputFromApiException("HistoricalFlight API output is empty ", e.toString());
    }


   return currencyData;
}

Репозиторий

@Repository
public interface CurrencyRepository extends JpaRepository<CurrencyData, Long> {
}

... И, наверное, я должен написать что-то здесь ..

@Bean
CommandLineRunner runner(CurrencyRepository currencyRepository) {
    return args -> {
        currencyRepository.save();
    };
}

Ответы [ 2 ]

1 голос
/ 29 июня 2019

Если вы используете Spring Boot, я думаю, вы должны определить основной класс, который реализует CommandLineRunner вместо определения его как @Bean. Это должно быть что-то вроде:

@SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootConsoleApplication.class, args);
    }

    @Autowired
    CurrencyRepository currencyRepository;

    @Autowired
    ConnectService connectionService;

    @Override
    public void run(String... args) {

        String output = connectionService.connect();
        CurrencyData currencyData = connectionService.gsonCurrency(output);
        currencyRepository.save(currencyData);

    } 
}

Также я предположил, что ваша конфигурация jpa правильная, а ваша CurrencyRepository работает как положено. Если у вас нет структуры базы данных, созданной вручную, вы можете рассмотреть возможность добавления в файл application.properties как:

spring.jpa.hibernate.ddl-auto=update

Это обеспечит вам, что JPA создает или обновляет правильные структуры базы данных при каждой загрузке, используя конфигурацию ваших сущностей.

EDIT: Извините, я забыл упомянуть о том, что вы должны передать объект, который вы хотите сохранить, в базу данных. Я отредактировал код так, как мне кажется, gsonCurrency метод - это метод внутри ConnectionService. Также вы можете передать параметр в метод connectionService.connect() для base, если вы хотите получить разные данные в соответствии с различными базовыми валютами, например:

CurrencyData currencyDataUSD = connectionService.gsonCurrency(connectionService.connect("USD"));
CurrencyData currencyDataEUR = connectionService.gsonCurrency(connectionService.connect("EUR"));
// and go on if you like
0 голосов
/ 29 июня 2019

Вы можете использовать Spring Boot and Rest Template, чтобы вы могли легко управлять преобразованием сообщений без необходимости писать HttpConnection низкого уровня.Есть два способа выполнить метод, когда запуск приложения происходит в Spring Boot, CommandLineRunner и ApplicationRunner, и здесь мы используем первый, как показано ниже:

@SpringBootApplication
public class Application {

private static final Logger log = LoggerFactory.getLogger(Application.class);

public static void main(String args[]) {
    SpringApplication.run(Application.class);
}

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
}

@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
    return args -> {
        Quote quote = restTemplate.getForObject(
                "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
        log.info(quote.toString());
    };
}

}

Источник:https://spring.io/guides/gs/consuming-rest/

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