【问题标题】:JPA Persist not persisting children entitiesJPA Persist 不持久化子实体
【发布时间】: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 @OneToMany might 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


【解决方案1】:

@FelixSeifert 帮我弄清楚了这个。似乎是FetchType.EAGER 导致了这个问题。我已切换到FetchType.LAZYCascadeType.ALL。我还在 PortfolioState.java 中添加了一个双向 @ManyToOne

public class Portfolio implements Serializable {

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

        private String ownerEmail;

        private Long roomId;

        private Double startingCash;

        @OneToMany(
                cascade = {CascadeType.ALL},
                orphanRemoval = true
        )
        private List<PortfolioState> states = new ArrayList<>();
}
public class PortfolioState implements Serializable {

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

    private Date fromDate;

    private Date to;

    private Double cash;

    @OneToMany(
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Position> positions = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    private Portfolio portfolio;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 2021-05-06
    相关资源
    最近更新 更多