Spring Boot启动时获取汇率API数据并通过JPA存储的实现咨询
Spring Boot启动时加载汇率API数据并存储到数据库的解决方案
嘿,我来帮你搞定这个启动加载和存储的逻辑!先梳理下你现有代码里的小细节,再一步步实现你要的功能:
第一步:修正模型类的小问题
首先你的CurrencyData里的base和date字段用了@Embedded,这不对——它们是普通字符串,不是嵌入实体,直接去掉这个注解就行。另外Rates类里的HKD字段没写完,得补全;还要给实体类加上无参构造,JPA要求实体必须有一个无参构造方法,不然会报错。修正后的代码如下:
// 修正后的CurrencyData @Data @AllArgsConstructor @NoArgsConstructor // 新增无参构造,JPA必需 @Entity public class CurrencyData { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @SerializedName("rates") @Expose @Embedded private Rates rates; @SerializedName("base") @Expose private String base; // 去掉@Embedded @SerializedName("date") @Expose private String date; // 去掉@Embedded } // 补全后的Rates @Data @Embeddable public class Rates { protected Rates(){} // JPA需要无参构造 @SerializedName("CAD") @Expose private Double cAD; @SerializedName("HKD") @Expose private Double hKD; // 补全字段定义 // 可按需添加其他汇率字段,比如USD、EUR等 }
第二步:完善启动加载逻辑(CommandLineRunner)
你已经选对了用CommandLineRunner实现启动时执行逻辑,现在只需要注入你写好的ConnectService、GsonConvert和CurrencyRepository,按顺序调用方法完成数据获取→反序列化→存储的流程:
@Configuration public class CurrencyDataLoader { @Bean CommandLineRunner currencyDataLoader( ConnectService connectService, GsonConvert gsonConvert, CurrencyRepository currencyRepository ) { return args -> { // 1. 调用API获取JSON字符串 String apiResponse = connectService.connect(); // 2. 反序列化为CurrencyData对象 CurrencyData currencyData = gsonConvert.gsonCurrency(apiResponse); // 3. 保存到数据库 currencyRepository.save(currencyData); System.out.println("汇率数据已成功加载并存储到数据库!"); }; } }
这样Spring Boot启动时,这个Runner会自动执行,帮你完成所有操作。
关于你提到的Map实现思路
如果不想为每个汇率字段都定义属性,确实可以用Map<String, Double>来接收所有汇率数据,这样就不需要Rates类了。修改后的模型类如下:
// 改用Map接收汇率的CurrencyData @Data @AllArgsConstructor @NoArgsConstructor @Entity public class CurrencyData { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @SerializedName("rates") @Expose @ElementCollection // 用这个注解存储Map类型的嵌入数据 private Map<String, Double> rates; @SerializedName("base") @Expose private String base; @SerializedName("date") @Expose private String date; }
Gson会自动把JSON里的rates对象转换成Map<String, Double>,JPA也会用@ElementCollection把这个Map存储到关联表(默认表名为currency_data_rates,包含currency_data_id、rates_key、rates_value三个字段)。你的GsonConvert代码不需要改动,依然可以正常反序列化。
额外优化建议
- 完善
ConnectService里的异常处理,把你写的TODO替换成自定义异常或合适的RuntimeException; - 添加重复数据判断,避免每次启动都存储相同数据:
在CurrencyRepository里新增查询方法:
然后在@Repository public interface CurrencyRepository extends JpaRepository<CurrencyData, Long> { Optional<CurrencyData> findByBaseAndDate(String base, String date); }CommandLineRunner里添加判断逻辑:Optional<CurrencyData> existingData = currencyRepository.findByBaseAndDate(currencyData.getBase(), currencyData.getDate()); if (existingData.isEmpty()) { currencyRepository.save(currencyData); System.out.println("汇率数据已成功加载并存储到数据库!"); } else { System.out.println("当天的汇率数据已存在,无需重复存储"); }
内容的提问来源于stack exchange,提问作者Grafik Krystian
相关产品推荐
相关产品推荐

