For example I need to retrieve several registers in a table, and edit a field, but it takes too long to save all with a loop, does exist a better way to save?
This how I do it....
class Table
static mapping = {
table "TABLEEX"
id generator:'sequence', params:[sequence:'TABLEEX_SEQ']
}
// identificacion
String data1
String data2
}
And searching the data:
def stuff = Table.createCriteria().list{
eq("data1","1")
}
And editing and saving
stuff.each {
it.data2 = "aaa"
it.save()
}
It isn't clear why you are retrieving the objects to begin with. Is something like this what you are looking for?
Table.executeUpdate("update Table t set t.data2=:newData where t.data1=:oldData", [newData: 'BAR', oldData: 'FOO'])
EDIT
You could also do something like this...
def query = Table.where {
data1 == 'FOO'
}
int total = query.updateAll(data2:'BAR')
Hibernate (the underlying mechanism of gorm, the grails orm) does not support that.
You'll have to iterate over every element and save or implement it yourself (and that will not make it faster).
Related
I have a domain class
class Url {
UUID id
String url
static hasMany = [
indications:UrlIndication
]
...
}
And
class UrlIndication {
UUID id
String name
static belongsTo = Url
...
}
I want to choose urls so that it has all the necessary UrlIndication elements in a given list indicationsId.
For that I use an association and criteria like this one:
indications {
and {
indicationsId.each{
indication->
eq ('id',UUID.fromString(indication as String))
}
}
}
However, all I got is an empty result. Can you suggest any modifications/ other methods so that I can do this? Thanks in advance
Your query returned an empty list because it's the equivalent of the expression (pseudo-code): if 1 = 1 and 1 = 2 and 1 = 3
Such an expression would always be false. in or inList would not work for the reason #innovatism described.
In theory, Criteria's eqAll() or HQL's = ALL would work. But, I don't know for sure because I could not get either one to work.
What will work is to use inList to return a subset of Urls: those which contain at least one of the UrlIndication IDs. Then use Groovy's containsAll() to finish the job.
def ids = indicationsId.collect { UUID.fromString(it as String) }
Url.createCriteria()
.buildCriteria {
indications {
inList 'id', ids
}
}
.setResultTransformer(org.hibernate.Criteria.DISTINCT_ROOT_ENTITY)
.list()
.findAll {
it.indications.id.containsAll(ids)
}
Since the query has the potential to return duplicate Url instances, the ResultTransformer is set to return a unique list.
Finally, findAll() is used along with containsAll() to filter the list further.
Using eqAll (maybe)
Something like the following might work. Something funky is going on with Grails' HibernateCriteriaBuilder that causes the eqAll method to look up properties in the root entity; completely ignoring the sub criteria. So the following uses Hibernate directly. It didn't work for me, but it's as close as I could get. And it gave me a head-ache!
Url.createCriteria().buildCriteria {}
.createCriteria('indications', 'i')
.add(org.hibernate.criterion.Property.forName('i.id').eqAll(org.hibernate.criterion.DetachedCriteria.forClass(UrlIndication)
.add(org.hibernate.criterion.Restrictions.in('id', ids))
.setProjection(org.hibernate.criterion.Property.forName('id'))
))
.setResultTransformer(org.hibernate.Criteria.DISTINCT_ROOT_ENTITY)
.list()
The problem I had is I could not get Restrictions.in to work. Restrictions.eq works fine.
the in clause should do:
indications {
'in' 'id', indicationsId.collect{ UUID.fromString indication.toString() }
}
Given a namedQuery:
class MyDomainObject {
String someProperty
static namedQueries = {
myNamedQuery {
// some implementation here
}
}
}
I can use it to generate a list, sorted by a single key, like this (documentation for 2.4.3 here):
def resultsList = MyDomainObject.myNamedQuery.list(sort: "someProperty", order: "desc")
How do I order the results by multiple columns? I'd like to be able to define the sort parameters dynamically, not define them in the query.
I'm sure there's a better way, but I ended up creating another named query that I can concatenate onto my chosen one (I could always incorporate into the original query too).
// expects to be passed a List containing a series of Maps
orderByMultipleColumns { List columnsToSortBy ->
columnsToSortBy.each { Map field ->
order("${field.fieldName}", field.fieldOrder)
}
}
// usage:
List orderByList = []
// ...
// within some loop that I use:
orderByList << [fieldName: someValue, fieldOrder: dir] // dir == 'asc' or 'desc'
// ...
MyDomainObject.myNamedQuery().orderByMultipleColumns(orderList).listDistinct(max: length, offset: start)
I have a query that bring back a cell in my table the has all xml in it. I have it so I can spit out what is in the cell without any delimiters. Now i need to actually take each individual element and link them with my object. Is there any easy way to do this?
def sql
def dataSource
static transactional = true
def pullLogs(String username, String id) {
if(username != null && id != null) {
sql = new Sql(dataSource)
println "Data source is: " + dataSource.toString()
def schema = dataSource.properties.defaultSchema
sql.query('select USERID, AUDIT_DETAILS from DEV.AUDIT_LOG T WHERE XMLEXISTS(\'\$s/*/user[id=\"' + id + '\" or username=\"'+username+'\"]\' passing T.AUDIT_DETAILS as \"s\") ORDER BY AUDIT_EVENT', []) { ResultSet rs ->
while (rs.next()) {
def auditDetails = new XmlSlurper().parseText(rs.getString('AUDIT_EVENT_DETAILS'))
println auditDetails.toString
}
}
sql.close()
}
}
now this will give me that cell with those audit details in it. Bad thing is that is just puts all the information from the field in on giant string without the element tags. How would I go through and assign the values to a object. I have been trying to work with this example http://gallemore.blogspot.com/2008/04/groovy-xmlslurper.html with no luck since that works with a file.
I have to be missing something. I tried running another parseText(auditDetails) but haven't had any luck on that.
Any suggestions?
EDIT:
The xml int that field looks like
<user><username>scottsmith</username><timestamp>tues 5th 2009</timestamp></user>
^ simular to how it is except mine is ALOT longer. It comes out as "scottsmithtue 5th 2009" so on and so forth. I need to actually take those tags and link them to my object instead of just printing them in one conjoined string.
Just do
auditDetails.username
Or
auditDetails.timestamp
To access the properties you require
I'm working on speed issues with a currently working method that finds a specific attribute collection within an ArrayList. Depending on the size, it can take longer than 7 seconds to find the value in the list.
I need to speed up this process, so I can deal with larger volumes of data. Any assistance would be greatly appreciated. Here is my example;
Method:
public ArrayList getIntegrationTag(String attribute) {
return crmMapping?.findAll { it.get("ATTRIBUTE") == attribute }?.collect{
it.INTEGRATION_TAG
}?.unique()
}//end getIntegrationTag(String attribute)
crmMapping content
"[{ATTRIBUTE=AcademicIndex, INTEGRATION_TAG=Contact~nAcademic_Index},
{ATTRIBUTE=AcademicInterest,
INTEGRATION_TAG=Contact~msplAcademic_Interest},........]"
the findAll loops over each record, then the collect loops over each record, then unique loops over each record again.
Try...
Set result = [] as Set
for(element in crmMapping) {
if(element.get("ATTRIBUTE") == attribute) {
result << element.INTEGRATION_TAG
}
}
return (result as ArrayList)
This will only loop once it it will be unique as it was added to a Set
Do the following once
def crmMappingMap = crmMapping.groupBy({ it.ATTRIBUTE })
Then you have a map of all same attribute instances and can access it using crmMappingMap[attribute].INTEGRATION_TAG, which will return the desired array, like this:
public ArrayList getIntegrationTag(String attribute) {
crmMappingMap[attribute].INTEGRATION_TAG.unique()
}
Always keep a map, then speed of access will be fast enough.
I have a table called employee and child table address.
Now I want to get a list of employees sort by address1 in address table using GORM.
Employee.findAllByName(name, [max: maxRecords, offset: 100,sort: Address.address1, order: desc])
the above statement is not working, any suggestions would be appreciated.
Thanks
Try using a criteria query like so...
def c = Employee.createCriteria()
def results = c.list (max: maxRecords, offset: 100) {
eq("name", name)
address {
order("addres1", "desc")
}
}
This works for me!
Another option is to add a default sort order like so...
class Address{
…
static mapping = {
sort address1:"desc"
}
}
However, I always prefer to do things as an 'as-needed' basis rather than define that sorting be done every time even when it may not be needed. U pick. Enjoy!