Announcement Announcement Module
Collapse
No announcement yet.
Design issue with @OneToMany etc. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Design issue with @OneToMany etc.

    Hi guys, I'm currently learning web applications design using Spring / Hibernate, and I have come across a design issue. The situation is very simple - there are 3 tables Users, Report, ReportChange. Each Report is created by a User, and each ReportChange is created by user and it considers a concrete Report. So there are a few, straightforward one-to-many and many-to-one foreign key relation.
    Following hibernate docs and tutorials I configure all one-to-many relations as lazy (so that collections are only loaded when needed) and many-to-one as eager. I wanted to create a service layer to handle all db related operations (so all ops in this layer would be marked @Transactional) and through DAOs (with hibernate session retrieved with SessionFactory, getCurrentSession()). Unfortunately with such solution, when I return User objects to the view, the Reports collection for is not loaded yet and, as the view logic is not in transaction scope I can not retrieve it... On the other hand if I use eager loading of Reports and Report changes for user, I will be loading whole database when retrieving user list... Makes no sense either.
    What I'm considering now is *not* to use the many-to-one (and such) annotations but, instead to implement old fashioned DAO methods - getReportsForUser(), getChangesForReport() etc. That in my opinion allows finer grading of db access. There are of course downsides of this approach but in my case I don't see any other option.
    Or maybe I should just make the transaction scope wider?

    I'd really appreciate any hints or suggestions for reading.

  • #2
    If you haven't already, you can read about the Open session in view pattern.

    I sometimes write methods that return an entity prefetching the lazy collections that I know I will be accessing in the view, like getUserPrefetchingReports()

    If it makes sense to have the Reports eagerly loaded for User, then you could "ease" the list users queries by using a lightweight view bean for User that only contains/queries the main attributes.

    Comment


    • #3
      Hi,

      thanks for the advice man, I'll definitely look into the osiv pattern!
      As for the other solutions I guess that with them you don't actually use the automatic hibernate @OneToMany etc bindings but rather fetch the requested collections "manually" with concrete methods in DAO or service layer? Or do you use the binding and force the hibernate to fill the collection by for example retrieving first object (I'm asking as I did not see any method in the API which forces automatic collection loafing)?
      I guess that with th last solution you don't use such mappings at all?

      anyway thanks a lot for hints.

      Comment


      • #4
        In both cases I keep the hibernate bindings.

        If the collections are mapped as lazy, and I write a method getUserPrefetchingReports(), then I explicitly initialize the lazy collection with Hibernate.initialize(u.reports) in the DAO method.

        If the collections are mapped as not lazy, and I need a lighter query for all Users without all Reports, then all I do is query the attributes I am interested in. HQL like this:

        Code:
        select new com.example.LightUserViewBean(u.name, u.id, u.joinDate) from User u; // ignore u.reports

        Comment

        Working...
        X