Search code examples
grailsmappinggrails-ormmany-to-one

Grails define mapping property in has many relationship


i have two domain classes with has many mapping.

One class :

class Line  {

static belongsTo = [header : Header]

Long invoiceId
Long lineNumber
Long oneId
Long secondId
Long thirdId

static mapping = {
    table('LINES_2_V')
    version(false)
    id composite: ['invoiceId', 'lineNumber']
}

}

another class :

class Header {

static hasMany = [lines: Line]
Long id

static mapping = {
    table('HEADERS_2_V')
    version(false)
    id column:'INVOICE_ID'
}

}

Createria :

Header.createCriteria().list() {

createAlias('Lines', 'l', CriteriaSpecification.INNER_JOIN)

if (oneId) {
    eq('l.oneId', oneId)
} else {
    isNull('l.oneId')
}
if (secondId) {
    eq('l.secondId', secondId)
}else {
    isNull('l.secondId')
}
if (thirdId) {
    eq('l.thirdId', thirdId)
}else {
    isNull('l.thirdId')
}

}

and i get following error :

ORA-00904: "L1_"."HEADER_ID": invalid identifier

Hibernate generated select looks like this :

Hibernate: select * from ( select this_.INVOICE_ID as INVOICE1_0_1_
from HEADERS_2_V this_, 
LINES_2_V ihl1_ where this_.INVOICE_ID=l1_.header_id and ihl1_.project_id is null 
and ihl1_.transaction_id is null and ihl1_.po_header_id is null ) where rownum <= ?

why it is trying to map by HEADER_ID ? how to make it to map by INVOICE_ID ?


Solution

  • Because that is your back reference to Header that is stored in Line table. Your tables are like this:

    Lines_2_V : invoice_id, line_number, header_id, one_id, second_id ,thid_id

    Header_2_V: invoice_id

    Since Gorm already has Header's id stored in Line table, its using that to join them.

    When you have belongTo as a map:

    static belongsTo = [header : Header]
    

    Grails/Gorm will create a back reference in your table. You can also use

     static belongsTo =  Header
    

    Which gorm creates intermediate table to join them for more information refer to GORM Gotchas article by Peter Ledbrook


    btw, Lines should be lines:

    createAlias('Lines', 'l', CriteriaSpecification.INNER_JOIN)
    

    should be

    createAlias('lines', 'l', CriteriaSpecification.INNER_JOIN)