I am new to groovy/grails, and I'm trying to to do a criteria search that finds all posts for a month, basically like this:
def getUserMinutesForYear(User user, Date date){
Date firstDate = new GregorianCalendar(date.year, Calendar.JANUARY, 1, 0, 0, 0).time
Date lastDate = new GregorianCalendar(date.year, Calendar.DECEMBER, 31, 23, 59, 59).time
def c = JobRegistration.createCriteria()
def minutes = c.get {
and{
eq("user.id", user.id)
between("job.happening", firstDate, lastDate)
}
projections {
sum("minutesWorked")
}
}
return minutes
}
The domain classes are
class Job {
String title
String description
Date happening
static hasMany = [registrations:JobRegistration]
}
class User {
static hasMany = [authorities: Role, registrations: JobRegistration]
static belongsTo = Role
String username
}
class JobRegistration {
Job job
User user
Integer minutesWorked
static belongsTo = [user:User,job:Job]
static constraints = {
user(blank: false)
job(blank:false)
minutesWorked(nullable :true)
}
String toString(){
return user.userRealName
}
}
Now, why do I get this exception?
org.codehaus.groovy.runtime.InvokerInvocationException: org.hibernate.QueryException: could not resolve property: job.happening of: JobRegistration
You need to nest the job relationship (you can also just us eq with user):
def minutes = c.get {
and{
eq("user", user)
job{
between("happening", firstDate, lastDate)
}
}
projections {
sum("minutesWorked")
}
}
cheers
Lee
Related
I am developing one application in grails. I have following kind of mapping. Now I am saving object of DemoD class but its not saving values neither showing me any error while save. I have printed all created object and all looks fine. but still I am now able to save records.
class DemoS {
String firstName
String lastName
Long rollNumber
String address1
String address2
String city
String state
static constraints = {
address2 nullable:true
}
static hasMany = [demoAList: DemoA]
}
class DemoD {
Date date
static hasMany = [demoAList: DemoA]
def beforeInsert = {
date = new Date()
}
}
class DemoA {
Long id
Boolean absent
Boolean halfday
String notes
Date date
static belongsTo = [demoS:DemoS, demoD:DemoD]
static constraints = {
notes nullable: true
}
}
class UploadDataService {
def saveUploadedData(def dataList) {
def i = 0
DemoD ddObj = new DemoD()
//Getting this dataList from excel and now creating object for each row.
dataList?.each{ rowList ->
if(i != 0){
def dsObj = DemoS.get(rowList[0]?.longValue())
DemoA daObj = new DemoA([id:rowList[0]?.longValue(),absent:rowList[1],halfday:rowList[2],notes:rowList[3] ? rowList[3] : ''])
dsObj.addToDemoAList(daObj)
daObj.demoS = dsObj
ddObj.addToDemoAList(daObj)
daObj.demoD = ddObj
}
i++
}
ddObj.save(saveOnError: true)
}
}
I have something like the following domain-structure (it's a legacy database!):
class Contract implements Serializable {
int type
...
hasMany = [attachments: Attachment]
static mapping = {
attachments cascade: "all-delete-orphan"
}
}
class Attachment implements Serializable {
static belongsTo = [contract: Contract]
int attNo
String name
static mapping = {
id generator: 'assigned', composite: ['contract', 'attNo']
}
}
The contract has - depending on it's type - a few default attachments which should be deleted and recreated if the type changes.
For this I created a service which is called just before saving the edited contract. (The service doesn't have the #Transactional annotation, to have it running in the same transaction than the save/update of the contract.)
class AttachmentService {
def removeAttRecords(int contractId) {
Contract contract = Contract.get(contractId)
def records = contract.getAttachments()
for (int i = 0; i < records.size(); i++) {
Attachment record = records[i]
contract.removeFromAttachments(record)
}
}
def insertAttRecord(int contractId, String name) {
def contract = Contract.get(contractId)
def records = contract.attachments
int maxNo = 0
for (attachment record: records) {
if (record.attNo > maxNo)
maxNo = record.attNo
}
Attachment att = new Attachment()
att.contract = contract
att.attNo = maxNo +1
att.name = name
att.validate()
att.save(insert: true, flush: true, failOnError: true)
}
def createDefaultRecords(int newType, int contractId) {
if (newType == 1) {
removeAttRecords(contractId)
} else if (newType == 2) {
removeAttRecords(contractId)
insertAttRecord(contractId, "Attachment XYZ")
insertAttRecord(contractId, "Attachment ABC")
} else if (newType == 3) {
removeAttRecords(contractId)
insertAttRecord(contractId, "Attachment DEF")
}
}
}
My problem is now, that I get a duplicate entries error from the database in the insertAttRecord->att.save call, if I call the createDefaultRecords method in my service. Because of the deletion and the recreation.
I currently have no idea, how I could work around it.
You're using id generator: 'assigned' for the Attachment class. That means you have to set its id (the primary key) yourself. It looks like since you're not assigning it the new entries will all have the same id, hence the duplicate entries failure.
I worked around my problem with the following code:
class AttachmentService {
def removeAttRecords(int contractId) {
Attachment.executeUpdate("delete from Attachment att where att.contract.id = ?", [contractId])
}
def insertAttRecord(int contractId, int nextMaxNo, String name) {
Attachment att = new Attachment()
att.contract = Contract.get(contractId)
att.attNo = nextMaxNo
att.name = name
att.validate()
att.save(insert: true, flush: true, failOnError: true)
}
def createDefaultRecords(int newType, int contractId) {
def result = Attachment.executeQuery("select max(att.attNo) from Attachment att where att.contract.id = ?", contractId)
if (result[0] == null) result[0] = 0;
int currMaxNo = result[0]
if (newType == 1) {
removeAttRecords(contractId)
} else if (newType == 2) {
removeAttRecords(contractId)
insertAttRecord(contractId, currMaxNo +1, "Attachment XYZ")
insertAttRecord(contractId, currMaxNo +2, "Attachment ABC")
} else if (newType == 3) {
removeAttRecords(contractId)
insertAttRecord(contractId, currMaxNo +1, "Attachment DEF")
}
}
}
After discussing with the db-designer, it would be ok to handle that in this way.
(but I'd still like to know, why it wasn't working, even with a session-flush... :-)
If I have four domain classes like this:
class Branch {
String name
static hasMany = [users:Users]
static mappedBy = [users:'branch']
static mapping = {
id column: 'f_branch_id'
name column: 'f_name'
}
}
class Users {
String name
static hasMany = [account:Account]
static mappedBy = [account:'user']
static belongsTo= [branch:Branch, title:Title]
static mapping = {
id column: 'f_user_id',
name column: 'f_name',
branch column: 'k_branch_id'
}
}
class Account {
String username
static belongsTo = [user:Users]
static mapping = {
id column: 'f_account_id'
user column: 'f_user_id'
username column: 'f_username'
}
}
class JoinTable implements Serializable {
Account account
Role role
static mapping = {
id composite : ['role', 'account']
role column :'k_role_id'
account column :'k_account_id'
version false
}
}
How can i get branch from JoinTable using criteria query
i try this process but fail for alias problem
def criteria = JoinTable.createCriteria()
def list = criteria.list {
account {
user{
branch{
eq("id", "2")
}
}
}
}
Domains
class Branch {
String name
static hasMany = [users:Users]
static mapping = {
id column: 'f_branch_id'
name column: 'f_name'
}
}
class Title {
...
}
class Users {
String name
static hasMany = [account:Account]
static belongsTo= [branch:Branch, title:Title]
static mapping = {...}
}
class Account {
String username
static belongsTo = [user:Users]
static mapping = {...}
}
class Role {
...
}
class JoinTable implements Serializable {
Account account
Role role
static mapping = {
id composite : ['role', 'account']
role column :'k_role_id'
account column :'k_account_id'
version false
}
}
Test
#TestMixin(GrailsUnitTestMixin)
#Mock([Act, Branch, Title, Users, Account, Role, JoinTable])
class EaseTests {
void testCriteria(){
10.times{
def b = new Branch().save(validate:false, flush:true)
10.times{
def u = new Users(branch:b).save(validate:false, flush:true)
10.times{
def a = new Account(user:u).save(validate:false, flush:true)
def joinTableRow = new JoinTable(account: a).save(validate:false, flush:true)
}
}
}
def c = JoinTable.createCriteria()
def results = c{
account{
user {
branch{
idEq(2l)
}
}
}
}
assert results
}
}
I have three domain objects
class OrgProfile {
String name
static mapping = {
discriminator column:'ORG_TYPE'
}
}
class Org extends OrgProfile {
static mapping = {
discriminator 'ORG'
}
}
class Jurisdiction extends OrgProfile {
String email
static mapping{
discriminator 'JURISDICTION'
}
}
I need to search by name and email to get all list of Org and Jurisdiction
so something like
def criteria = OrgProfile.createCriteria()
criteria.list{
or {
ilike("name", "%${token}%")
ilike("email", "%${token}%")
}
}
where token is a string. How can this be achieved?
Tried the code:
def criteria = OrgProfile.createCriteria()
def results = criteria.list{
or {
ilike("name", "%${token}%")
ilike("email", "%${token}%")
}
}
Results as expected.
Is possible to call namedQuery on grails inside a controller? I know that I can call a namedQuery inside another namedQuery, but i dont want to do that. Any ideas? Thanks
User.groovy
static namedQueries = {
filterUsers{
eq("age", 21)
}
}
MyController.groovy
def r = User.createCriteria().list {
eq("id", 1)
filterUsers() //not possible
}
or..
MyController.groovy
//not possible too
//Cannot invoke method createCriteria() on null object
def r = User.filterUsers().createCriteria().list {
eq("id", 1)
}
Here's an example:
Domain:
class User {
int age
String userName
static namedQueries = {
filterUsers {
eq("age", 21)
}
}
static constraints = {
}
}
Controller:
class TestController {
def index = {
def users = User.filterUsers {
and {
like 'userName', 'Derek%'
}
}
render users as JSON
}
}
Also, you can find more about this here: Reference Documentation