简体   繁体   中英

Weird issue with hasMany in Grails using PostgreSQL. “ERROR: column <column_name> does not exist”

I'm having a hard time trying to get "hasMany" to work in Grails 2.0.1 using PostgreSQL 9.1. I got two tables:

CREATE TABLE "_QUESTIONS"
(
  "QUESTION_ID" bigint NOT NULL,
  "TEXT" text,
  CONSTRAINT "PK" PRIMARY KEY ("QUESTION_ID" )
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "_QUESTIONS"
  OWNER TO postgres;

CREATE TABLE "_ANSWERS"
(
  "ANSWER_ID" bigint NOT NULL,
  "TEXT" text,
  "QUESTION_ID" bigint,
  CONSTRAINT "PK1" PRIMARY KEY ("ANSWER_ID" ),
  CONSTRAINT "FK" FOREIGN KEY ("QUESTION_ID")
      REFERENCES "_QUESTIONS" ("QUESTION_ID") MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "_ANSWERS"
  OWNER TO postgres;

and two domain classes:

class Question {
    String text

    String toString(){
        text
    }

    static constraints = {
    }    
    static hasMany = [answers: Answer]    
    static mapping = {
        table '`_QUESTIONS`'
        version false
        id generator: 'identity'
        id column: '`QUESTION_ID`'
        text column: '`TEXT`'
    }
}

class Answer {
    String text
    Question question

    String toString(){
        text
    }

    static constraints = {
    }

    static  belongsTo = [question : Question]

    static mapping = {
        table '`_ANSWERS`'
        version false
        id generator: 'identity'
        id column: '`ANSWER_ID`'
        text column: '`TEXT`'
        question column: '`QUESTION_ID`'
    }
}

I've generated Views and Controllers for both of them and when I try to browse a particular Question I get the following error:

URI:/hasManyTest/question/show/1
Class:org.postgresql.util.PSQLException
Message:ERROR: column answers0_.question_id does not exist Position: 8

with stack trace:

Line | Method
->>    8 | runWorker in \grails-app\views\question\show.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Caused by SQLGrammarException: could not initialize a collection: [hasmanytest.Question.answers#1]
->>   26 | doCall    in C__Users_root_IdeaProjects_hasManyTest_grails_app_views_question_show_gsp$_run_closure2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     55 | run       in C__Users_root_IdeaProjects_hasManyTest_grails_app_views_question_show_gsp
|   1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    603 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run . . . in java.lang.Thread

Caused by PSQLException: ERROR: column answers0_.question_id does not exist
  Position: 8
->> 2103 | receiveErrorResponse in org.postgresql.core.v3.QueryExecutorImpl
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   1836 | processResults in     ''
|    257 | execute . in     ''
|    512 | execute   in org.postgresql.jdbc2.AbstractJdbc2Statement
|    388 | executeWithFlags in     ''
|    273 | executeQuery in     ''
|     96 | executeQuery in org.apache.commons.dbcp.DelegatingPreparedStatement
|     26 | doCall    in C__Users_root_IdeaProjects_hasManyTest_grails_app_views_question_show_gsp$_run_closure2
|     55 | run . . . in C__Users_root_IdeaProjects_hasManyTest_grails_app_views_question_show_gsp
|   1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run       in java.lang.Thread

I've done a lot of gymnastics for the past couple of days and nothing seems to help, when I remove association everything works fine though. Am I missing something obvious?

The issue appears to be a mismatch between assumptions made by Grails/GORM mapping and the SQL used to create the tables.

If you omit the quotes around table and column names in the above SQL, tables and columns will be case-insensitive. From http://wiki.postgresql.org/wiki/Things_to_find_out_about_when_moving_from_MySQL_to_PostgreSQL :

Database, table, field and columns names in PostgreSQL are case-independent, unless you created them with double-quotes around their name, in which case they are case-sensitive. In MySQL, table names can be case-sensitive or not, depending on which operating system you are using.

Taking Grails out of the equation, if you create the table using the following:

CREATE TABLE "_QUESTIONS"
(
  "QUESTION_ID" bigint NOT NULL,
  "TEXT" text,
  CONSTRAINT "PK" PRIMARY KEY ("QUESTION_ID" )
)
WITH (
  OIDS=FALSE
);

Then:

test=> select * from _questions;
ERROR:  relation "_questions" does not exist
LINE 1: select * from _questions
                      ^
test=> select * from _QUESTIONS;
ERROR:  relation "_questions" does not exist
LINE 1: select * from _QUESTIONS;
                      ^
test=> select * from "_QUESTIONS";
 QUESTION_ID | TEXT 
-------------+------
(0 rows)

However, if you create the table without the quotes around table and column names:

CREATE TABLE _QUESTIONS
(
  QUESTION_ID bigint NOT NULL,
  TEXT text,
  CONSTRAINT PK PRIMARY KEY (QUESTION_ID)
)
WITH (
  OIDS=FALSE
);

Then:

test=> select * from _questions;
 question_id | text 
-------------+------
(0 rows)

test=> select * from _QUESTIONS;
 question_id | text 
-------------+------
(0 rows)

test=> select * from "_QUESTIONS";
ERROR:  relation "_QUESTIONS" does not exist
LINE 1: select * from "_QUESTIONS";
                  ^

I've managed to figure this out. Turned out, somewhy ORM tries to access association column through its lowercased name, changing the name solved the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM