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'
}
Related
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 Grails 2.2.3 domain class called FundType that I am trying to map to a legacy database table. It has two fields: code and description. I would like the id to be called code anytime I use the domain class and preferably on any of the generated scaffolding. But every time I use the name key on id I get this exception:
| Error 2013-07-24 09:38:44,855 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application: Error evaluating ORM mappings block for domain [com.company.scholallow.FundType]: null
Message: Error evaluating ORM mappings block for domain [com.company.scholallow.FundType]: null
This is what my domain class consists of:
class FundType {
String id
String description
static mapping = {
id column: 'fund_code', generator: 'assigned', name: 'code'
description column: 'fund_desc'
}
}
And anytime I am using a FundType instance I would like to call code like fundTypeInstance.code and NOT fundTypeInstance.id. This will make it more user friendly for me because I'm dealing with something called code, not id.
So I would like to know is what I'd like to do possible? And what am I doing wrong in my domain class that is causing this ORM mappings error?
Edit:
Okay, so I changed my domain class to the following and I am getting a FundType not found with ID null error.
class FundType {
String code
String description
static mapping = {
id generator: 'assigned', name: 'code'
code column: 'fund_code'
description column: 'fund_desc'
}
}
I added some sql logging to see what Hibernate is doing and this is what was output: select * from ( select this_.FUND_CODE as RTVFTYP1_1_0_, this_.FUND_DESC as RTVFTYP2_1_0_ from RTVFTYP this_ ) where rownum <= ?
Use String code instead of String id in the domain class.
You are deliberately mentioning to the GORM that I want to use the property code which maps to table column fund_code whose value is assigned as the id (primary key). In that case, you just need to have the property codedefined in the domain class instead of the id.
(I'm answering the fix that worked for me for future use by other programmers)
#dmahapatro was right, I needed to add String code.
It looks like naming the id something different just doesn't play well with Grails dynamic scaffolding. I did some tests and I can still use FundType.get(code) and it will return the object just as if I passed in an id. I can also do FundType.findByCode(code).
It looks like I have to change the scaffolded controller to expect a String id instead of the default Long id. I also have to change the scaffolded list view to send fundTypeInstance.code instead of fundTypeInstance.id to the show controller, but I suspect that adding a getId() that just returns this.code will fix that.
how audit-logging can work in domain class like userRole from springSecurity?
class SecUserSecRole implements Serializable {
static auditable = true
User user
Role role
...
def onSave = { map ->
println "onSave userRole detected"
}
}
thanks anyway..
I am not fully understanding why this is not working, but the reason seems to be auditPlugin cannot get the persisted properties when the id for class is composite. Therefore, it assumes nothing has changed and it wont call onSave.
The generated SecUserSecRole class introduces a composite key for ID based on 'role', 'user' and auditPlugin is trying to find the persisted property names from the hibernate PostInsertEvent. At this its not clear know why but the properties will be empty when domain is using composite key.
As a workaround try to change your domain mapping to
static mapping = {
//id composite: ['role', 'user']
role unique: 'user'
version false
}
NOTE: This is not a solution and might have other side effects as far as springSecurity plugin.
Update: My concern was removing composite key might impact springSecurity many-to-many relationship, but according to Burt's post, seems it is safe to remove composite key and just create it unique as I mentioned here.
I have a domain class having an Integer variable 'code'. my requirement is to make 'code', primary key column for that domain and also auto increment and to remove the default 'id' column from the table created for that doamin.thnks
use this :
static mapping = {
id name: 'code'
}
more informations here :
http://grails.org/doc/2.0.x/ref/Database%20Mapping/id.html
Domain classes in Grails by default dictate the way they are mapped to the database using sensible defaults. You can customize these with the ORM Mapping DSL.
Customizes the way the identifier for a domain class is generated with id.
See the Grails documentation for id.
static mapping = {
id column: 'code', type: 'integer'
}
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.