Jan Chabik
Jan Chabik

Reputation: 99

JPA Persist not persisting children entities

I have a problem with persisting children entities even though I'm using a CascadeType.PERSIST. When i add new children object to a parent it's persisted but it's fields are made null.

My Entities:

@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;

}

When the following lines of code get executed, PortfolioState get's persisted with all except id as 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, [email protected], 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, [email protected], 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, [email protected], 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)])

I've tried fixing this issue by using CascadeType.MERGE along with PERSIST, but it results in states duplicating. I'm using h2-in-memory database and plain JPA without hibernate. I'm using a default save method from JPARepository interface. Can you explain what and why is happening ? How do i fix this ?

Upvotes: 0

Views: 1164

Answers (1)

Jan Chabik
Jan Chabik

Reputation: 99

@FelixSeifert helped me figured out this one. It seems that FetchType.EAGER was causing the problem. I've switched to FetchType.LAZY and CascadeType.ALL. I've also added a bidirectional @ManyToOne in PortfolioState.java.

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;

}

Upvotes: 1

Related Questions