1

I have a parent entity that has child entities (A) who in turn have their own child entities (B).

@Entity
public class Parent {
    @OneToMany
    Set<ChildA> childrenA;
}

@Entity
public class ChildA {
    @OneToMany
    Set<ChildB> childrenB;
}

I'm trying to display the data via a JSF dataTable. I would like to show the following.

Parent1 | NumberOfRelatedChildrenB
Parent2 | NumberOfRelatedChildrenB

To generate the rows in the dataTable I'm using a MangagedBean which gets a List of the Parents via a ParentFacade.findAll(), but I can't figure out how I can get a List of all the associated ChildBs. I guess I could add a @OneToMany ChildB relationship to the Parent entity, but I was hoping there would be a way to get them via the ChildA relationship?

Thanks in advance & sorry for the poor explanation!

Phll2
  • 185
  • 2
  • 6

2 Answers2

1

No, I suggest to avoid creating an additional relationship in this case. One way is to create a method in the managed bean that returns the number of related ChildB given an input Parent:

@ManagedBean
public class MyManagedBean {

    private List<Parent> parentList;//+getter
    private Map<Long, Long> relatedChildrenB = new HashMap<Long,Long>();//+getter
    @EJB
    private ParentFacade parentFacade;

    @PostConstruct
    public void init() {
        parentList = parentFacade.findAll();
        for (Parent parent : parentList) {
            relatedChildrenB.put(parent.getId(), parentFacade.getNumberOfRelatedChildrenB(parent));
        }

}

and in the facelets page:

<h:dataTable value="#{myManagedBean.parentList}" var="parent">
    ...
    #{myManagedBean.relatedChildrenB[parent.id]}
</h:dataTable>

and implement the corresponding queries in the facade service class.

Note that passing an object using parenthesis () in the previous revision in an EL expression requires EL 2.2 and thus either a Servlet 3.0 compatible container or applying some workaround. This solution does not need method call with parameters.

Finally, note that in my final edit I have followed the wise suggestion of skuntsel to avoid db calls in getter methods.

Community
  • 1
  • 1
perissf
  • 15,979
  • 14
  • 80
  • 117
  • This is a great answer, although I found it slightly more complex than Kaos' answer for my specific question, it allows you the added flexibility of being able to create any type of query you want against each of the parent entities via the EntityManager in the ParentFacade which is more useful in the wider scope of things, so thanks! – Phll2 Jul 23 '13 at 11:54
  • Thanks for the feedback. Keep in mind also the limits of the other answer, that I evidenced in my comment. – perissf Jul 23 '13 at 11:59
  • 1
    Why won't you prepare the needed data in a postconstruct method at once? Hitting DB within a 'getter' can hardly be described as being the best practice? Moreover, it's not a JSF-related problem, but rather a JPA one. It would be wise to (pre)load all related data in one shot. – skuntsel Jul 23 '13 at 15:31
  • @perissf I made some minor improvements and upvoted your answer. Feel free to rollback them if you don't like the edit :) – skuntsel Jul 23 '13 at 19:46
  • @perissf I thought that your answer would benefit if dependence on EL 2.2 were eliminated, but it is a standard nowadays so... probably it was good enough :) – skuntsel Jul 23 '13 at 19:54
0

Simple solution would be to put a method in Parent that returns children count and then use it in dataTable column e.g.

@Transient
public int getAllChildrenCount() {
   // iterate through children list and count
}

On view:

#{parent.allChildrenCount}
kaos
  • 1,598
  • 11
  • 15
  • The OP probably needs to eliminate duplicate children and this operation might be inefficient for large datasets. In this case a count query might be a better choice – perissf Jul 23 '13 at 09:18