【发布时间】:2020-12-06 22:43:16
【问题描述】:
即使我使用的是 CascadeType.PERSIST,我也遇到了持久化子实体的问题。当我将新的子对象添加到父对象时,它会被持久化,但它的字段被设为空。
我的实体:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class Portfolio {
@Id
@GeneratedValue
private Long id;
private String ownerEmail;
private Long roomId;
private Double startingCash;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST})
private List<PortfolioState> states;
}
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
public class PortfolioState {
@Id
@GeneratedValue
private Long id;
private Date fromDate;
private Date to;
private Double cash;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.REFRESH})
private List<Position> positions;
}
当执行以下代码行时,PortfolioState get 将保持除 id 之外的所有内容为 null。
/*Adding a new PortfolioState to Portofolio's states */
System.out.println(" Portfolio : " + portfolio.toString());
Portfolio savedPortfolio = portfolioRepository.save(portfolio);
System.out.println(" Saved portfolio : " + savedPortfolio.toString());
System.out.println(" Portfolio object after saving " + portfolio.toString());
Portfolio : Portfolio(id=1, ownerEmail=jasiekziom@gmail.com, roomId=1, startingCash=1000.0, states=[PortfolioState(id=2, fromDate=2020-01-01 00:00:00.0, to=Mon Jan 06 00:00:00 CET 2020, cash=300.0, positions=[Position(id=3, ticker=MSFT, quantity=2), Position(id=4, ticker=AAPL, quantity=3)]), PortfolioState(id=null, fromDate=Tue Jan 07 00:00:00 CET 2020, to=Sun Sep 14 02:00:00 CEST 3197, cash=290.28, positions=[Position(id=null, ticker=MSFT, quantity=2), Position(id=null, ticker=AAPL, quantity=3), Position(id=null, ticker=NIO, quantity=3)])])
Saved portfolio : Portfolio(id=1, ownerEmail=jasiekziom@gmail.com, roomId=1, startingCash=1000.0, states=[PortfolioState(id=2, fromDate=2020-01-01 00:00:00.0, to=Mon Jan 06 00:00:00 CET 2020, cash=300.0, positions=[Position(id=3, ticker=MSFT, quantity=2), Position(id=4, ticker=AAPL, quantity=3)]), PortfolioState(id=5, fromDate=null, to=null, cash=null, positions=null)])
Portfolio object after saving Portfolio(id=1, ownerEmail=jasiekziom@gmail.com, roomId=1, startingCash=1000.0, states=[PortfolioState(id=2, fromDate=2020-01-01 00:00:00.0, to=Mon Jan 06 00:00:00 CET 2020, cash=300.0, positions=[Position(id=3, ticker=MSFT, quantity=2), Position(id=4, ticker=AAPL, quantity=3)]), PortfolioState(id=5, fromDate=null, to=null, cash=null, positions=null)])
我已尝试通过将 CascadeType.MERGE 与 PERSIST 一起使用来解决此问题,但它会导致状态重复。我正在使用内存中的 h2 数据库和没有休眠的普通 JPA。我正在使用 JPARepository 接口中的默认保存方法。 你能解释一下发生了什么以及为什么会发生吗?我该如何解决这个问题?
【问题讨论】:
-
只是为了澄清:所有的对象都是新的,它们应该被持久化吗?您是否在持久化之前手动插入 ID?顺便说一句:考虑change the fetch type to lazy。另外,unidirectional
@OneToManymight not be the best idea。考虑将其更改为双向@OneToMany或只是单向@ManyToOne。 -
@FelixSeifert Portfolio 是一个已经存在的对象,该对象已从 DB 及其所有子项中获取。在
System.out.println(" Portfolio : " + portfolio.toString())上面运行的代码创建了一个新的 PortfolioState 并将其添加到 Portfolio.states。我会应用你的提示回复你。 -
当投资组合对象确实存在时,它可能不会级联更改以保存其子项。您只需设置
CascadeType.PERSIST,即仅当父对象本身被持久化时,持久化操作才会级联到子级。FetchType.EAGER不是这个原因(见你的答案)。
标签: java spring spring-boot jpa spring-data-jpa