Grails search two child objects - grails

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.

Related

GORM 'where criteria' with multiple many-to-many associations

Assuming you have three domain objs defined as such:
class Author {
String name
static hasMany = [books: Book]
}
class Book {
String name
static belongsTo = [author: Author]
static hasMany = [words: Word]
}
class Word {
String text
Set<Author> getAuthors() {
// This throws GenericJDBCException:
Author.where {
books.words == this
}
}
}
Why does getAuthors() fail with ERROR spi.SqlExceptionHelper - Parameter "#1" is not set; but works fine if rewritten using a Criteria:
public Set<Author> getAuthors() {
// This works as expected:
Author.withCriteria {
books {
words {
eq('id', this.id)
}
}
}
}
Do I have the syntax of the 'where query' wrong???
It seems like the criteria for your query is sort of misleading. books and words are both associations and you are expecting that words to be equal to single instance of the word object.
You can try this:
def getAuthors() {
Author.where {
books{
words {
id == this.id
}
}
}.list()
}

Grails Query with parent

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
}
}

Restrict the rows retrieved from database for the relationship between the domain classes

I have two domain classes:
class Entity {
static hasMany = [
titles: Title
]
}
class Title {
Boolean isActive
static belongsTo = [entity:Entity]
static mapping = {
isActive type: 'yes_no'
}
}
Now when I am calling Entity.get(0) I would like to take from the database the Entity with id=0, but only with active Titles (where isActive = true). Is it possible in grails? I've tried to add where clause in static mapping of Title domain class:
static mapping = {
isActive type: 'yes_no'
where 'isActive = Y'
}
or
static mapping = {
isActive type: 'yes_no'
where 'isActive = true'
}
but it doesn't work. I am using Grails in version 2.2.1
Could You help me? Thank You in advance.
In this case you can use criteria to do that:
Entity.createCriteria().get {
eq('id', 0)
projections {
titles {
eq('isActive', true)
}
}
}
I don't think it's possible to set a default where to be applied in all your database calls to that Domain Class.
You can also wrap your logic in a service:
class EntityService {
def get(Long id) {
return Entity.createCriteria().get {
eq('id', id)
projections {
titles {
eq('isActive', true)
}
}
}
}
}

Call namedQuery inside a criteria in controller

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

Renaming composite foreign keys in GORM

I have the following classes:
class Catalog {
static mapping = {
id composite:['name', 'manufacturer']
columns {
name column:'cat_name'
manufacturer column:'manuf_id'
}
}
String name
Manufacturer manufacturer
}
class Order {
static mapping = {
columns {
// How to rename foreign keys as cat_name, manuf_id?
}
}
Catalog catalog // creates catalog_name, catalog_manufacturer_name
}
Presently, an Order table is generated with the attributes catalog_name and catalog_manufacturer_name (which reference the composite primary keys of the Catalog table).
I need to rename these generated columns to cat_name and manuf_id in the Order table to work with an existing database. Is this possible, and if so, how?
This solved my problem (grails 2.0.4):
http://jira.grails.org/browse/GRAILS-4504?focusedCommentId=64996&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-64996
My case:
class GroupMessage implements Serializable {
Group group
Integer messageId
static mapping = {
datasources(['ds1'])
table 't_group_msg'
version false
id composite: ['group', 'messageId'], generator: 'assigned'
group column:'grpid'
messageId column:'msgid', type:int
}
}
class GroupMessageDetail implements Serializable {
GroupMessage groupMessage
Integer detailId
String message
String url
static mapping = {
datasources(['ds1'])
table 't_group_msg_det'
version false
id composite: ['groupMessage', 'detailId'], generator: 'assigned'
columns {
groupMessage {
column name: 'grpid'
column name: 'msgid'
}
detailId column:'id', type:int
message column:'sms'
url column:'url'
}
}
It's not possible using GORM configuration, but you can do it with a custom Configuration class:
package com.foo.bar;
import java.util.Collection;
import java.util.Iterator;
import org.codehaus.groovy.grails.orm.hibernate.cfg.DefaultGrailsDomainConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
public class CompositeAwareHibernateConfiguration extends DefaultGrailsDomainConfiguration {
private static final long serialVersionUID = 1;
private boolean _alreadyProcessed;
#SuppressWarnings("unchecked")
#Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
if (_alreadyProcessed) {
return;
}
for (PersistentClass pc : (Collection<PersistentClass>)classes.values()) {
if (pc instanceof RootClass) {
RootClass root = (RootClass)pc;
if ("com.foo.bar.Order".equals(root.getClassName())) {
for (Iterator iter = root.getTable().getColumnIterator(); iter.hasNext(); ) {
Column column = (Column)iter.next();
if ("catalog_name".equals(column.getName())) {
column.setName("cat_name");
}
else if ("catalog_manufacturer_id".equals(column.getName())) {
column.setName("manuf_id");
}
}
}
}
}
_alreadyProcessed = true;
}
}
Put the class in src/java and register it in DataSource.groovy:
dataSource {
pooled = true
driverClassName = ...
username = ...
password = ...
configClass = com.foo.bar.CompositeAwareHibernateConfiguration
}
I have write a solution that is for any domain-class that need it and you don't need readapt every time.
class Catalog {
static mapping = {
id composite:['name', 'manufacturer']
columns {
name column:'cat_name'
manufacturer column:'manuf_id'
}
}
String name
Manufacturer manufacturer
}
class Order {
Catalog catalog
static mapping = {
}
static foreigners = [
catalog : [name : "catalog_name",
manufacturer: "catalog_manufacturer_name"]
]
}
This is the GORM Configuration class that i write to consume the foreigners in the domain class.
package my.app.package
import java.util.Collection;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
class MyCustomGrailsAnotationConfiguration extends GrailsAnnotationConfiguration{
private static final long serialVersionUID = 1;
private boolean _alreadyProcessed=false;
#SuppressWarnings("unchecked")
#Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
if(_alreadyProcessed){
return;
}
classes.values().each{rootClass ->
if(rootClass instanceof RootClass){
def domainClass= null
Boolean hasForeigners=false
try{
domainClass=Class.forName(rootClass.entityName,false,Thread.currentThread().getContextClassLoader())
hasForeigners = domainClass.metaClass.hasProperty(domainClass, 'foreigners')
}catch(Exception e){}
if(domainClass && hasForeigners){
rootClass?.table?.foreignKeyIterator?.each{fKey->
fKey?.columnIterator?.each{column->
domainClass.foreigners?.each{attrName,columns ->
columns.each{columnItmName,columnItmValue->
def exp=attrName+"_"
columnItmName.split("").each{exp+=(it==~/[A-Z]/) ? "_"+it:it}
exp=exp.toLowerCase()+".(id)\$"
//println "Expression:"+exp
if(column.name.matches(exp)){
//println "Match:"+column.name+" changing to "+columnItmValue
column.name=columnItmValue
}
}
}
}
}
}
}
}
_alreadyProcessed = true;
}
}
Put the my.app.package.MyCustomGrailsAnotationConfiguration.groovy class in src/groovy/my/app/package/MyCustomGrailsAnotationConfiguration.groovy and register it in DataSource.groovy:
dataSource {
pooled = true
driverClassName = ...
username = ...
password = ...
configClass = my.app.package.MyCustomGrailsAnotationConfiguration
}
I hope that will useful for you.
Thanks #carlosmain for your help

Resources