• Post Reply Bookmark Topic Watch Topic
  • New Topic

Populating a datatable from @onetomany collection

 
Randy Maddocks
Ranch Hand
Posts: 92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, I am having a hard time trying to wrap my head around trying to get a couple of columns in a datatable populated with values from a @OneToMany collection. The concept is simple but my brain refuses to grasp it!! I will try to make this brief...

I have several forms built with primefaces 3.5 using NetBeans 8 IDE on a JBoss EAP 6.21 server, and JPA 2.1 annotations. Data is extracted from an Oracle 11 database, which consists of several lookup tables, as well as a primary table and secondary table. Using the EntityManager createQuery method I query the database, which of course returns a resultset. The query grabs all records from the primary, as well as values from 2 specific columns of the secondary database, based on search criteria entered by the user on a primefaces search form. The returned results are then iterated through, this is where I am trying to get the values from the secondary table to populate specific fields in the datatable.

Here is the applicable code from the list.xhtml form containing the datatable:



"Primary" Entity class:


"Secondary" Entity class:


EJB Facade:


Backing Bean:


As odd as the code may look (and I will completely understand anyone cringing as to some of the coding methods I use), specifically with the ui:repeat tags nested inside the datatable tag of the list.xhtml form, I strangely do see the values from the secondary table showing up in the form showing the results in a datatable. However, when the user clicks on a specific record in the returned resultset listed in the datatable, another form is opened and populated with the values from the datatable, but the 2 fields on that form that should be populated with the 2 values I referred to before from the secondary table (i.e. policy1Num and totalPayoutAmt) do not have the values in them. This is partly because I have those 2 fields in the editable form pointing to the managed bean of the secondary table (code from that bean not shown here), rather than the same "polNum.policy1Num" and "totPayout.totalPayoutAmt" var I am using in the list.xhtml form. To be honest, I have no idea how those values are being successfully returned into the datatable of the list.xhtml form - I happened to "stumble" across the use of the "polNum" and "totPayout" vars with the "policyPaymentCollection" list. I do not know how to do the same thing for those 2 fields in the editable form. Bottom line, if someone can enlighten me as to what I am doing wrong, or even provide something like an analogy to help me understand how a datatable gets populated, specifically with values in a @OneToMany collection, it would be greatly appreciated. I have read several articles about datatables and JPA usage, but as noted, my brain just doesn't seem to be grasping the concept. Sorry this isn't brief after all. Thank you.

Regards,

Randy Maddocks
 
Tim Holloway
Bartender
Posts: 18408
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, that's a little too information-dense for me to make an immediate precise analysis, but I'll do what I normally do in such cases and throw out some general advice and see if we can apply it.

First, standard caution #1: A JSF backing bean is not a Controller. It is a Model. In MVC, a Controller's one and only function is to transfer values from the Model (backing bean properties) to the View (xhtml) and vice versa. The application programmer does not write that code - it is an integral part of JSF. The Backing bean contails model data and its accessor (get/set methods), listeners (which are should not be transferring data) and action methods (which are non-MVC business methods).

Second, an observation. Since your ui:repeats are basically just generating a 1-column subtable, I'd recommend using a nested dataTable over a repeat/br loop.

On to the main topic.

A datatable renders a 2-dimensional display by retrieving and rendering values from its model. So you don't literally "populate the table", you populate the model. The model is an ordered collection of rows and columns, where the row is (almost always) some sort of uniform class instance and the columns are fixed properties of that class instance. In cases where you are using an ORM query as the basis, the datatable model would usually be an ordered coilection of table/view row objects.

Notice I keep using the word "ordered". JSF expects reproducible results, so unordered collections (generic collections, hashtables, and so forth) are not suitable as model collections and will usually cause an error.

You can - and people often do - use the ORM datamodel as directly as the JSF datatable GUI datamodel, but it isn't essential. Sometimes, for example, I'll introduce a façade object as the GUI datamodel row object so that I can translate database "boolean" values (which might be something like "T" and "F") to actual boolean values (JSF checkboxes require these). However, there is a 1-to-1 correspondence between GUI model rows and displayed dataTable rows. This is also sometimes leveraged by building a façade where the façade model rows are sorted in another order, some rows from the actual ORM model are omitted in the façade model or even extra rows are added. You have all sorts of flexibility there.

When the model object references another object in a 1-to-1 correspondence (or many-to-1), you can use EL notation to reference its properties for the dataTable value set. For example: "#{foreignPartyBean.manager.person.firstName}". When there is a 1-to-many or many-to-many correspondence but you only need to reference a single element in the secondary object, EL can handle that as well. For example: "#{foreignPartyBean.person.employee[3].birthDate}" or even "#{foreignPartyBean.person.employee['Fred Smith']}".

In cases where there is a need to reference a many-target in quantity, you either need to flatten the original returned object that will be used as a basis, build a façade that flattens it, or use a sub-table that references the secondary objects as the sub-model.

Finally, some general dataTable notes. In JSF2, a dataTable can reference an ordered collection such as a List or array directly as its "value" property. However, if you do that, then it becomes very cumbersome to determine what row a user has selected when clicking on a button or link in the table. So it's better to wrap the collection in a DataModel object. The DataModel allows using the unmodified GUI model collection while decorating it with useful properties - most notable the "getCurrentRow()" and "getRowIndex()" methods that action methods can use to know what row the action applies to.

Secondly, if you do nest dataTables, be aware that as of JSF2, the DataModel functions don't properly support sub-models. There are ways to determine what sub-row was selected, but they require doing some unpleasant things. That's also true, however for ui:repeat, so it's no reason not to use a nested dataTable.
 
Randy Maddocks
Ranch Hand
Posts: 92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Tim,

Thank you very much for your time and expertise, I really appreciate it. I understand your reference to my post being information-dense, I tried to include pertinent details without overdoing it. Obviously I got a little too wordy in the end. :(

I have considered DataModel and will look into it. I will also take into consideration your reference to unordered versus ordered results. I am going to print your reply and study it until it sinks deep into my subconscious. I know I have to understand how this works or I won't get anywhere. Thanks again for your help!
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!