Announcement Announcement Module
Collapse
No announcement yet.
Creating bidirectional many-to-many set Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Creating bidirectional many-to-many set

    I'm trying to create a bidirectional many-to-many relationship between 2 entities, but I end up getting 2 relationship tables instead of 1. For example:

    Code:
    field set --fieldName categories --element Category --cardinality MANY_TO_MANY --class Problem
    field set --fieldName problems --element Problem --cardinality MANY_TO_MANY --class Category
    this will create 2 tables:
    category_problems and problem_categories
    BTW, very neat how roo knows to call it categories instead of categorys. Which library does it use for this?

    Of course, I need that to be only 1 table and a bidirectional relationship... How do I specify this in roo?

  • #2
    I think I understand now how to create a bidirectional many-to-many set. The thing I needed above was to add --mappedBy to one of the sets (either --mappedBy categories to the problems set or vice versa).

    So now everything seems to work with the following annotation:
    Code:
    @javax.persistence.ManyToMany(cascade = javax.persistence.CascadeType.ALL, mappedBy = "categories")

    Comment


    • #3
      Are you able to update sets from both side of the relationship from the UI?

      Comment


      • #4
        Marc, no I'm not... So this is typical Hibernate behavior. If you only set a relation from an object that doesn't control that relationship, it doesn't get persisted. But roo clearly has a bug in creating web scaffolding that allows me to specify it anyway. It should either be persisted properly or not presented as an input on the webpage.

        Comment


        • #5
          Sorry, I am actually unclear what is not working here. Is there a specific hibernate bug (meaning the same application works fine with openjpa)? If so, the Roo web scaffolding is correct and we should see if hibernate can be fixed.

          -Stefan

          Comment


          • #6
            Hi Stefan, no it's not a hibernate bug... it's how hibernate is specified to work. When you declare a bi-directional relationship as in my example above where problems can have multiple categories and categories can have multiple problems, you have to declare 1 side as the controlling side. By adding mappedBy on the Category entity's problems relationship, I made the Problem entity the controlling side... so if I now set category.getProblems().add(problemABC), it will not get persisted. Instead I have to do problemABC.getCategories().add(category).

            The issue with roo is that roo creates scaffolding so that you can add problemABC to a category's list of problems. You hit save and it doesn't actually save. Correct hibernate behavior, but obviously not correct web behavior.

            Comment


            • #7
              Ah I see what you mean. The problem is that this is a rather rare problem which would be hard to pick up by Roo. So I am not sure if Roo should go so far in detecting cyclic reference problems of this kind. It would be hard for Roo to figure out which side is the owning side.

              I think the upcoming changes to the generated views will make your life a lot easier in this regard by allowing you to customize the view field handling in the jspx file by just changing a single line to resolve this issue. This should address the problem in the most convenient way without having to make commands even more complex to cater for such cases.

              Cheers,
              Stefan

              Comment


              • #8
                It's not a cycle problem though. It's a simple which side of the relationship controls problem. And we tell roo which side owns the relationship with the mappedBy option when creating the relationship field. All roo has to do is not generate the option to pick the other side of the relationship in the views for fields with mappedBy set on them.

                I'm anxious to see the upcoming changes to the generated views Stefan!

                Comment


                • #9
                  Ok, I think you could convince me . Can you please raise a feature improvement request for this?

                  -Stefan

                  Comment


                  • #10
                    I've encountered this issue during my introduction to Roo. My first use case involved a many-to-many relationship, and Roo 1.2.0M1 still provides scaffolding to update the relation from the non-controlling side. The changes aren't persisted. OpenJPA seemed to behave the same way as HIBERNATE. Is this part of the JPA standard and all providers will behave this way? Was Stefan ever persuaded that Roo should stop providing scaffolding for an operation that can't happen?

                    Comment


                    • #11
                      I have made some minor changes to improve the situation, but the general improvement to have Roo detect cyclic references has not been addressed. In fact it appears the community is not voting much on this issue (https://jira.springsource.org/browse/ROO-325). I think this can be resolved in many cases with a few minor tweaks by the developer rather than trying to automatically detect cyclic references in Roo.

                      Comment


                      • #12
                        Hopefully this will clear things up a little (doesn't look to be related to cyclic references).

                        1) The hibernate behavior of many-to-many relationships only allows for changes to the relationship to be persisted from the controlling side (the non-mappedBy side).

                        2) Spring Roo currently allows the user to try and modify this relationship from either side via the UI (even though it is only successfully persisted from the controlling side).

                        Until Roo changes the UI for the non-controlling side, try this workaround -
                        Modify the non-controlling side's jspx pages to not allow for changing relationships in two pages:
                        * Edit create.jspx to remove the line for the controlling entity - or set render="false" (you can't persist it, so why show it?)
                        * Edit update.jspx to add disabled="true" to the line for the controlling entity (show the current relation, but don't allow for any changes - they won't persist anyways)
                        Last edited by chrisdowden; Apr 28th, 2012, 06:50 PM.

                        Comment


                        • #13
                          This post was really usefull , now I understand better how works the manytomany relationship

                          Comment

                          Working...
                          X