Version grails domain class by DateTime - grails

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.

Related

How can I update my existing database table using domain class in grails 3.3.0?

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.

Grails scaffolding, still can't process java8 localdateTime in edit forms, nor can it do Map property

I am using Grails v3.3.9, latest grails hibernate 8 and grails plugins in build.gradle, along with java8 plugin, fields plugin (didn't make any difference) and Hibernate 8.
compile "org.hibernate:hibernate-core:5.1.5.Final"
compile group: 'org.hibernate', name: 'hibernate-java8', version: '5.1.5.Final'
compile "org.grails.plugins:gsp"
compile 'org.grails.plugins:grails-java8:1.2.3' //java 8 features including datetime in GSP
compile 'org.grails.plugins:fields:2.2.10'
I've tried this on my Domain model which extends an abstract class with LocalDateTime
abstract class Agreement {
String contractReference
String status
LocalDateTime contractSignedDate
LocalDateTime lastUpdated //updated by framework
LocalDateTime dateCreated //updated by framework
static constraints = {
contractReference nullable:false
status nullable:false
contractSignedDate nullable:true
}
}
and concrete class here
class MaintenanceAgreement extends Agreement {
String level
Map category = [:] //p1 to p5 and sla details
//static belongsTo = [serviceProvider : OrgRoleInstance, maintainer: OrgRoleInstance]
// implemented as unidirectional many to one ! mag point to org
static belongsTo = [maintainer: OrgRoleInstance]
static constraints = {
level nullable:false
//serviceProvider nullable:true
maintainer nullable:false //ref to maintainer party
category nullable:false
}
}
If I have a record in Db from bootstrap with null column - grails just doesn't how any field holder for null entry. Go back to bootstrap and manually create a value, restart.
At least this time list and show rendering put an actual on the form
However when you go to create a new form (or the edit action) you get this. The contractSigned (localDateTime) has no editor, and lastly the domain model has a property category as a Map, and there is no editor for Map column.
This is a real problem. I can revert back to trying to use Date but that's a retrograde step really, and the platform suggests the new data time formats are supported. The Map column to think what my fallback for that might.
Am I missing something here that makes this work ? or do I have re raise as defect ?
I ran into this in previous 3.3.8 build here also with no resolution to data time issue
previous record
see also previous ask for feature here
make java new dates first class citizen in grails
Don't use LocalDateTime in you class for data type. You might not able to edit that. Use Date type instead. Then grails itself will provide you date-picker to add and edit as well. If you need to extract current date time in GSP you can use ${new Date() as value of that field.

GORM: implement uuid getter while preserving id getter

Given you have to keep the existing GORM getter functionality that is based on the default incremental id:
How would you add getter functionality based on a new attribute uuid?
Most desirably there would be something like:
Overload get(Long id) with get(String uuid) so that both getters can be used side by side.
In the long run, the performance of the uuid getter is critical. So I assume it would be best to make it the primary key.
I'm working on Grails 2.5.4 and will be switching to Grails 3 in the next months. So the solution should be working in both worlds of Grails.
In this case it is better to use .findByUuid() and add an index to the field to maintain performance.
I can't comment but i think here is your solution
How to change primary key column in grails?
static mapping = {
id name: 'uuid'
}
static mapping = {
id column: 'uiid', type: 'String'
}

grails validation when fetching rows

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.

Grails - Using automatic timestamps, with varieable other than dateCreated and lastUpdated

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.

Resources