Grails
  1. Grails
  2. GRAILS-828

many-to-many obviously stores relations in wrong columns

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 0.4.1
    • Fix Version/s: 0.5-RC1
    • Component/s: Persistence
    • Labels:
      None
    • Environment:
      OSX mysql or postgres

      Description

      steps to reproduce the error:

      1. install testapp attached with this report grails version is 0.4.1 but also occures on 0.4
      2. configure database (i used mysql at localhost databasename tester user root no password)
      3. run application
      4. create two categories (important to see the error)
      5. create 1 product
      6. edit product and add two categories
      7. check table product_category should look like
      --------------------------+

      categories_id products_id

      --------------------------+

      1 1
      1 2

      --------------------------+

        Issue Links

          Activity

          Hide
          Burkard Endres added a comment -

          here the conversation that lead to this report

          If one of you can formulate a test application using grails bug-report
          and attach it to an issue that would be helpful

          Cheers

          On 2/18/07, groovyjoe <joe.yenoom@gmail.com> wrote:
          >
          >
          > I have similar results when I save the objects through a service. If I save
          > it from the ApplicationBootstrap class the foreign keys are correct. In both
          > I am using the same <owner>.add<Child> GORM method (e.g. author.addBook).
          >
          > I'm using Grails 0.4.1
          >
          > Joe
          >
          >
          > Burkard Endres wrote:
          > >
          > > Hi,
          > >
          > > i am still a little confused about manyToMany mapping
          > > i did a simple example with two Domainclasses
          > > Author and Book
          > >
          > > class Author

          { > > String name > > > > static hasMany = [books:Book] > > > > }

          > >
          > > class Book

          { > > > > String name > > static hasMany = [authors:Author] > > def belongsTo = Author > > }

          > >
          > >
          > >
          > > swob=> select * from author;
          > > id | version | name
          > > ----------------
          > > 308 | 0 | test
          > > 310 | 0 | test
          > > (2 rows)
          > >
          > > swob=> select * from book;
          > > id | version | name
          > > ----------------
          > > 309 | 0 | test
          > > (1 row)
          > >
          > > swob=> select * from author_book;
          > > authors_id | books_id
          > > -----------+---------
          > > 309 | 308
          > > (1 row)
          > >
          > >
          > > with this values in the collection table it works but i would have
          > > expected that the 308 is in the authors_id column of author_book
          > > and the 309 in the books_id, but perhaps i am missing something?
          > >
          > > any clarification would be great.
          > >
          > > Burkard
          > >

          Show
          Burkard Endres added a comment - here the conversation that lead to this report If one of you can formulate a test application using grails bug-report and attach it to an issue that would be helpful Cheers On 2/18/07, groovyjoe <joe.yenoom@gmail.com> wrote: > > > I have similar results when I save the objects through a service. If I save > it from the ApplicationBootstrap class the foreign keys are correct. In both > I am using the same <owner>.add<Child> GORM method (e.g. author.addBook). > > I'm using Grails 0.4.1 > > Joe > > > Burkard Endres wrote: > > > > Hi, > > > > i am still a little confused about manyToMany mapping > > i did a simple example with two Domainclasses > > Author and Book > > > > class Author { > > String name > > > > static hasMany = [books:Book] > > > > } > > > > class Book { > > > > String name > > static hasMany = [authors:Author] > > def belongsTo = Author > > } > > > > > > > > swob=> select * from author; > > id | version | name > > ---- ------- ----- > > 308 | 0 | test > > 310 | 0 | test > > (2 rows) > > > > swob=> select * from book; > > id | version | name > > ---- ------- ----- > > 309 | 0 | test > > (1 row) > > > > swob=> select * from author_book; > > authors_id | books_id > > ----------- + --------- > > 309 | 308 > > (1 row) > > > > > > with this values in the collection table it works but i would have > > expected that the 308 is in the authors_id column of author_book > > and the 309 in the books_id, but perhaps i am missing something? > > > > any clarification would be great. > > > > Burkard > >
          Hide
          Graeme Rocher added a comment -

          I know it might not seem logical when you look at the table but this is actually correct. The 1 product is represented by the "products_id" column. The name "products" comes from the collection on your Category class and hence relates

          class Category {
             static hasMany = [products:Product]
             static belongsTo = Product
          }
          
          class Product {
            static hasMany = [categories:Category]
          }
          

          I imagine your code looks like this:

          new Product()
                     .addCategory(new Category())
                     .addCategory(new Category())
                     .save()
          

          So whats happening here is the product id is stored in the categories_id column because the name of the relationship is "categories". The category id is stored in the products_id because it relates to the products relationship on the Category class.

          In other words the column relates to the name of the "relationship" and not the class name. It is the only way we can do this because there might be multiple many-to-many relationships

          Show
          Graeme Rocher added a comment - I know it might not seem logical when you look at the table but this is actually correct. The 1 product is represented by the "products_id" column. The name "products" comes from the collection on your Category class and hence relates class Category { static hasMany = [products:Product] static belongsTo = Product } class Product { static hasMany = [categories:Category] } I imagine your code looks like this: new Product() .addCategory( new Category()) .addCategory( new Category()) .save() So whats happening here is the product id is stored in the categories_id column because the name of the relationship is "categories". The category id is stored in the products_id because it relates to the products relationship on the Category class. In other words the column relates to the name of the "relationship" and not the class name. It is the only way we can do this because there might be multiple many-to-many relationships
          Hide
          Martin van Dijken added a comment -

          Even if there are multiple many-to-many relationships, should they not each have a different table?

          I know this can easily be fixed by the Grails user by overriding the mapping, but the naming is very counterintuitive and therefore will most likely always be adjusted. Convention over configuration ideals suggest fixing this somehow...

          Show
          Martin van Dijken added a comment - Even if there are multiple many-to-many relationships, should they not each have a different table? I know this can easily be fixed by the Grails user by overriding the mapping, but the naming is very counterintuitive and therefore will most likely always be adjusted. Convention over configuration ideals suggest fixing this somehow...
          Hide
          Graeme Rocher added a comment -

          should what each have a different table?

          There is a separate table created for the mapping column a many to many results in 3 tables.. 2 for the domain classes an a mapping table

          Show
          Graeme Rocher added a comment - should what each have a different table? There is a separate table created for the mapping column a many to many results in 3 tables.. 2 for the domain classes an a mapping table
          Hide
          Dimo Velev added a comment -

          You can fix this (imho bug) by doing something like:

           
          class Category {
             static hasMany = [products:Product]
             static belongsTo = Product
             static mapping = {
                 products(column: 'category_id')
             }
          }
          
          class Product {
            static hasMany = [categories:Category]
             static mapping = {
                 categories(column: 'product_id')
             }
          }
          
          Show
          Dimo Velev added a comment - You can fix this (imho bug) by doing something like: class Category { static hasMany = [products:Product] static belongsTo = Product static mapping = { products(column: 'category_id') } } class Product { static hasMany = [categories:Category] static mapping = { categories(column: 'product_id') } }

            People

            • Assignee:
              Graeme Rocher
              Reporter:
              Burkard Endres
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development