Am currently working on a Grails project, that was previously written in some other language. So we have this DB, whose table and column names, we aren't suppose to change. Now the problem is, the column name used for time-stamping is not date_created or last_updated. So is there a way that i can use grails automatic time-stamping and keep my column name unchanged?
How stupid can i be.. Only thing i had to do was to add the below code to my domain class
static mapping = {
dateCreated column: "create_date"
lastUpdated column: "modified_date"
}
Here "created_date" and "modified_date" where my preferred column names.
Related
I would like to add new column in my existed table using domain class but it is not happening. if I use create-drop in application.yml file then it works but at the same time I lost my data. I needed to keep the data as well as I needed to add new column by updating domain class property in grails 3.3.0 and SQL Server 2012
package com.alumni
class Student
{
String studentId
String studentName
String age
static constraints = {
}
}
Database is not updating with column address
It's unclear from your code snippet, but it sounds like you're trying to add
String address
Note that columns are made NOT NULL by default, so if data exists in the table, it's attempting to add a non-nullable column, with null data on every row, so the column will fail to create. You need to allow this column to be nullable in the constraints block as well
static constraints = {
address(nullable: true)
}
If you add that, the column should create successfully.
There seems to be a change in behavior from grails 2 to grails3. When i create a one to many relationship like
class Author {
static hasMany = [books: Book]
String name
}
class Book {
String title
}
It will create a join table with columns author_books_id and book_id. In grails 3 it also adds a not null constraint on the first column. In grails 2 not null constraint is not applied. So when i upgrade to grails 3 it is breaking because there are already few records that have first column values to null. It works fine in grails 2 but with grails 3 the first column should not be null. Furthermore the join table is read only so i cannot remove the rows will null first column values. Is there a way to make the first column nullable = true by making changes in domains and not directly in migration file.
The code was extracted from the grails documentation. Please scroll down to one to many section.
6.2.1.2 One-to-many
http://docs.grails.org/3.0.17/guide/GORM.html
Try changing your Book class to this
class Book {
String title
Author author // this creates the belongs to relationship
}
static constraints = {
author nullable:true
}
Also when you recompile the code make sure to delete previous table and start fresh. Grails will not alter any table to delete anythings. It only adds new stuffs.
Is it possible to fetch a default value in grails if a column is null? If I were to represent following query via grails domain object then how could I achieve it:
SELECT IFNULL(empsalary,0.00) from Employee;
Domain object:
class Employee{
Integer id,
Float empsalary
static constraints = {
id unique: true, blank:false
empsalary nullable:true
}
}
making empsalary nullable false isn't an option due to existing data
validator on empsalary seems to work when inserting rows but not while data fetch
we can consider writing say getEmpSalary() method on domain and perform check there but there are several other fields we need to do this so trying to avoid massive code changes
If you want a default value to come out of the database without having to code anything into your classes, I suggest you update every row where it is null and set it to 0 in the database. If data is getting inserted from another application and that application is allowing a null value, put a 'DEFAULT 0' on your database column.
Grails also offers an "afterLoad" event which is run when a domain object gets loaded from the database. See the documentation here: http://grails.org/doc/2.3.7/guide/GORM.html.
I think you can do this with HQL:
def salary = Employee.executeQuery('SELECT COALESCE(empsalary, 0.0) FROM Employee')[0]
See this SO Question.
Please try setting Float empsalary = 0.0 in your domain object.
I have a domain class called FoapRequest. I want one of the properties called "approver" to be a list of integers. Order matters, so I've defined the class as described by http://grails.org/doc/latest/guide/GORM.html#sets,ListsAndMaps as a list:
class FoapRequest {
Integer requester
Integer subject
List approver
static hasMany = [foap:FOAP, newFoap:NewFoap, approver:Integer]
...
Just for clarification, FOAP and NewFoap are two other domain objects.
I need to map this class to a particular table in the Oracle database, so I also specify a static mapping with a join table:
static mapping = {
table 'OUR_SCHEMA.FOAP_REQUEST_TABLE
id column : 'ID', generator:'sequence', params: [sequence:'OUR_SCHEMA.FOAP_REQUEST_SEQ']
requester column : 'REQUESTER'
subject column : 'SUBJECT'
approver indexColumn: [name: "APPROVER_IDX"], generator:'sequence', params: [sequence:'OUR_SCHEMA.APPROVER_SEQ'],
joinTable: [name:'OUR_SCHEMA.APPROVER_TABLE',
key: 'ASSOCIATED_REQUEST',
column: 'APPROVER_PIDM',
type: "integer"
]
However, when I try to create a new instance of the FoapRequest object, I get the following error:
Invalid column type
The console displays the following:
Error 2012-08-01 12:29:31,619 [http-bio-8080-exec-9] ERROR errors.GrailsExceptionResolver - SQLException occurred when processing request: [POST] /FOAPauth/foapRequest/saveFoapRequests - parameters:
I am certain that the issue lies with the jointable. The domain model didn't include the joinTable originally- approver was just an Integer type (I realized too late that I was going to need to track multiple approvers).
Here's the SQL for creating the APPROVERS table:
CREATE TABLE "OUR_SCHEMA"."APPROVER_TABLE"
(
"APPROVER_IDX" NUMBER(*,0) NOT NULL ENABLE,
"ASSOCIATED_REQUEST" NUMBER(*,0) NOT NULL ENABLE,
"APPROVER_PIDM" NUMBER(8),
);
I'd prefer to avoid creating an Approver domain class if at all possible, since all I really need to keep track of are the integer identifiers.
So, after much janking with join tables, I determined that the best way to deal with my needs was to simply create an Approver object in my domain model.
class Approver {
Integer pidm
String approvalDecision
Date lastUpdated
Date dateCreated
static belongsTo = [foap: FOAP]
}
To be honest, I'm not really sure why I was trying so hard to avoid this. Possibly because my DBAs use a version control system for table definitions that I find a hair annoying. :)
Regardless, a simple one-to-many relationship between domain classes met all my needs, no join table required.
For those who are still burning to know, I did manage to get a statically mapped join table working using a Map, which was more appropriate for my needs (though not as appropriate for them as a new domain class, and not nearly as simple).
I ended up doing it in a different domain object- FOAP instead of FoapRequest:
import java.util.Map
class FOAP {
...
Map approvalData
...
static mapping = {
table 'OURSCHEMA.FOAP_TABLE'
id column : 'ID', generator:'jpl.hibernate.util.TriggerAssignedIdentityGenerator'
fund column : 'FUND'
org column : 'ORG'
chartOfAccounts column : 'CHART_OF_ACCOUNTS'
permissionType column: 'PERMISSION_TYPE'
foapRequest column: 'REQUEST_ID'
version column : 'VERSION'
approvalData joinTable: [name:'OURSCHEMA.FOAP_APPROVERS',
key: 'FOAP'
]
}
For the table definition, I used the column names similar to those in my original question.
CREATE TABLE "OUR_SCHEMA"."APPROVER_TABLE"
(
"FOAP" NUMBER(*,0) NOT NULL ENABLE,
"APPROVER_IDX" VARCHAR2(255),
"APPROVER_DLT" NUMBER(8),
);
The IDX column was the map object's key, the DLT column its value. I'd recommend against this approach, for anyone who can avoid it. Creating a new domain object is much simpler.
I'd like to version a grails domain class by DateTime such that:
each primary ID + DateTime property results in a new DB row (i.e. a new DB row per version)
the newest version can be found without having to specify the DateTime value
My knowledge of grails is a little limited right now and I don't understand how I can achieve this.
Consider the following domain class as an example:
import org.joda.time.DateTime
class Page {
String pageId
DateTime theVersion
String content
static constraints = {
pageId(nullable:false, blank:false, unique:true, matches:"[a-zA-Z\\._-]+")
content(nullable:false, blank:false)
}
static mapping = {
content(type:"text")
}
}
What changes are needed to ensure a new DB row is inserted per version? I'm assuming some form of constraint is required such that pageId+theVersion is unique but I don't know how to express this in the GORM DSL.
How might I get the most recent version without knowing the relevant DateTime value?
I'm envisaging something like:Page.findByPageIdAndTheVersionLessThanEquals('uniquePageId', new DateTime())
I expect this would find many objects not just one. I'd like to be able to also express the equivalent of ORDER BY theVersion DESC LIMIT 0,1
Just create the new versions with new Page(), not with get() - a new record will be inserted.
To assure uniqueness, put into constraints:
theVersion(unique: 'pageId')
Page.findByPageId(pageId, [sort: 'theVersion', order: 'desc', max: 1])
You can utilize Grails' dateCreated implicit timestamping feature - it will even work with joda-time plugin.
OTOH, why don't you utilize Grails' built-in version field? It provides you some features out of box and takes care for optimistic locking.