Kindly, Convert this below hql query to GORM either using criteria or using some API. I am new to grails and I searched enough but I did't get any positive solution for this forgive me if it is simple.
MappingDetail.executeQuery("select map.id from MappingMaster as map where map.id = (select mapdetail.id from MappingDetail as mapdetail where mapdetail.rawdata_template.id=(select rawdata.id from RawDataMasterTemplate as rawdata where rawdata.name like :name))",[name:'%Rick%'])
Why do you have to use criteria here? I think this is the select where you use HQL instead.
def raw = RawDataMasterTemplate.findByNameLike('%Rick%')
def detail = MappingDetail.findByRawdata_template(raw)
def master = MappingMaster.get(detail?.id)
Test this:
MappingMaster.withCriteria {
createAlias 'mappingDetail', 'mp'
createAlias 'mp.rawDtaMasterTemplate', 'rd'
projections {
property 'id'
}
ilike 'rd.name', '%Rick%'
}
Related
so i require something like the dynamic finder should change as per the condition, let me explain by code what i mean
the below code find all employee by status and lastdateattended
def employee = Employee.findAllByStatusAndLastDateAttended("INA",dateObject)
now i have two fields in Employee LastDateAttended and LastDateSigned , and now i want that if a record does not have LastDateAttended, then it should find by LastDateSigned , otherwise LastDateAttended, so another condition is like
def employee = Employee.findAllByStatusAndLastDateAttended("INA",dateObject)
and i somehow wants to join and use both the query based on a condition , can it be achieved ?, if possible please help
I think criteria query make sense here, something like following
Employee.createCriteria().list{
and{
eq('status','INA')
or {
eq('lastDateAttended',dateObject)
eq('lastDateSigned',dateObject)
}
}
}
Employee.list().findAll { emp->
emp.status == "INA" && ( emp.lastDateAttended!=null?
emp.lastDateAttended.equals(dateObject):emp.lastDateSigned.equals(dateObject)
)
}
Employee.findAllByStatusOrLastDateAttendedOrStatusAndLastDateAttended("INA",dateObject)
I use EasyGrid plugin and must find values where integer field like '%001%'
initialCriteria {
ilike('id', "%"+params.id+"%")
}
But ilike doesn't work with Integer. How to do it?
I tried to do:
initialCriteria {
ilike('id'.toString(), "%"+params.id+"%")
}
initialCriteria {
ilike('str(id)', "%"+params.id+"%")
}
but it's not work.
If id is an integer in the database, then ilike doesn't really make much sense and there is probably a better way to do what you are trying to do (like adding a type field or something to the domain object, and filter by type)
However, you should be able to do something like this (untested):
initialCriteria {
sqlRestriction "cast( id AS char( 256 ) ) like '%001%'"
}
Following criteria not working if you search from your textbox when user search any text character by mistake like 12dfdsf as your searchable id. It will give you an exception
initialCriteria {
ilike('id', "%"+params.id+"%")
}
For better use you can use following criteria
initialCriteria {
sqlRestriction "id like '%${params?.id}%'"
}
You could do:
String paddedId = params.id.toString().padLeft(3,'0')
initialCriteria {
ilike('id', "%$paddedId%")
}
The solution offered by tim_yates with the sqlRestriction would work in version 1.5.0 of easygrid.
One of the main differences from 1.4.x is that the gorm datasource no longer uses DetachedCriteria, but Criteria - which maps directly to Hibernate's Criteria API.
So you can try it on the last version.
(Keep in mind that the upgrade might break your existing grids. There's also many other changes)
Another small observation is that 'initialCriteria' is not the right place to do stuff like that. (it's not wrong, but there is a 'globalFilterClosure' property for applying column independent filters)
I mixed the code posted by #tim_yates and mine:
String paddedId = params.id.toString().padLeft(3,'0')
def crit = Book.withCriteria {
sqlRestriction "lpad(cast( id AS char( 256 ) ), 3, '0') like '%${paddedId}%'"
}
I've tried with a h2 in-memory db and it works, but I am not sure about two things:
the real usefulness of that
lpad syntax consistence across all db engines
YMMV
I'm running grails 1.3.6 and I have this code:
String hql = '''
UPDATE
ApiResponse a
SET
a.lockId = :lockId
WHERE
a.lockId = 0
ORDER BY
a.dateAdded asc
LIMIT 5
'''
ApiResponse.executeUpdate(hql, [lockId : workerId])
It seems that this code updates all rows in DB instead of the 5 oldest entries. Does this mean LIMIT is not working in HQL? Please help me how to achieve the same SQL logic in GORM or HQL. Basically, I need to do a bulk update using LIMIT.
what i do (grails 1.3.7):
ExAus.executeQuery( "select distinct <field> from <controller>", [max: 20, offset: 0] )
While waiting for someone to reply, I think I found a workaround. Here it is:
def c = ApiResponse.createCriteria()
def targetList = c.list {
eq('lockId', 0)
maxResults(5)
order("dateAdded", 'asc')
}
String hql = '''
UPDATE
ApiResponse
SET
lockId = :lockId
WHERE
id in (:ids)
'''
ApiResponse.executeUpdate(hql, [lockId : workerId, ids: targetList.collect {it.id}])
I believe this approach can still be considered same logic with the original. However, this has to make 2 queries.
Feel free to suggest other approaches. Thanks!
I know the post is quite old but the question is still relevant since I had the same problem.
I fell back to using Groovy sql (jdbc) instead.
You will need to inject the dataSource object within your service/controller first by using:
def dataSource
Then you may do this in your method:
String sqlQuery = '''
UPDATE
API_RESPONSE a
SET
a.LOCK_ID = :lockId
WHERE
a.LOCK_ID = 0
ORDER BY
a.DATE_ADDED asc
LIMIT 5
'''
def sql = new Sql(dataSource)
sql.executeUpdate(sqlQuery, [lockId : workerId])
Note that you will need to use the database native table and column names in the sql query.
i use webflow in a my grails application, i have 2 tables with relation ManyToMany in hibernate mode. this relation as u know, creates a table with 2 primary keys of the original tables, both be the primary key of the third table.
my tables are destination and destinationGroup.
i write a select statement with dynamic finders to have a list of destnation group that has specific destination.
i try these ways and no effect for any one:
1-
def DestinationInstance = Destination.get(params.destination)
flow.DestinationGroupList = DestinationGroup.executeQuery("select distinct d.name,d.description from DestinationGroup d where d.destinations = :p",[p:DestinationInstance])
2-
def DestinationInstance = Destination.get(params.destination)
flow.destinationGroupList = DestinationGroup.findAllWhere(Destinations:destinationInstance)
3-
def DestinationInstance = Destination.get(params.destination)
flow.destinationGroupList = DestinationGroup.findAll("from DestinationGroup as d where d.destinations =:p", [p:destinationInstance]
)
these 3 statement has no effect, if there is any why for solving this problem please till me about it.
thanks
Have you tried a Criteria query?
def c = DestinationGroup.createCriteria()
flow.destinationGroupList = c.list{
destinations{
idEq(destinationInstance.id)
}
}
Is there a way to querying across 2 databases in grails ?
Example (I made a select on two databases - works and test) :
select
c.crf_name,
c.crf_id,
ig.group_id,
ig.group_name,
from
works.crfs c,
test.item_groups ig;
1) I would like to query against two databases, and attach results to a domain.
Or :
2) Is it possible to mixing one query part with data from database and other part with domain class ?
Edit : I need to do a single query mixing tables from 2 databases (one db is PostgreSQL and other db is Mysql). So, in grails is it possible to mix to dataSources beans in one query ?
Edit 2 : Here a better example :
select
igm.item_id,
igm.item_group_id as group_id,
igm.crf_version_id,
ig.name as group_name
from
works.item_group_metadata igm,
test.item_group ig
where
igm.item_group_id=ig.item_group_id
;
If you are planning to do your own sql (like it seems to be the case) over 2 datasources, I suggest that you define your 2 datasources as Spring beans in grails-app/conf/spring.
e.g. (drop your db drivers in /lib and replace the values to match your RDBMS drivers and connection string) :
import org.apache.commons.dbcp.BasicDataSource
import oracle.jdbc.driver.OracleDriver
beans = {
worksDataSource(BasicDataSource) {
driverClassName = "oracle.jdbc.driver.OracleDriver"
url = "jdbc:oracle:thin:#someserver:someport:works"
username = "works"
password = "workspassword"
}
testDataSource(BasicDataSource) {
driverClassName = "oracle.jdbc.driver.OracleDriver"
url = "jdbc:oracle:thin:#someserver:someport:test"
username = "test"
password = "testpassword"
}
}
Then create a service to handle your queries, like :
import groovy.sql.Sql
class SomeService {
def worksDataSource
def testDataSource
def query1 = """
SELECT crf_name, crf_id
FROM works.crfs
"""
def query2 = """
SELECT group_id, group_name
FROM test.item_groups
"""
def sqlWorks = Sql.newInstance(query1)
def sqlTest = Sql.newInstance(query2)
// Then do whatever you like with the results of the 2 queries
// e.g.
sqlWorks.eachRow{ row ->
def someDomainObject = new SomeDomainObject(prop1 : row.crf_name, prop2 : crf_id)
someDomainObject.otherProp = whateverYouLike()
someDomainObject.save()
}
}
Your query doesn't have a where clause so I don't know how you want to relate the data coming from your 2 tables...
If you want to do a single query mixing tables from 2 databases, (ask your DBA to) establish a DBLink between databases test and works and perform the query on the datasource containing the DBLink.
I hope this helps.
You should use a "UNION SELECT" which is supported by most databases. Make sure that both select statements have the same number of columns.
select
crf_name,
crf_id
from
ig
UNION SELECT
group_id,
group_name
from
id
A union select concatenates the results for 2 queries, for example:
select 1 union select 2
Have you looked at the Datasources plugin? It sounds like it will do what you require, but I think you'd need to use HQL or finders on the domain objects directly, rather than SQL, for it to work.
I haven't used the plugin myself but I'd be interested to hear how it goes it you try it.
HTH