Mapping breaks my domain class - grails

When I add the following mapping to my domain class, I get an error. Can someone help me see what I'm doing wrong here?
Domain Class
package sample
class Todo {
String name
String note
Date dateCreated
Date lastUpdated
Date dueDate
Date lastModifiedDate
Date completedDate
String priority
String status = "Started"
User owner
Category category
static belongsTo = [User, Category]
static constraints = {
name (blank:false)
priority()
status()
note (maxSize:1000, nullable:true)
completedDate(nullable:true)
dueDate(nullable:true)
}
String toString() {
name
}
}
Mapping I Want to Add
static mapping = {
table 'todo-tbl'
columns {
name column: 'name-str'
note column: 'note-str'
}
cache true
}
Error I Get When Adding Mapping
Error 500: Internal Server Error URI /sample/todo/list Class
org.h2.jdbc.JdbcSQLException Message Table "TODO" not found; SQL
statement: select this_.id as id72_0_, this_.version as version72_0_,
this_.category_id as category3_72_0_, this_.completed_date as
completed4_72_0_, this_.date_created as date5_72_0_, this_.due_date as
due6_72_0_, this_.last_modified_date as last7_72_0_,
this_.last_updated as last8_72_0_, this_.name-str as name9_72_0_,
this_.note-str as note10_72_0_, this_.owner_id as owner11_72_0_,
this_.priority as priority72_0_, this_.status as status72_0_ from
todo-tbl this_ limit ? [42102-164]

I solved this. Apparently using the hyphen in the table name was a big no-no. This stopped the table from being created in the DB.
Changed
table "todo-tbl"
to
table "todoTbl

Related

Gorm mapping/self-reference for one-to-many relationship

So I have my domain below. Basically what I'm wanting to do is get all the demandNumbers for a given WorkOrderSummary. The data structure exists in the view already so I really just need to figure how I can map the WorkOrder-to-demandNumbers (one-to-many) relationship. So one lab_order_header_id can contain many demand_header_ids.
class WorkOrderSummary {
String workOrderNumber
Long demandNumbers
String demandTypeName
String statusName
Date needByDate
String customerName
Long facilityId
Long labDestinationId
Long assetTagQuantity
static hasMany = [demandNumbers: WorkOrderSummary]
static mapping = {
version false
table name: 'work_orders_v', schema: 'lab'
id column: 'lab_order_header_id'
demandNumbers column: 'demand_header_id'
demandTypeName column: 'demand_type'
statusName column: 'status'
}
}
Right now this is only getting me one-to-one in terms of lab_order_header_id to demand_header_ids.
Any suggestions?
Edit - 9/26/2016
Created another domain class for the demandNumbers and notated the belongsTo:
class SalesOrderSummary {
String demandTypeName
static belongsTo = [workOrder: WorkOrderSummary]
static constraints = {
}
static mapping = {
version false
table name: 'work_orders_v', schema: 'lab'
id column: 'demand_header_id'
workOrder column: 'lab_order_header_id'
demandTypeName column: 'demand_type'
}
}
If you wish to have many DemandNumbers for a given WorkOrderSummary
you should replace the following line:
static hasMany = [demandNumbers: WorkOrderSummary]
With the following line:
static hasMany = [demandNumbers: DemandNumbers]
It should make the relationship you are trying to get.

Dealing with org.h2.jdbc.JdbcSQLException

I am getting a org.h2.jdbc.JdbcSQLException error, I have an association whit a basic collection types
class User {
String email
String password
String role = "user"
String fullName
Boolean enabled = false
Date dateCreated
Date lastUpdated
static hasMany = [schools:String]
}
I create a view where user can select schools in checkboxs tag, then in a controller action I get schools values and try to apply next query in order to get all users that have some or all selected schools
def query = User.where {
schools in params.list("schools")
}
I get following error message
ERROR util.JDBCExceptionReporter - Parameter "#1" is not set; SQL statement:
select this_.id as id2_0_, this_.date_created as date2_2_0_, this_.email as email2_0_, this_.user_status as user4_2_0_, this_.full_name as full5_2_0_, this_.last_updated as last6_2_0_, this_.password as password2_0_, this_.user_role as user8_2_0_ from user this_ where this_.id in (?, ?) order by this_.date_created asc [90012-164]
thanks for your time

Is it possible in grails to disable persistence of a domain class dynamically with inheritance

My question is related to/or identical to
Is it possible in grails to disable persistence of a domain class?
I am using grails 2.2.1 where I tried to turn off a domain class by putting
static mapWith = "none"
gorm creates the database table, and calling .save() will actually put an entry to the database. So the mapWith flag did nothing for me. I also cannot find any documentation regarding the mapWith flag. Is there a replacement in Grails 2?
Update on sept 16 with code
package test
class Person {
String name
static constraints = {
}
static mapping = {
version false
tablePerHierarchy false
table 'psn'
}
}
-------------------
package test
class Employer extends Person{
static mapWith = 'none'
String title
static constraints = {
}
static mapping = {
version false
tablePerHierarchy false
table 'emplyr'
}
}
---------
package test
class Employee extends Person{
String description
static constraints = {
}
static mapping = {
version false
tablePerHierarchy false
table 'emplyee'
}
}
I would assume Employer should not be treated as a domain object. However, when I perform, a Person.list(), this sql was shown:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_1_.description as descript2_1_0_, this_2_.title as title2_0_, case when this_1_.id is not null then 1 when this_2_.id is not null then 2 when this_.id is not null then 0 end as clazz_0_ from psn this_ left outer join emplyee this_1_ on this_.id=this_1_.id left outer join emplyr this_2_ on this_.id=this_2_.id limit ?
Hibernate: select count(*) as y0_ from psn this_ left outer join emplyee this_1_ on this_.id=this_1_.id left outer join emplyr this_2_ on this_.id=this_2_.id
Why would it join emplyr????? My purpose is to eliminate this table join when this is mark as "none". Am I doing something wrong?

How to ensure data integrity when using Table Per Subclass?

I am using the table per subclass strategy in Grails by setting the tablePerHierarchy property of the static mapping field in my superclass to false. This way, Grails creates one table for my superclass and one additional table for each of my subclasses.
However, while the superclass and subclass records share the same ID (primary key), there are no foreign key constraints to keep them consistent, i.e. it is possible to delete the superclass record, leaving the subclass record in an invalid state. I want to know if there is a setting/property to make GORM address this in some way, e.g. through constraints. Or is my only option to add foreign keys manually?
For example, given the following domain class as superclass:
class Product {
String productCode
static mapping = {
tablePerHierarchy false
}
}
And the following domain class as subclass:
class Book extends Product {
String isbn
}
This results in the creation of two tables, the Product table and the Book table. When creating a Book – through scaffolded pages, for instance – a record is inserted into each table, their only link being the fact that the ID value is the same for each. Specifically, the data might look like this:
PRODUCT
Id Version ProductCode
1 1 BLAH-02X1
BOOK
Id ISBN
1 123-4-56-7891011-1
Because there is no formal relationship defined at the database level for these tables, it is possible to delete one of the records and leave the other, which results in invalid data. Obviously I can use SQL to manually create a foreign key constraint on the two ID fields, but I was hoping to let Grails handle that. Is this possible?
Using Grails 2.2.1
Solved!
The following solution fixed this issue for me. Add the class below to src/java (this class cannot be written in Groovy)
package org.example;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.JoinedSubclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import java.util.Iterator;
public class TablePerSubclassConfiguration extends GrailsAnnotationConfiguration {
private static final long serialVersionUID = 1;
private boolean alreadyProcessed = false;
#Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
if (alreadyProcessed) {
return;
}
for (PersistentClass persistentClass : classes.values()) {
if (persistentClass instanceof RootClass) {
RootClass rootClass = (RootClass) persistentClass;
if (rootClass.hasSubclasses()) {
Iterator subclasses = rootClass.getSubclassIterator();
while (subclasses.hasNext()) {
Object subclass = subclasses.next();
// This test ensures that foreign keys will only be created for subclasses that are
// mapped using "table per subclass"
if (subclass instanceof JoinedSubclass) {
JoinedSubclass joinedSubclass = (JoinedSubclass) subclass;
joinedSubclass.createForeignKey();
}
}
}
}
}
alreadyProcessed = true;
}
}
Then in DataSource.groovy set this as the configuration class
dataSource {
configClass = 'org.example.TablePerSubclassConfiguration'
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
dbCreate = "update"
url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
}
Update
I've submitted a pull request to Grails for this issue. The fix was included in Grails 2.3.8 or 2.3.9 (can't remember which).
Hibernate ensures the data integrity in case of table per subclass. In case of table per subclass, subclass maintains a primary key association with superclass. Have a look at Hibernate Table per subclass. To validate the fact here is your test case:
class Product {
String productCode
static mapping = {
tablePerHierarchy false
}
}
class Book extends Product{
String isbn
}
//Test Case
def testTablePerSubclass{
def product = new Product(productCode: 'XYZ456')
product.save(flush: true, failOnError: true)
def book = new Book(isbn: '123456123', productCode: 'ABC123')
book.save(flush: true, failOnError: true)
assert Book.list().size() == 1 //One Book
assert Book.list()*.id == [2] //Book id
assert Product.list().size() == 2 //One Product, one Book (2 Products)
assert Product.list()*.id == [1, 2] //Product id, Book Id
//Grab the product (book) to delete
def productToDelete = Product.get(book.id)
productToDelete.delete(flush: true)
assert Book.list().isEmpty() //Book deleted from Book table as well
assert Product.list().size() == 1 //One Product remaining in Product table
assert Product.list()*.id == [1] //Remaining Product Id
}
Keep logSql true in DataSource.groovy to see corresponding sqls getting executed.
Log Sql Output:-
Hibernate: insert into product (id, version, product_code) values (null, ?, ?)
Hibernate: insert into product (id, version, product_code) values (null, ?, ?)
Hibernate: insert into book (isbn, id) values (?, ?)
Hibernate: select this_.id as id0_0_, this_1_.version as version0_0_, this_1_.product_code as product3_0_0_, this_.isbn as isbn1_0_ from book this_ inner join product this_1_ on this_.id=this_1_.id
[com.example.Book : 2]
Hibernate: select this_.id as id0_0_, this_.version as version0_0_, this_.product_code as product3_0_0_, this_1_.isbn as isbn1_0_, case when this_1_.id is not null then 1 when this_.id is not null then 0 end as clazz_0_ from product this_ left outer join book this_1_ on this_.id=this_1_.id
[com.example.Product : 1, com.example.Book : 2]
Hibernate: delete from book where id=?
Hibernate: delete from product where id=? and version=?
Hibernate: select this_.id as id0_0_, this_1_.version as version0_0_, this_1_.product_code as product3_0_0_, this_.isbn as isbn1_0_ from book this_ inner join product this_1_ on this_.id=this_1_.id
[]
Hibernate: select this_.id as id0_0_, this_.version as version0_0_, this_.product_code as product3_0_0_, this_1_.isbn as isbn1_0_, case when this_1_.id is not null then 1 when this_.id is not null then 0 end as clazz_0_ from product this_ left outer join book this_1_ on this_.id=this_1_.id
[com.example.Product : 1]
Using Grails 2.2.2

Columns in join table are NOT NULL

I have a domain class:
class Author {
String name
static hasMany = [superFantasticAndAwesomeBooks: Book, superBadAndUltraBoringBooks: Book]
}
This is all nice when using the in-memory database, however, when running on Oracle the Book collections are modeled in a join table which cannot be created because the column names are too long.
So, then I tried specifying the join table properties:
static mapping = {
superFantasticAndAwesomeBooks joinTable: [key: awesomeBooks]
superBadAndUltraBoringBooks joinTable: [key: boringBooks]
}
The problem (which doesn't happen if joinTable isn't specified) is that the join table is created where columns correspoinding to awesomeBooks and boringBooks are NOT NULL (they need to be nullable because a Book will be an awesomeBook or a boringBook)
Is there any way to configure joinTable to allow NULL columns?
Another option would be to map the join table yourself with a Domain class, for example:
class AuthorBook {
Author author
Book book
String status
static constraints = {
author(nullable:false)
book(nullable:false)
status(nullable:false,inList:['SuperFantasticAndAwesome','SuperBadAndUltraBoring'])
}
}
So your Author class becomes:
class Author {
...
static hasMany = [authorBooks:AuthorBook]
}
In this way the status is stored as a value of the join and statuses can be added, updated, or removed as needed in the future. It does have the side effect of having to query through the AuthorBook class to get to the associated Books.
See also: http://grails.org/Many-to-Many+Mapping+without+Hibernate+XML
I just ended up using 2 join tables:
static mapping = {
superFantasticAndAwesomeBooks joinTable: [name: 'awesomeBooks', key: 'book_id']
superBadAndUltraBoringBooks joinTable: [name: 'boringBooks', key: 'book_id']
}

Resources