2

I have a question about using springboot with thymeleaf and relationship management.

I have three objects that needs to be fully bi-directional:

obj1(Many)--TO--(One)obj2(One)--TO--(Many)obj3

They are setup:

public class Obj1 {
@Id
private long id;
@ManyToOne(cascade=CascadeType.ALL)
private Obj2 obj2;

public class Obj2 {
@Id
private long id;
@OneToOne
private User planUser
// Other fields
@OneToMany(mappedby = obj2)
private List<Obj1> obj1;
@OneToMany(mappedby obj2)
private List<Obj3> obj3;

public class Obj3 {
@Id
private Long id;
@ManyToOne
private Obj2 obj2;

In terms of the view, there is a page called view1 which is for populating Obj1. This works.

There is another page called view2 for : 1. Displaying some basic details from Obj1 2. Populating/Updating Obj2 and Obj3

The problem is on submitting view2 to update/create Obj2 and Obj3.

I have tried to get the controller to call methods on the Obj1 Service:

@Override
@Transactional
public Obj1 associateObj1ToObj2(Long Obj2Id, Obj1 newObj1) {
    final Obj2 obj2 = ojbj2Repository.findOne( obj2Id );
    obj2.getObj1().add( newObj1);
    newObj1.setObj2( obj2 );
    return obj1Repository.save( newObj1 );
} 

Questions:

  1. Even if I have the @Post in the form controller obj2Repo.save(obj2) when I try to recall it in associateObj1ToObj2- the values that should have been saved (like userPlan) aren't. Why?
  2. Can and should a single root object serve multiple pages in a situation like above? (The suggested alternative apparently is to create a hybrid class to use for backing pages like view2 - link to git example be great (is this called a DTO)).
  3. Is it correct that springboot will not handle the relationship settings, at least in a case where a childs child needs to be updated)
  4. What is the life of the Hibernate session?

Note: By Many relationships really should be called few - the collections on the relationships almost always number less than 10.

This answer seems to be partly related : Could not initialize proxy - no Session

Al Grant
  • 2,102
  • 1
  • 26
  • 49

1 Answers1

3

I was going to discuss both sides of using conversation based support frameworks here, however, I think that is irrelevant in hindsight. While those frameworks can help with the boilerplate necessary to ultimately handle view/controller/domain object consistency, I don't think that changes how you should be designing your controllers and views to interact with users.

I would say most developers often take the stance of sending their entity beans to the view to be that backing bean representation. For small, non-complex, imo play projects that will suffice but typically this approach starts to break down when entity relationships or UI layouts become complex.

By using non-entities as your backing beans for your view, you allow your UI and View to grow organically without be constrained by decisions and choices to model your database tables and persistence relationships. It also means that you can leverage database schema design choices without influencing how you layout and interact with users in your UI. This becomes extremely useful during refactoring your code or improving the user's experience through UI changes.

Even if I have the @Post in the form controller obj2Repo.save(obj2) when I try to recall it in associateObj1ToObj2- the values that should have been saved (like userPlan) aren't. Why?

Did the form actually send that information back in the post?

Lets assume we have a very simple object:

class SomeEntity {
  private Integer id;
  private String name;
  private String address;
  private List<String> nicknames;
}

If all the form allows is the user to change their address but the form doesn't actually send us back the value for name, it'll be empty when we inspect that SomeEntity instance in the controller. Is that really what we want? The same happens if you have a relationship. If the form doesn't actually send us back the list of nick names, that relationship will be empty too.

To me, this highlights why backing beans for views should ultimately represent the view's use case and only that. We know precisely what fields the view needs and returns and we manage the lifecycle of that data independent of the data which our entity models require to be considered valid both in the perspective of our application and the persistence provider.

Can and should a single root object serve multiple pages in a situation like above? (The suggested alternative apparently is to create a hybrid class to use for backing pages like view2 - link to git example be great (is this called a DTO)).

This is simply a preference design choice. A single backing bean for a view is perfectly fine. There are reasons to consider multiple backing beans though:

  1. Treat your view as a composition of smaller pieces.
    This allows code reuse of those components in other UI layouts.
  2. Isolate mutable vs immutable form attributes.

Typically I prefer (1) as the default choice. The only time I advocate the use of (2) are situations where the view has a fair amount of read-only fields giving the user contextual information and they only can mutate a smaller portion of the overall number of attributes.

Is it correct that springboot will not handle the relationship settings, at least in a case where a childs child needs to be updated)

This isn't a spring-boot concern. A lot of precisely how this happens is dependent on other factors as I have mentioned previously.

  1. What data was serialized in the form and conversely sent back to the controller.
  2. How was the form organized, was it serialized back properly.
  3. Are you using a conversation framework / configuration.

What is the life of the Hibernate session?

This varies depending on your configuration setup.

Spring boot does allow the OpenSessionInView or OpenEntityManagerInView filter to be used which extends the lifecycle of a Hibernate session to the point that the web request has ended. In my opinion, you should never use this other than for simple prototypes as it comes with its own share of problems, which include performance and unexpected insertions, updates, and deletions based on poor assumptions or code.

Naros
  • 19,928
  • 3
  • 41
  • 71