How to exclude some columns with GORM with dynamic finders? - grails

I have the following domain object:
class DbDeployment
{
static constraints = {
startDate(nullable: false)
endDate(nullable: true)
username(nullable: true)
fabric(nullable: false)
description(nullable: true)
status(nullable: true)
details(nullable: true)
}
static mapping = {
columns {
details type: 'text'
}
}
Date startDate = new Date()
Date endDate
String username
String fabric
String description
String status
String details // xml representation of the plan
}
I would like to be able to run a query like this:
DbDeployment.findAllByFabric("f1", params)
but I would like to ensure the column details (which is potentially huge) is not retrieved.
Is there a way to do this?

Option 1: Create an association for the large data field(s)
One suggestion from this answer is to break the large data property out into a separate domain, which will cause it to load lazily. Example:
class DbDeployment {
Date startDate = new Date()
Date endDate
...
DbDeploymentDetails details
}
class DbDeploymentDetails {
String details
static belongsTo = DbDeployment
}
Option 2: Using a new domain + mapping to the original table
An answer on a different question links to a Grails mailing list question which has a great answer from Burt Beckwith, but the SO answer doesn't give an example. For the sake of posterity I'll yoink his example from the mailing list and put it here.
It involves creating another domain class without the large field, and then using its static mapping closure to map to the other domain's table.
class DbDeployment {
Date startDate = new Date()
Date endDate
...
String details
}
class SimpleDbDeployment {
Date startDate = new Date()
Date endDate
...
// do not include String details
static mapping = {
table 'db_deployment'
}
}
Then you can just use the finders on SimpleDbDeployment:
SimpleDbDeployment.findAllByFabric('f1', params)
Burt, it'd be great if you would re-answer with your example from the mailing list; I'll cut it out of mine and upvote yours, since you deserve the credit.

Related

Grails: Find class property based on Date

I have a Grails 2.4.3 application that uses Oracle as the database.
There's a class called User:
class User {
String userName = ""
String userPassword = ""
Date userAdded
}
In a controller i am using the following code to find all user names.
def names = User.where { }.projections { property 'userName' }.list()
Now i want to find User Names based on the date in which they were added to database.
For e.g., if a date range is provided as between 12/01/2014 to 12/12/2014, Now i want to get all the User Names added during that period.
Is there a easy way of doing it?
This should do it
Date start = // get the start date
Date end = // get the end date
def userNames = User.withCriteria {
ge('userAdded', start)
le('userAdded', end)
projections {
property("userName")
}
}

java.lang.NullPointerException in command object

I want to parse a string to date just before validate a command object, here is my command object code
class ActivitiesCommand {
List schools
List departments
Date from
Date to
static constraints = {
schools nullable:false
departments nullable:false
from blank:false
to blank:false
}
def beforeValidate() {
def from = new Date().parse("yyyy-MM-dd", from)
def to = new Date().parse("yyyy-MM-dd", to)
}
}
but i am getting java.lang.NullPointerException when i try def from = new Date().parse("yyyy-MM-dd", from) or def to = new Date().parse("yyyy-MM-dd", to). What can i do in order to successfully parse the date before validate command object?
I read the command object docs. I got this sample from there. I tried if removing ? beforeValidate does not work, so i understand i need to provide a null safe but i do not know how to do it in my scenario
class Person {
String name
static constraints = { name size: 5..45 }
def beforeValidate() { name = name?.trim() }
}
Thanks for your time.
from and to is set to Date in the Command Object, so request parameter string with from and to names will be converted to a Date and then bound to these field.
If the expected date format matches then binding will be successful.
In your case, from and to in beforeValidate is treated as String instead. If they are String actually then you can make them nullable: false in constraints or do the check as below in beforeValidate:
from = from ? Date.parse("yyyy-MM-dd", from) : new Date() - 1 //for example
Note the appropriate use of Date.parse()

How to set formula in grails domain class?

I am trying to write formula in my domain class which helps me in creating criteria.
class MyClass {
//some fields
Date appointmentTime
String ddmmyy
int year
int month
int day
static transients = [
'ddmmyy',
'year',
'month',
'day'
]
static mapping= {
ddmmyy formula('DATE_FORMAT(appointmentTime)')
year formula('YEAR(appointmentTime)')
month formula('MONTH(appointmentTime)')
day formula('DAYOFMONTH(appointmentTime)')
}
}
Whenever I am trying to use this fields in my criteria it throws error i.e. can not resolve property 'ddmmyy' of 'myClass'.
MyCriteria is:
Date myDate = Calender.instance.time
def results = MyClass.createcriteria().list{
lt('appointmentTime', date+1)
ge('appointmentTime', date)
projections {
groupProperty('ddmmyy')
count('id')
}
}
Any idea why I am getting an exception for this?
You need to make these fields non transient to use in criteria. See reference document
http://gorm.grails.org/6.1.x/hibernate/manual/#derivedProperties

Setting default value for Date field in Grails Domain Class

I'm trying to set a default value for a Date field in a Domain class.
I can use defaultValue in the mapping configuration but it doesn't work with Date fields (I've tried it on String and Integer and it works fine).
This is an example:
class Something {
Date myField
static mapping = {
myField defaultValue: new Date()
}
}
This code fails because the CREATE statement that Hibernate generates is incorrect. It is something like:
... my_field datetime default Mon Nov 25 17:59:08 UYST 2013 not null ...
You can always initialize the field in the static initializer or set the value in the constructor:
class Something {
// initializer
Date myField = new Date()
// or in the ctor
Something() {
myField = new Date()
}
}
This doesn't set a default value in the database schema, it merely sets the value of the field on creation of the instance. If you want the schema to have a default value, you can use the 'defaultValue' mapping entry like so:
class Something {
Date myField
static mapping = {
myField defaultValue: "now()"
}
}
the value you set for the default value is dependent on your database vendor. (notice the use of sql now() method rather than Java/Groovy new Date().
GORM readily caters for the most basic Date use cases; create and update.
Simply include keywords dateCreated and lastUpdated into the domain's properties for the default functionality to occur.
Warning: If their constraints are nullable: false this will cause a fail. Either remove those constraints or set autoTimestamp to false.
For example:
class MyDomain {
Date dateCreated
Date lastUpdated
Date yesterday = new Date().previous()
Date weekAgo = new Date() - 7
Date monthAgo = new Date() - 30
Date usaIndepenceDay = new Date().copyWith(
year: 1776,
month: Calendar.JULY,
dayOfMonth: 4,
hourOfDay: 0,
minute: 0,
second: 0)
static mapping = {
//autoTimestamp false
}
static constraints = {
//dateCreated nullable: false
}
}
Read the more about groovy dates at this SO answer, the groovy date api, and GORM's date-event features here
You can use this for default crated date auto get from system date
class User {
String userName
String firstName
String lastName
Date createdDate = new Date() // set system date
static mapping = {
version false
id generator: 'increment'
cache true
}
static constraints = {
userName(unique: true)
}
}

How to use "WHERE" with grails criteria

Class Vote {
String name;
Date startDate;
Date endDate;
}
I want to show all vote when Date of end is superior to new Date
Grails docs show you the list of operators in a criteria. In your case you can use gt and pass the current date.
def votes = Vote.createCriteria().list() {
gt('endDate', new Date())
}

Resources