Is there any way to set a default value to domain class property?
I have a class called PayMethod, where I want the name property to default to "Cash" and I want this default value when I create this table, is this possible using Constraints?
package abc
import util.UserUtil
import embed.AuditUser
class PayMethod {
String name = "Cash"
AuditUser audit = new AuditUser()
static embedded = ['audit']
static constraints = {
name blank: false, size: 5..30, unique: true
}
static mapping = {
table 't01i0010'
id column: 'F_ID', precision: 4, scale: 0
name column: 'F_NAME', length: 30, defaultValue: 'Cash'
version column: 'F_REVISION'
}
def authUserService
int insertIndex = 0
int updateIndex = 0
static transients = ['authUserService', 'insertIndex', 'updateIndex']
def beforeInsert = {
audit.entryUser = UserUtil.user()
audit.entryDate = new Date();
}
def beforeUpdate = {
audit.reviseUser = UserUtil.user()
audit.reviseDate = new Date();
}
def afterInsert = {
if(insertIndex == 0){
def user = audit.entryUser
def date = audit.entryDate
log.info "POST INSERT => ENTERER: ${user} ENTERED: ${date}"
}
insertIndex++
}
def afterUpdate = {
if(updateIndex == 0){
def user = audit.reviseUser
def date = audit.reviseDate
log.info "POST UPDATE => REVISE: ${user} REVISED: ${date}"
}
updateIndex++
}
}
This will be possible in 2.2 which should be released this week or next. See http://jira.grails.org/browse/GRAILS-5520 for the relevant feature request. The syntax will be
static mapping = {
name defaultValue: "'Cash'"
}
For now you'll need to do what you're doing - set the value as the default value of the field. You can manually update the database schema, or do the work as part of a migration.
To build on the previous answer, you can use the defaultValue attribute in Grails 2.2 but you need to be careful to put double and single quotes around default values for String properties and double quotes around integer properties so that the default values appear correctly in the DDL. So, for instance, you need to use:
static mapping = {
myStringProperty defaultValue: "'Cash'"
myIntProperty defaultValue: "0"
}
If you only use single quotes, you will end up with an error like "Column "CASH" not found"
Also, as far as I can tell, default values do not work for properties that are enums.
Had the same issue and using static mapping didn't work for me either (using 2.2.3); the below link provided me a functional answer (set the default value in your object declarations):
http://grails.1312388.n4.nabble.com/How-to-set-a-default-value-for-column-td1383753.html
For String, encapsulate with quotes; int/integer should just be the value.
Hope this helps!
Related
I am using Grails 2.4.0.And create an application and deploy on linux.
My Domain is
class UserDetails {
String userEnvironment = ""
Long userId = 0L
Boolean accountCreated = false
Integer retries = 0
String password = ""
boolean accountCreationInProgress = true
static constraints = {
accountCreationInProgress nullable : true
}
}
When saving its working fine on windows.But accountCreated and accountCreationInProgress column is blank on linux. Why don't know.
Anyone please help me out.
Change to:
class UserDetails {
StringuserEnvironment = ""
LonguserId= 0L
Boolean accountCreated= false
Integer retries = 0
Stringpassword= ""
Boolean accountCreationInProgress = true
static constraints = {
//there is no point to use nullable for accountCreationInProgress if you set it default to true value during create
}
}
Remember to drop table in database before rerun of app.
I have to keep track of sequential submissions per fiscal year. Given the fiscal year '2015' then the numbering should be '2015001, 2015002, 2015003, etc'.
I have defined a domain class to keep track of these settings:
class MYAPPConfig {
String fiscalYear
Integer requestCount
static constraints = {
fiscalYear (size: 4..4, nullable: false)
requestCount(max: 999, nullable: false)
}
}
The idea is that for a new fiscal year I will add a new record and the 'requestCount' will be reset to 0 (or 1 depending on how Grails wants to manage it).
Ideally this field should be mapped to an Oracle sequence field. If that's not possible then should I manage the increment logic in a service method?
My Grails version is 2.4.2
Thanks.
I figured it out.
I took a different route (after more googling). I added dateCreated to my model which is managed by Grails so its updated automatically. So all I needed to do is get the record with the latest date (every year we will add a new record for the coming fiscal year). Take note of the [0] at the end of the call, that flattens the array of arrays returned and allows me to deal with a single object.
My model now looks like this ( MYAPPConfig.groovy ) :
class MYAPPConfig {
String fiscalYear
Integer requestCount
Date dateCreated
static constraints = {
fiscalYear (size: 4..4, nullable: false)
requestCount(max: 999, nullable: false)
}
}
I created the following service ( ManageRequestsService.groovy )
import grails.transaction.Transactional
#Transactional
class ManageRequestService {
def getNextTrackingId() {
def latestConfig = MYAPPConfig.listOrderByDateCreated(max:1, order: "desc")[0]
def latestFiscal = latestConfig.fiscalYear
Integer sequence = latestConfig.requestCount
sequence++
latestConfig.requestCount = sequence
latestConfig.save(flush:true)
return latestFiscal + sprintf('%03d', sequence)
}
}
And in my controller ( MyTestController.groovy ) I have:
class MyTestController {
def manageRequestsService
def test() {
def trackingId = manageRequestsService.getNextTrackingId()
render "Next id is: ${trackingId}"
}
}
Giving the following output ( http://localhost:8080/MYAPP/myTest/test ):
Next id is: 2015001
Refresh page!
Next id is: 2015002
Refresh again!
Next id is: 2015003
What are the benefits of using the grails insert flag when saving a domain class?
Here is an example:
Lets say I have a Domain Object FooBar:
FooBar foo = FooBar.find("foo")?: new FooBar(id:"foo")
foo.bar = "bar"
foo.save()
Would it be better do do something more like this:
boolean insertFlag
FooBar foo = FooBar.find("foo")
if(foo == null){
insertFlag = false
}else {
foo = new FooBar(id:"foo")
insertFlag = true
}
foo.bar = "bar"
foo.save(insert: insertFlag)
I was thinking that the save would run smoother somehow with the insert flag verses not having it.
insert inside save is highly useful if you have the id generator for a domain class as assigned. In that case the id has to be assigned by the user.
This is a way to inform hibernate that whether you want to insert a record or just want to update.
class FoofBar{
String bar
static mapping = {
id generator: 'assigned'
}
}
def fooBar = new FooBar(bar: 'foo')
fooBar.id = 100
fooBar.save() //inserts a record with id = 100
def secondFooBar = FooBar.get(100)
secondFooBar.id = 200
//want to insert as a new row instead of updating the old one.
//This forces hibernate to use the new assigned id
fooBar.save(insert: true)
This will make it clear.
I have several Grails 2.1 domain classes that include dateCreated and lastUpdated fields that GORM manages automatically, eg:
class Person {
Date dateCreated
Date lastUpdated
String name
}
I want Grails to automatically fill in these fields at runtime, but I also want to create some test data where I can manually define the values of these dates. The trouble is that Grails automatically sets the values if these fields with an interceptor even when I have specifically set them.
I have seen this SO question which describes how to allow changes to dateCreated, but I need to change lastUpdated as well. Is this possible?
Whoops, my mistake, the approach in the other question does work, but the entity in question was separately being saved somewhere else. It also seems that you need an explicit flush to make things work:
def withAutoTimestampSuppression(entity, closure) {
toggleAutoTimestamp(entity, false)
def result = closure()
toggleAutoTimestamp(entity, true)
result
}
def toggleAutoTimestamp(target, enabled) {
def applicationContext = (ServletContextHolder.getServletContext()
.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT))
def closureInterceptor = applicationContext.getBean("eventTriggeringInterceptor")
def datastore = closureInterceptor.datastores.values().iterator().next()
def interceptor = datastore.getEventTriggeringInterceptor()
def listener = interceptor.findEventListener(target)
listener.shouldTimestamp = enabled
null
}
def createTestPerson() {
def luke = new Person(name: "Luke Skywalker")
withAutoTimestampSuppression(luke) {
def lastWeek = new Date().minus(7)
luke.dateCreated = lastWeek
luke.lastUpdated = lastWeek
luke.save(failOnError: true, flush: true)
}
}
If it is an integration test you can use an hql update statement to manually set lastUpdated.
This question is about altering how the Grails data-binding handles string-to-integer conversion.
Consider the following domain object:
class Foo {
String name
Integer price
}
Furthermore, assume that the domain object is populated from HTTP request parameters:
def foo = new Foo(params).save()
The save() method above will fail if params.price == "" (empty string). I'd like to change this behaviour globally so that an empty string is parsed as zero (0) when converting from a string to an integer in Grails data-binding. How do I achieve that?
added a filter see the setion 5.5.1 Events and Auto Timestamping in the grails documentation (http://grails.org/doc/1.1.x/index.html)
def beforeInsert = {
if (price == '') { price = 0}
}
Instead of changing the data binding why not just write your own setter? In the setter test to see if the string is empty, if it is set price to 0. If it isn't do a normal integer conversion.
try this constraint instead
static constraints = {
price(validator: {val, obj ->
if (val == '' || val == 0) {
obj.price = 0
return true
} else if (val < 1) {
return false;
}
})
}
import org.grails.databinding.BindUsing
class Foo {
String name
#BindUsing({ obj, source ->
source["price"] ?: 0
})
Integer price
}