bootstrapping domains with eachWithIndex - grails

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`"
}

Related

Default string size for Postgresql and Grails 3.3.8 seems to be 20 characters

My string columns are defaulting to 20 characters. All the documentation suggests the default is 255. How do I set that without changing each individual column. I am using Grails 3.3.8 and Postgresql 9.3.
class DbConnection {
String name
String platform
creates 20 character columns
If I add a mapping:
static mapping = {
name sqlType: 'varchar(255)'
platform sqlType: 'varchar(255)'
url sqlType: 'varchar(255)'
}
I get the proper 255 characters, however, grails fails the string on validation:
Field error in object 'dop_etc.DbConnection' on field 'url': rejected value [localhost:5432/rbc48_fantasy]; codes [dop_etc.DbConnection.url.size.error.dop_etc.DbConnection.url,dop_etc.DbConnection.url.size.error.url,dop_etc.DbConnection.url.size.error.java.lang.String...
There seems to be a default size set somewhere and I can't seem to find it. Thanks for your responses.
Apologies, found the problem in some pasted code (in application.groovy)
grails.gorm.default.constraints = {
'*'(nullable: true, size: 1..255)
}
Here's the helpful article:
Overriding default `maxSize` in domain class

Schema Export Errors while launching grails application

I am trying to follow the Grails application from the book Grails 2 - A Quick start guide. The grails version that i am using is 2.4.4 on Ubuntu 14.04 with the open jdk 7
I am getting the following error
Error 2015-03-09 20:05:02,117 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport - HHH000389: Unsuccessful: alter table tek_event drop constraint FK_1xbf5b7edlnmgmrc90jhbyvg7 if exists
| Error 2015-03-09 20:05:02,118 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport - Table "TEK_EVENT" not found; SQL statement:
There is nothing in my application except two domain classes and scaffolded controllers ...
Here are the domain classes TekUser and TekEvent
class TekEvent {
String city
String name
TekUser organizingUser
String venue
Date startDate
Date endDate
String description
String toString(){
"$name, $city"
}
static constraints = {
name()
city()
description maxSize:5000
organizingUser()
venue()
startDate ()
endDate()
}
}
And the TekUser Domain class
class TekUser {
String fullName
String userName
String password
String email
String website
String bio
String toString(){
fullName
}
static constraints = {
fullName()
userName()
email()
website()
bio maxSize:5000
}
}
The controllers for them are pretty barebones
class TekEventController {
def scaffold = TekEvent;
}
class TekUserController {
def scaffold = TekUser;
}
I am not able to follow what is going wrong here ...or is it a benign error that I could just ignore.
Also this started happening when I changed the datatype of organizingUser in the TekEvent class from String to TekUser
These are ignorable errors - there's nothing bad happening. Unfortunately the Hibernate developers changed the logging strategy in Hibernate 4, and that's what you're seeing.
In Hibernate 3, using "create-drop" means to drop all current mapped tables and associated objects (sequences, joins, etc.), then run the create statements, and if the jvm shuts down cleanly, drop all of the tables again at the end. "create" is slightly different in that it does all of the drops and all of the creates, but doesn't do anything at shutdown. This is one I use often since it lets me view data in disk-based databases after the app shuts down.
So the core issue is that the initial drop statements are missing the "if exists" clause, and sometimes not everything that Hibernate is trying to drop exists. So you get these scary looking errors, but they're harmless since they're just telling you that some of the things that were supposed to be deleted were never created.
In Hibernate 3, these errors were stored in a list of strings that you could access after running the script. In Hibernate 4 they changed it to log the errors, I assume since not all errors in that phase are ignorable, so it's better to have false positives in with the real issues than everything hidden in a list that is probably rarely checked.
You can choose to ignore these (at the risk of also ignoring unrelated real error messages), or use a custom Dialect that generates the proper SQL. One example is here

How to specify sequence on non-id column in Grails?

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"]
}

GORM: mapping large text fields database agnostically

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
}
}
}

Mapping exception when using discriminator in Grails 2.0.0

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.

Resources