为何Spring Boot中Apps与App的JPA Repository无法保存数据?
Spring Boot中JPA无法保存从Roku API获取的Apps和App实体问题
我正在用Java Spring Boot开发一款基于Roku Dev Tools API的遥控器应用,TelevisionRepository能正常保存实体,但AppsRepository和AppRepository无法保存数据。怀疑和从Roku API(返回XML格式)解析对象属性有关。需求是调用http://{{rokuIPAddress}}:8060/query/apps获取指定电视的安装频道并保存到数据库。
控制器代码
// 获取电视应用列表 @GetMapping(path = "/get-apps/{name}") public ResponseEntity<Apps> getApps(@PathVariable String name) { return appsService.getApps(name); }
服务层代码
// 获取电视应用列表 public ResponseEntity<Apps> getApps(String name) { Television tele = televisionRepository.findByTelevisionName(name).orElseThrow(() -> new TelevisionNotFoundException()); log.info(String.format("Requesting apps for %s via: http://%s:8060/query/apps", name, tele.getIpAddress())); ResponseEntity<Apps> responseEntity = this.restTemplate.getForEntity("http://" + tele.getIpAddress() + ":8060/query/apps", Apps.class); Apps apps = responseEntity.getBody(); System.out.println(apps.toString()); for (App app : apps.getApp()) { appRepository.save(app); } appsRepository.save(apps); return ResponseEntity.ok(apps); }
实体类代码
App实体
@Entity @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "app") public class App { @Id @XmlAttribute(name = "id") private String id; @XmlAttribute(name = "type") private String type; @XmlAttribute(name = "version") private String version; @ManyToOne(fetch = FetchType.LAZY) @JsonIgnore private Apps apps; // 构造方法、getter和setter }
Apps实体
@Entity @XmlRootElement(name = "apps") @Table(name = "apps") @XmlAccessorType(XmlAccessType.FIELD) @JsonIgnoreProperties(ignoreUnknown = true) public class Apps { @Id @GeneratedValue @Column(name = "id", nullable = false) private Long id; @OneToMany(mappedBy = "apps", cascade = CascadeType.REMOVE) @JacksonXmlElementWrapper(useWrapping = false) private List<App> app; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "television_id") @JsonIgnore private Television television; // 构造方法、getter和setter }
Repository定义
AppRepository
public interface AppRepository extends JpaRepository<App, String> { }
AppsRepository
public interface AppsRepository extends JpaRepository<Apps, Long> { }
H2数据库配置
spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true
问题原因及解决方法
关联关系未维护
从Roku API解析得到的Apps和App对象之间没有建立双向关联,保存前需手动设置:Apps apps = responseEntity.getBody(); // 建立双向关联 if (apps.getApp() != null) { apps.getApp().forEach(app -> app.setApps(apps)); }级联配置缺失
当前Apps的@OneToMany仅配置了删除级联,需添加保存/更新级联类型,这样保存Apps时会自动级联保存关联的App:@OneToMany(mappedBy = "apps", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) @JacksonXmlElementWrapper(useWrapping = false) private List<App> app;修改后无需循环调用
appRepository.save(app),直接保存apps即可。Television关联未设置
Apps实体关联了Television,但代码中未绑定对应电视对象,需添加:apps.setTelevision(tele);确保外键约束正常。
事务管理
为服务层getApps方法添加@Transactional注解,避免事务边界问题导致数据未提交:@Transactional public ResponseEntity<Apps> getApps(String name) { // 原有代码逻辑 }
内容的提问来源于stack exchange,提问作者Adriaan Veney
相关产品推荐
相关产品推荐

