spring-boothibernatejpaspring-data-jpahibernate-onetomany

How to get the child elements of a parent in Hibernate?


@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Portfolio {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name")
    private String name;


    @OneToMany(mappedBy="child", fetch = FetchType.EAGER)
    private List<PortfolioChildMap> portfolioChildMap;
}
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PortfolioChildMap {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Portfolio parent;

    @ManyToOne
    @JoinColumn(name = "child_id")
    private Portfolio child;


}
@Repository
public interface PortfolioChildMapRepository extends JpaRepository<PortfolioChildMap, Integer> {}

@Repository
public interface PortfolioRepository extends JpaRepository<Portfolio, Integer> {}


@SpringBootApplication
public class HibernateApplication {
    public static void main(String[] args) {
        SpringApplication.run(HibernateApplication.class, args);
    }

    @Bean
    CommandLineRunner commandLineRunner(PortfolioRepository portfolioRepository,
                                        PortfolioChildMapRepository portfolioChildMapRepository){
        return args -> {
            Portfolio parent = Portfolio.builder().name("Portfolio").build();
            portfolioRepository.save(parent);

            Portfolio childrenA = Portfolio.builder().name("Children_A").build();
            portfolioRepository.save(childrenA);

            Portfolio childrenB = Portfolio.builder().name("Children_B").build();
            portfolioRepository.save(childrenB);




            portfolioChildMapRepository.save(PortfolioChildMap.builder().parent(parent).child(childrenA).build());
            portfolioChildMapRepository.save(PortfolioChildMap.builder().parent(parent).child(childrenB).build());

        };
    }
}

I want to get a children's portfolio for each parent portfolio. What is the best way to implement this ? is it possible to add some method to PortfolioRepository and get all child portfolios or it should be done from source code ?

enter image description here

enter image description here

As you can see table PortfolioChildMap contains two columns parent_id and child_id. I want to get a Portfolio list for parent Portfolio. Is it possible to implement this on PortfolioRepository side ? I want to call some methods and get a list with or without childe portfolios or somehow get child portfolios using Stream API

@Repository
public interface PortfolioRepository extends JpaRepository<Portfolio, Integer> {
    List<Portfolio> some_method_here(parent id);

}

or using Stream API but frankly say i don't know how to do this

Optional<Portfolio> portfolioOptional = portfolioRepository.findById(1);
if(portfolioOptional.isPresent()){
    Portfolio portfolio = portfolioOptional.get();
    List<Portfolio> childrenPortfolio =  portfolio.getPortfolioChildMap().....
}

Solution

  • You have to establish a bidirectional relationship between 'Portfolio' and 'PortfolioChildMap', update 'Portfolio' entity by replacing:

       @OneToMany(mappedBy = "child", fetch = FetchType.EAGER)
    

    with:

       @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
    

    Alternatively, you can implement a JPA query like this:

    @Repository
    public interface PortfolioRepository extends JpaRepository<Portfolio, Integer> {
        @Query("SELECT pc.child FROM PortfolioChildMap pc WHERE pc.parent.id = :parentId")
        List<Portfolio> findChildrenByParentId(@Param("parentId") Integer parentId);
    }
    

    Then in your service class you can call the method:

    Optional<Portfolio> portfolioOptional = portfolioRepository.findById(parentId);
    if (portfolioOptional.isPresent()) {
        Portfolio parent = portfolioOptional.get();
        List<Portfolio> childrenPortfolios = portfolioRepository.findChildrenByParentId(portfolioOptional.getId());
    }