At general I have problem with mapping: org.hibernate.MappingException: Repeated column in mapping for entity: os.comida.StoreDocumentRw column: Type (should be mapped with insert="false" update="false")
To introduce the problem: I have many document types where each document type differs just a little bit from any other. All of them have common properties: date, number, issuer etc. So I decided store all document types in one physical table (one - it's very important for me). To implement this I wanted use hibernate discriminator.
Below I'm pasting my source code. I have there a base class StoreDocument and two document types StoreDocumentRw and StoreDocumentWz.
class StoreDocument {
String type
Date documentDate
static mapping = {
table '"StoreDocument"'
version false
id column:'"StoreDocumentID"', generator:'sequence', params:[sequence:'STORE_DOCUMENT_SEQ']
discriminator column: '"Type"'
documentDate column:'"DocumentDate"'
type column:'"Type"'
}
}
class StoreDocumentRw extends StoreDocument {
String rwSpecificData
static mapping = {
discriminator value: 'rw'
rwSpecificData column:'"RwSpecificData"'
}
}
class StoreDocumentWz extends StoreDocument {
String wzSpecificData
static mapping = {
discriminator value: 'wz'
wzSpecificData column:'"WzSpecificData"'
}
}
And when I'm trying run an app I get mentioned earlier org.hibernate.MappingException: Repeated column in mapping for entity: os.comida.StoreDocumentRw column: Type (should be mapped with insert="false" update="false")
When I add type insertable: false, updateable: false to StoreDocumentRw mapping, it's still the same.
When I add type insertable: false, updateable: false to StoreDocument mapping, it's even worse:
ERROR hbm2ddl.SchemaExport - Unsuccessful: create table COMIDA2."StoreDocument" ("StoreDocumentID" number(19,0) not null, "DocumentDate" timestamp not null, "Type" varchar2(255 char), "Type" varchar2(-1 char) not null, "WzSpecificData" varchar2(255 char), "RwSpecificData" varchar2(255 char), primary key ("StoreDocumentID"))
ERROR hbm2ddl.SchemaExport - ORA-00957: duplicate column name
So I don't know where I should put this insertable/updateable thing to make it working. I'm using Grails 2.0.0 and Oracle 10g. Can anybody tell me what's wrong with my code?
Solution:
My mapping in StoreDocument was wrong. It's enough to cut String type and type column:'"Type"' and edit discriminator mapping like this discriminator column:[name:'"Type"',length:50], which in result gives:
class StoreDocument {
Date documentDate
static mapping = {
table '"StoreDocument"'
version false
id column:'"StoreDocumentID"', generator:'sequence', params:[sequence:'STORE_DOCUMENT_SEQ']
discriminator column:[name:'"Type"',length:50]
documentDate column:'"DocumentDate"'
}
}
In StoreDocument you have String type and discriminator column: '"Type"', so from your exceptions it looks like Grails is trying to create two columns of name type. Try changing the name of your String or discriminator-column and see if that corrects the issue.
To get around the issue with generating a varchar(-1) field try this: discriminator column:[name:'Type',length:10] from this JIRA GRAILS-5168. Of course, change the length to whatever you need.
Related
Setup: Grails 2.5.6 with Hibernate 4.3.10
I have a table with a string id. Thing is, its values are numeric strings, and this seems to mess up get() when I pass in a value such as "000000".
Domain class:
class Term
{
static mapping = {
id name: 'code', generator: 'assigned'
version false
code column: 'CODE'
description column: 'DESC'
}
String code
String description
}
Data looks like:
CODE || DESC
-------++---------------------------
000000 || The Beginning of Time
201715 || Post Secondary Winter 2017
201815 || Post Secondary Winter 2018
999999 || The End of Time
And then in testing I found the following:
assert Term.list() // works fine
assert !Term.get('foo') // works fine
//assert Term.get('000000') // throws exception
The exception thrown is:
Method threw 'org.springframework.orm.hibernate4.HibernateSystemException' exception.
Provided id of the wrong type for class Term. Expected: class java.lang.String, got class java.lang.Long
org.hibernate.TypeMismatchException: Provided id of the wrong type for class Term. Expected: class java.lang.String, got class java.lang.Long
So it looks like at some point the '000000' and the '201715' and whatever else are being inconveniently converted into Long objects. Using as String doesn't help either. Can anyone help me tell Hibernate that this String should be treated as a String?
This seems like a Grails bug and I'm guessing it is because you have not declared id to be of type String in your domain class because it is mapped to a different field (which makes sense).
You could try adding
String id
to your domain class although that may not caused desired behaviour with column generation.
I would suggest rather than using get() you could use findByCode() as you have mapped your id to the code field and the result should be the same.
Another headache :-( Someone please help. I'm simply trying to batch create domain instances using eachWithIndex within my bootstrap file in my Grails 3 project.
Here's my domain class...
package ttt_server
class TttPriority {
String name
int order
Date dateCreated
static constraints = {
name blank: false, nullable: false
order blank: false, nullable: false
dateCreated nullable:true, blank:true
}
}
Here's my bootstrap code for batch creation...
["Mortal","Major","Critical","Minor","Nice To Have"].eachWithIndex{ name, idx ->
new TttPriority(name: name, order: idx).save(flush:true)
}
I'm near to the point of pulling my hair out on this one.
Here's the error....
2017-07-31 16:30:41.755 ERROR --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values (0, 'Mortal', 0)' at line 1
2017-07-31 16:30:41.817 ERROR --- [ main] o.s.boot.SpringApplication >: Application startup failed
org.springframework.jdbc.BadSqlGrammarException: Hibernate operation: could not execute statement; bad SQL grammar [n/a]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values (0, 'Mortal', 0)' at line 1
at ...
order is a SQL keyword. You need to rename or remap that property.
static mapping = {
order column: "my_order"
}
Because order is a reserved word you have to use some other name for your column. Or surround your column name with backticks
Example
static mapping = {
order column: "order_col"
}
or
static mapping = {
order column: "`order`"
}
I am trying to map a column in grails to a sequence, but this column is not the id.
Integer seqCol
I have tried the following code in static mapping, I'm basically just switching 'id' with 'colum'.
column name: "seqCol", generator: "sequence", params:[sequence:"SEQUENCE_NAME"]
This returns an error on save, saying that seqCol cannot be null which leads me to believe the mapping failed.
In order to change the name of the id property, you need to specify the name for the id property.
Integer seqCol
static mapping = {
id name: 'seqCol', column: 'seq_col', generator: "sequence", params:[sequence:"SEQUENCE_NAME"]
}
So I have a grails model looking like this:
class Tree {
Long id;
String name;
static hasMany = [branches: Branch
}
class Branch {
Long id;
String name;
static belongsTo = [tree: Tree]
}
The issue is that in DB, the Tree id is a number, while the tree_id in the Branch table is a varchar.
The db model is a de facto foreign key that is not enforced at all as a constraint.
Gorm generate a query that is not handled by my database: it tries to bing a numerical value where text is expected:
ERROR util.JDBCExceptionReporter - ORA-01722: invalid number
How can I tell GORM to convert the value before binding the parameter ?
I looked in the join table config but I did not find anything relevant.
Have you tried using sqlType in column definition in mappings?
class Branch {
Long id
String name
static belongsTo = [tree: Tree]
static mapping = {
tree column: 'TREE_ID', sqlType: "char"
}
}
Unable to test right now, but do let me know.
I have a Grails application that will run against either a SQL Server or Oracle backend. I am using GORM as an ORM.
I want to map a large text field in a way that supports both database types. In my Grails domain class I have something like:
class Note {
String content
static constraints = {
content nullable: false, blank: false
}
}
I then declare database tables that look like this:
-- oracle
CREATE TABLE NOTE
(
id NUMBER(19, 0) NOT NULL,
version NUMBER(19, 0) NOT NULL,
content CLOB NOT NULL
);
-- SQL Server
CREATE TABLE NOTE
(
id NUMERIC(19, 0) NOT NULL,
version NUMERIC(19, 0) NOT NULL,
content NVARCHAR(MAX) NOT NULL
);
GORM is running in validate mode on startup, and I can't find a combination of Oracle and SQL Server data types and GORM mappings that allow the storage or large text fields without GORM failing to start correctly.
I have tried:
setting the type to text in mappings, but this doesn't seem to work. Oracle complains about expecting the content field to be of type long, and SQL Server wants a type of text in these circumstances.
setting the type to clob, which passes schema validation but then doesn't allow me to set the field as a string value - GORM expects data of type CLOB.
How should I configure my database definitions and GORM to make this work?
As hackish as it is, a solution eventually emerged: by querying the Grails configuration at startup time, you can select an appropriate data type.
class Note {
String content
static constraints = {
content nullable: false, blank: false
}
static mappings = {
content sqlType: DbSupport.bigStringType
}
}
class DbSupport {
static def getBigStringType() {
// examine which hibernate dialect is selected, and pick
// an appropriate type mapping for that database type:
def dialect = ApplicationHolder.application.config.dataSource.dialect
switch (dialect) {
case "org.hibernate.dialect.SQLServerDialect":
return "nvarchar"
break
case "org.hibernate.dialect.Oracle10gDialect":
return "clob"
break
}
}
}