How to access relationship table when doing executeQuery in Grails? - grails

Is it possible to access the relationship table when doing HQL statement?
As an example, I have 3 tables: account, commitment, account_commitment. It was generated using these domains:
class Account {
static hasMany = [ commits : Commitment ]
String name
}
class Commitment {
static hasMany = [ actors : Account ]
String description
}
My final and actual SQL query is something like this:
SELECT
b.id,
account_name,
d.nid,
d.title
FROM
account_commitment a, // is this available in HQL?
account b,
commitment c,
content_type_act d
where
d.nid = 3332
and a.account_id = b.id
and a.act_id = c.id
and c.act_id = d.nid
I believe HQL only allows valid class domains. Since the relationship table is automatically generated, is this possible in HQL?
Thanks.

No, HQL only works with mapped classes. If you want to run SQL queries just use groovy.sql.Sql. But if you only want to access the intermediate table to join the other two, that's unnecessary since HQL knows about the relationships between tables already.

Related

Unusual Joins SQL

I am having to convert code written by a former employee to work in a new database. In doing so I came across some joins I have never seen and do not fully understand how they work or if there is a need for them to be done in this fashion.
The joins look like this:
From Table A
Join(Table B
Join Table C
on B.Field1 = C.Field1)
On A.Field1 = B.Field1
Does this code function differently from something like this:
From Table A
Join Table B
On A.Field1 = B.Field1
Join Table C
On B.Field1 = C.Field1
If there is a difference please explain the purpose of the first set of code.
All of this is done in SQL Server 2012. Thanks in advance for any help you can provide.
I could create a temp table and then join that. But why use up the cycles\RAM on additional storage and indexes if I can just do it on the fly?
I ran across this scenario today in SSRS - a user wanted to see all the Individuals granted access through an AD group. The user was using a cursor and some temp tables to get the users out of AD and then joining the user to each SSRS object (Folders, reports, linked reports) associated with the AD group. I simplified the whole thing with Cross Apply and a sub query.
GroupMembers table
GroupName
UserID
UserName
AccountType
AccountTypeDesc
SSRSOjbects_Permissions table
Path
PathType
RoleName
RoleDesc
Name (AD group name)
The query needs to return each individual in an AD group associated with each report. Basically a Cartesian product of users to reports within a subset of data. The easiest way to do this looks like this:
select
G.GroupName, G.UserID, G.Name, G.AccountType, G.AccountTypeDesc,
[Path], PathType, RoleName, RoleDesc
from
GroupMembers G
cross apply
(select
[Path], PathType, RoleName, RoleDesc
from
SSRSOjbects_Permissions
where
Name = G.GroupName) S;
You could achieve this with a temp table and some outer joins, but why waste system resources?
I saw this kind of joins - it's MS Access style for handling multi-table joins. In MS Access you need to nest each subsequent join statement into its level brackets. So, for example this T-SQL join:
SELECT a.columna, b.columnb, c.columnc
FROM tablea AS a
LEFT JOIN tableb AS b ON a.id = b.id
LEFT JOIN tablec AS c ON a.id = c.id
you should convert to this:
SELECT a.columna, b.columnb, c.columnc
FROM ((tablea AS a) LEFT JOIN tableb AS b ON a.id = b.id) LEFT JOIN tablec AS c ON a.id = c.id
So, yes, I believe you are right in your assumption

Save record having reference to another record in Grails Domain

I have 2 domain classes: A and B, defined as follow:
class A {
String data
static hasMany = [bs: B]
}
class B {
String data
static belongsTo = [a: A]
}
Now we have field a_id in table B.
The problem is that I had a_id already, how can I properly insert a new B record with a_id as foreign key?
Currently I did like this:
B b = new B(
data: "data",
a: A.get(a_id)
)
b.save()
=> To be able to insert the B record, I have to do one more query which get the whole A object, such a wasting time & memory since a_id alone is already enough.
Thank you very much.
No way to do that, sadly.
If you want to optimize, consider using B.executeUpdate or even raw SQL
Sql sql = new Sql(dataSource)
sql.executeUpdate("insert into....")

Grails left outer join query HQL or criteria challenge

I am a newbie to hql and tried out several combinations that i could find but i seem unable to construct the correct HQL query for a left join.
I have the following domain model:
class Company {
static hasMany = [employees: Employee]
}
class Employee {
static belongsTo = [
Company
]
}
So a employee does not know anything about the companies. Now i would like to create a hql query that gives met the employees without a company. In sql i have successfully created the query using a left join but i seem not to be able to create a criteria or hql query that gives me a correct result.
Any a clue or some tips on how i could achieve the result?
Here you go, this works:
Employee.executeQuery("""
Select e
from Employee e
where e not in (Select ce from Company c left join c.employees ce)
""")

Criteria to get all domains with collection less than property

Given the following domain class:
class Game {
Integer maxUsers
static hasMany = [users: User]
}
Using the Criteria API, what should I do to get all domains with the number of users less than maxUsers property?
I don't think it's possible to do with Criteria api, as Hibernate Criteria don't support HAVING clause. There is an open JIRA issue for that, you can try patches submitted there.
An alternative would be to use HQL:
def results = Game.findAll("from Game where id in (select g.id from Game g join g.users u group by g.id, g.maxUsers having count(u) < g.maxUsers)")

NHibernate: getting object model with HQL using a join on table

I am having difficult time trying to figure out how to get a mapped object using a join on a table (not mapped table).
Tables:
DataForm: (Id, AliasName (FK), ...)
Customer: (Id, ...)
CustomerAliases: (PK AliasName, CustomerId (FK))
So aliases are unique for every Customer and Customer may have many aliases.
Code:
DataForm.Customer - this is what I need
So how do I write the HQL in the getter?
Since CustomerAliases table is just a list of aliases I don't have it mapped to a class but is accessed through on the Customer. How can I get Customer using AliasName?
If it was normal SQL I would just do:
SELECT * From Customer c
INNER JOIN CustomerAliases ca ON ca.AliasName = 'AliasNameProvided'
WHERE ca.CustomerId = c.Id
HQL can only be use on mapped classes. When you leave the mapped area, you need to use SQL which looks exactly like the SQL in your question.
I would map it:
class Customer
{
IList<string> AliasNames { get; private set; }
}
mapping:
<class name="Customer">
<!-- ..... -->
<bag name="AliaseNames" table="CustomerAliases">
<key column="CustomerId"/>
<element column="AliasName"/>
</bag>
</class>
query:
from Customer c join c.AliasNames n
where n = :alias

Resources