Best practices for developing JPA based master-details tables

Hi all,

I am tryng to develop master-detail page, represented by two tables, based on Oracle scott/tiger schema (so, this is well-know Dept/Emps relationship). So, I have two JPA entities, representing two DB tables.

For both table’s ContainerDataSource, I am using
Viritin ListContainer:

https://vaadin.com/directory#!addon/viritin

which basically work with List. - exaclty what master Dept Entity @NamedQuery “findAll” returns , and @OneToMany relationship filed for details Employees also. So, Viritin;s ListContainer fits very hadny with what I already have in my entities - just perform findAll, or take relationship List and I am already have List for build ContainerDataSource for details (Emps) table


Now, about master-details synchronization:

Because I am working with detached entites, and PersistenceUnit is RESOURCE_LOCAL (app should work on Tomcat), for the @OneToMany annotation I am forced to use fetch=FetchType.EAGER. This way, I am able to have detail Employyes even in the detached mode. So, when user select/changes current row in the master (Depts) table, int the table’s ValueChangeListener, I am rebuild child ListContainer by simply taking @OneToMany List from selected Dept.

So far, so good.

But, wondering, whether this is the best approach for taking details entities LIst, considering CRUD operation on details table? Because, in that scenario, for master Dept, I am forced to maintain related Employeed List instance by myself. Each time when adding new deails Employee, I need to add new Employee instance to the corresponding List. I know, this is required by JPA also (maintain entity graph in memory in sync. with database model), and this is performance efficient (no need to perform JPA Query in order to take Emps details), but this is not esy task at all. For example, when deleting some Emps for particular Dept, , going to another one app page, and goind back to Dept/Emps page again, I am able to see in fact deleted employees for that master, so something goes wrong im memoty model, I am have hard to find bug somewhere :frowning: The things are just becames complicated because of EntityManager.
merge()
behaviour - it returns _another _instance of just edited Employee entity,so I am forrced to _replace old one entity in the table;s Container with tha new instance

Because of that, would it be better (at least simpler) to use parametrized @NamedQuery ("
select o from Employees o where o.department =…"
) each time master Dept changes? Because it guaranties I will have correct Employee list each time user perform CRUD operation on detail employees table. And, after every CRUD operation, rebuild appropriate Container based on query result. At the same time, this have perfomanc cost.

What you are people doing, what is the best practice, and, is there any CRUD master/detal demo, which demonstrates the best techniques? it is simply strange that for a lot of tools/frameworks, there is one such example…or still exists?

Hi,

You have a rather large “question”. If you could share a small app stub I could probably suggest something more concrete, but here are couple hints that might help you to get forward.

First of, I’d not be afraid of fetching a fresh set of entities from the backend (to e.g. Table or Select components). That is a really easy method to ensure you have valid and fresh data for your UI and it shouldn’t be slow. Maintaining an up-to-date datamodel in memory, might indeed be a bit better performing option, but it requires lots of careful programming, especially in clustered environment. Listing data from DB might be/become slow if you use eager fetch type or some other inefficient DB queries.

That’s why you most often shouldn’t use FetchType.EAGER, if you are aiming for good DB scalability. If you need the related entities in your Table or Grid listings, it is much more efficient to fetch them with a join clause (TIP: try using entity graphs if you are using JPA 2.1). In many cases you don’t need the relations in your Table/Grid, at least not all of them. Then, when you select an entity for editing, you should fetch a fully loaded version of it that your pass for your form UI. Even with JPA, there is still a database behind the scenes, and some things just need to be done in the way RDBMSs have been designed to be used.

Also check our recent
JPA best practices webinar
we had in the autumn. It might give you some good tips for your application.

cheers,
matti

Hi,

Thanks for response, your reply satisfies me at this moment…
I recommend, however, once again (this is more intended for Vaadin team in general), to consider creating a non-trivial JPA CRUD application, which demonstrates all those best techniques. I believe that something like that has brought a lot of new customers, because the highest number of applications is based precisely on that.

Thanks again…

Agreed. I have also stated it many times that we really should provide better full stack examples. Before we come up with some official demo, you can check out
this example app
, it might give you some answers.

cheers,
matti

Just one question, regarding Viritin.
Is there place to ask Viritin specific question?
For example, I am not sure that your ListContainer conforms to the

https://vaadin.com/api/com/vaadin/data/Container.html

interface. Lets take a look at getItem() method:
"Gets the Item with the given Item ID from the Container.
If the Container does not contain the requested Item, null is returned.
"

Now, take a look at ListConainer implementation:

public Item getItem(Object itemId) {
    if (itemId == null) {
        return null;
    }
    return new DynaBeanItem<T>((T) itemId);
}

So, except for null values, metbhod allways returns DynaBeamItem instance, regardless of fact that container may not contain that item…huh?

Hi,

That indeed is a “violation of specification”, but it is done on purpose. Infact, I think this is a but in container specification. If the container would make a contains check there, it could be really expensive operation for larger datasets.

Does that cause some harm somewhere? In my usage that has never been an issue. If you need to check for existences of some entity, I’d do it straight from the original collection (or service object) anyways.

The “violation of specification” should definitely be mentioned in javadocs, but that’s all I’d do for it with this knowledge.

cheers,
matti