I have a reference to call that may or may not be there. When I add the nullable option it still doing Inner Join when I want an Left Join (show the left even if the right is null). Is this possible in the NH map?
References(x => x.DefaultCategory, "CATEGORY_ID")
.Nullable();
The join type isn't specified in the mapping, but in the query.
IN HQL, use left join syntax as with SQL.
With Criteria, use:
.CreateAlias("categories", "c", JoinType.LeftOuterJoin)
Related
I have an SQL query that I need to convert to an HQL query.
I have a class Item that contains a set of Components. The SQL table for Item is DBO.W_ITEM and the table for Component is DBO.W_COMPONENT.
In SQL, I've had no trouble doing this like so...
SELECT
item.noun,
comp.type
FROM
DBO.W_ITEM item
INNER JOIN DBO.W_COMPONENT comp ON item.id = comp.id
However, I can't get this to work in HQL.
I've tried it like this...
SELECT
item.noun,
comp.type
FROM
InventoryItemInv item
INNER JOIN item.components comp ON item.id = comp.id
but the HQL doesn't seem to know what to do with the ON - and says it's an unexpected token. According to all the literature, HQL supports the ON keyword.
Any suggestions?
Thanks in advance!
You don't need to use the ON clause to define the binding column, Hibernate will infer it from the relationship defined in the model, following HQL query should work for you
SELECT item.noun, comp.type
FROM InventoryItemInv item
INNER JOIN item.components comp
I'm not sure it is a active record bug or not.
Or is there a way to do .includes and disable the LEFT OUTER JOIN strategy explicitly.
Here is my cases:
Given the keyword is 'abc' without a 'dot'
Post.where(:name => "abc").includes(:author)
There are two sqls used as normal
Post Load (0.8ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`name` = 'abc'
Author Load (0.4ms) SELECT `authors`.* FROM `authors` WHERE `authors`.`id` IN (1)
Given the keyword is 'abc.' with a 'dot'
Post.where(:name => "abc.").includes(:author)
The sql is using LEFT OUTER JOIN strategy, that's confusing.
SELECT `posts`.`id` AS t0_r0, `posts`.`name` AS t0_r1, `posts`.`author_id` AS t0_r2, `posts`.`created_at` AS t0_r3, `posts`.`updated_at` AS t0_r4, `authors`.`id` AS t1_r0, `authors`.`created_at` AS t1_r1, `authors`.`updated_at` AS t1_r2
FROM `posts` LEFT OUTER JOIN `authors` ON `authors`.`id` = `posts`.`author_id`
WHERE `posts`.`name` = 'abc.'
I know eager loading with includes is realized with LEFT OUTER JOIN strategy when there are conditions on the association, like
Post.includes(:author).where(:authors => {:name => 'zhougn' })
But in my test cases, there is no such a condition. Basically both Multi-SQL strategy and LEFT OUTER JOIN strategy can give me correct result, but when Posts and Authors are stored in different databases, LEFT OUTER JOIN strategy will fail.
Yes, this is a bug. Issue #950: ActiveRecord query changing when a dot/period is in condition value. Fixed in Rails 4, it appears, by deprecating the feature that was getting hung up on this (no solution except to do it different and require the programmer to be explicit when they want a left outer join -- as well as which tables are referenced when using string conditions with includes).
My current dirty workaround (in Rails 3) is to encode/decode the dots like this:
.where("posts.name = REPLACE(?, '˙', '.')", somename.gsub(".", "˙"))
I am new with this. Please help me.
My inner join looks like this:
select p.idprodus, p.denumire, p.cantitate from Produs p inner join Furnizor f
on p.idfurn = f.idfurn
I want to make the inner join on the column idfurn, but I get these errors:
org.hibernate.QueryException: outer or full join must be followed by path expression select p.idprodus, p.denumire, p.cantitate from sakila.entity.Produs p inner join Furnizor f
on p.idfurn = f.idfurn
at org.hibernate.hql.classic.FromParser.token(FromParser.java:170)
at org.hibernate.hql.classic.ClauseParser.token(ClauseParser.java:86)
at org.hibernate.hql.classic.PreprocessingParser.token(PreprocessingParser.java:108)
at org.hibernate.hql.classic.ParserHelper.parse(ParserHelper.java:28)
at org.hibernate.hql.classic.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:216)
at org.hibernate.hql.classic.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:185)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
In HQL, you use entities, not tables. And entities are linked together by associations (OneToOne, OneToMany, etc.) Joins can anly be done between associated entities.
For example, if you have a ManyToOne association between Product and Provider, the HQL query is:
select p from Product p inner join p.provider provider where ...
The on clause is unnecessary, because Hibernate knows from the mapping of the ManyToOne association that a Product is associated with its provider using the product.id_provider foreign key to the provider.id_provider primary key.
All of this is very well explained, with lots of examples, in the Hibernate documentation.
If an association (e.g. OneToMany mapping) does not exist and you need an inner join then use the old cross join notation.
How can I change the default join type to be an inner join instead of a left outer join for mappings when I use References?
For Example:
public class SomeClassMap : ClassMap<SomeClass>
{
public SomeClassMap()
{
Id(x => Id);
References(x => x.Account);
}
}
this usually turns out to be something like this...
FROM SomeClass SC
LEFT OUTER JOIN Account A
ON SC.Id = A.Id
I'd like to have this be an inner join instead of a left outer join. Any thoughts?
Similar question here:
Inner or Right Outer Join in Nhibernate and Fluent Nhibernate on Many to Many collection
I'm assuming this also applies to one to many relationships. Someone please chime in if this does not hold true anymore.
Really quick question..
Does Linq2NHibernate always create a left join to retrieve relationships? Is there a way that I can get an inner one instead?
Thank you in advance.
Filipe
As far as I know.
For any relationship that is not One-to-One, NHibernate makes the assumption that the relationship could have 0 to many results, thus uses a Left Join.
I don't know about Linq2NHibernate, but in NH3 using QueryOver API you can specify the join types.
For example, give a Product with a Category. If you wrote:
var result = Session.QueryOver<Product>()
.Fetch(x => x.Category).Eager
.List();
This will result in a left join, if you wanted to specify an inner join you could write the same query as:
var result = Session.QueryOver<Product>()
.JoinQueryOver(x => x.Category, JoinType.InnerJoin)
.List();
This will result in an Inner Join.
As far as I know you can't specify join types when using the LINQ provider (Query<T> in NH3)