How to avoid unnecessary inner join on a simple query on entity inheritance mapped with JOINED strategy? - sql

I'm using JPA 2 with Hibernate 4.2.0-Final as provider and I have the following entities:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
public class Person {
#Id
private String id;
.. Person attributes ..
.. Getters/Setters ..
}
#Entity
#Table(uniqueConstraints={#UniqueConstraint(name="UniqueCode", columnNames="code")})
public class Customer extends Person {
#Column(nullable=false)
private String code;
.. Other Customer attributes ..
.. Getters/Setters ..
}
And I have the following JPQL:
SELECT count(distinct c.code) FROM Customer c
For which Hibernate is generating the following SQL:
select
count(distinct customer0_.code) as col_0_0_
from
Customer customer0_
inner join
Person customer0_1_
on customer0_.id=customer0_1_.id
But I only need to count Customers with distinct code, which happens to be a field that is specific to Customer, so there is no need for the inner join to 'Person'. I'd like Hibernate to generate the SQL like follows (i.e. without joinning table 'Person'):
select
count(distinct customer0_.code) as col_0_0_
from
Customer customer0_
Is there a way to tell Hibernate to avoid the unnecessary inner join? Maybe some Hibernate-specific Query Hint?

The JOINED Strategy in JPA uses a separate table for each class in the object hierarchy.
So if you want to load objects for a subclass you also have to load information from the parent class (As the subclass alone does not represent complete picture without the attributes in the parent class). This results in a JOIN when querying for the sub-object.
From the JPA documentation you can see this as being a main disadvantage for The JOINED strategy.
1) Aside from certain uses of the table-per-class strategy described
below, the joined strategy is often the slowest of the inheritance
models. Retrieving any subclass requires one or more database joins,
and storing subclasses requires multiple INSERT or UPDATE statements.

Related

How to join Two tables of two non relashinship defined columns using Nhibernate QueryOver

Using NHibernate QueryOver, I want to join two tables using two columns which are not defined in the mapping as a relationship.
E.g. This is not my exact scenario but this can explain that
Tables:
Employee(Id, Name, DepartmentId, SomeCode,Address)
Department (Id, Name, ,Code)
Select
SELECT *
FROM EMPLOYEE E
JOIN DEPARTMENT D
ON D.Code = E.SomeCode
Can someone please tell me how to do this query using NHibernate QueryOver. Note that "SomeCode" in Employee and "Code" in Department are not defined as a relationship. DepartmentId is the foreign key and I can join these using JoinAlias but I want it in a somewhat different way.
There are similar questions, e.g.
NHibernate (+ FluentNhibernate) : Join two detached tables
Hibernate Criteria Projection without mapped association of tables
And the answer is:
either use HQL and CROSS JOIN (with WHERE)
There is NO way how to do that with QueryOver/Criteria)
See the doc:
14.2. The from clause
Multiple classes may appear, resulting in a cartesian product or "cross" join.
from Formula, Parameter
from Formula as form, Parameter as param
So using HQL in your case, we can do it like this:
SELECT ...
FROM EMPLOYEE E, DEPARTMENT D
WHERE D.Code = E.SomeCode
...
BUT I would suggest: create that mapping in the code. Simply introduce many-to-one relation. It will be loaded lazily (only if used) and will nicely serve to our needs - be used in QueryOver as a relation for Join
If there is such relation, if this exist in the business object domain, we should not be scared to use it. We can hide it via security etc...

Is it possible to optimize SQL Generated by Hibernate for OneToMany relationship with JoinTable?

I'm using JPA with Hibernate 4 as provider and I have the following entities:
#Entity
public class Customer {
#Id
private String id;
private String name;
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name="customers_phones",
joinColumns={#JoinColumn(name="id_customer")},
inverseJoinColumns={#JoinColumn(name="id_phone")}
)
private List<Phone> phones;
.. Getters/Setters ..
}
#Entity
public class Phone {
#Id
private String id;
private String number;
.. Getters/Setters ..
}
And I have the following JPQL:
SELECT c FROM Customer c INNER JOIN c.phones p WHERE p.id = :phone
For which Hibernate is generating the following SQL:
select
customer0_.id as id1_0_,
customer0_.name as name2_0_
from
Customer customer0_
inner join
customers_phones phones1_
on customer0_.id=phones1_.id_customer
inner join
Phone phone2_
on phones1_.id_phone=phone2_.id
where
phone2_.id=?
I'd like Hibernate to generate the SQL like follows (i.e. without joinning table 'Phone'):
select
customer0_.id as id1_0_,
customer0_.name as name2_0_
from
Customer customer0_
inner join
customers_phones phones1_
on customer0_.id=phones1_.id_customer
where
phones1_.id_phone=?
I know I could map a new entity to the join table 'customers_phones' associate it to Customer and use it in the query or I could use native SQL instead of JPQL, but I was wondering if there is a better way to achieve this (without changing entity model and still using JPQL), maybe some Hibernate-specific Query Hint?

Fluent NHibernate One-to-Many Mapping Results in Bad Query

I have a pretty simple one to many mapping using Fluent NHibernate and it works fine except the the queries NH generates are less than ideal. I found this when I checked the sql log from NH.
The query I am looking for is like
select p.*, c.* from parent p inner join child c on p.Id = c.parentId
where p.ID is the PK of the parent table and c.ParentId is a FK in the child table pointing to the PK of the parent table.
But what I found from the sql log is something like this:
select P.* from Parent
followed by a bunch of queries running against the child table like
select * from child c where c.ParentId = #p0
Not surprisingly this is causing performance issues.
My question is why NH is not generate the inner join query I think it should? What do I need to change so that NH will generate the desired query?
The JOIN is not suitable in this scenario. It will produce SELECT resulting in more rows, then the Parent table has. I.e: each child of a parent will append new row.
The appropriate solution here is to keep these selects separated. Firstly select the parent, then load all children for all parents (just selected parents). NHibernate does have nice solution for this:
19.1.5. Using batch fetching
Fluent version described here: How to Eager Load Associations without duplication in NHibernate?
This would work a bit similar as you experienced. Firstly select parent, then go for child(ren). The biggest difference is, that instead of 1 + N (going for each children collection separately) we now go for more children in batches. so it could be 1 + 2
Examples of the batch size mapping
1) Colleciton
HasMany<Child>(x => x.Children)
.BatchSize(25);
2) Entity itself
public ChildMap()
{
Id(x => x....
...
BatchSize(25);
There are many other advantages, where the PAGING is one of the most profitable. Because we are working with a flat (not multiplied) Parent, we can apply .Take() and .Skip()
Finally, fi we would like to find some Parents based on their children, we can use in this scenario Subqueries: 15.8. Detached queries and subqueries

When should I favor JOIN instead of attribute access in singular attributes?

Consider the following Entity:
#Entity
public class Employee {
#Id
#GeneratedValue
private Long id;
private String name;
// Assume that Project has a 'name' property
#OneToMany(mappedBy = "manager")
private List<Project> projects;
#OneToOne
private Department department;
// Assume that Computer has a 'model' property
#ManyToOne
private Computer computer;
//...
}
I want to get all Project names for given Employee.
In order to do this, I need to do a JOIN, so:
// JPQL query
SELECT p.name FROM Employee e JOIN e.projects p
// Criteria API equivalent (pseudo-code)
Root<Employee> emp = CriteriaQuery#from(Employee.class);
CriteriaQuery#select(emp.get(Employee_.projects).get(Project_.name));
And these queries are fine.
However, I cannot do:
// JPQL query
SELECT e.projects.name FROM Employee e
// Criteria API equivalent (pseudo-code)
Root<Employee> emp = CriteriaQuery#from(Employee.class);
Join<Employee, Project> empProj = emp.join(Employee_.projects);
CriteriaQuery#select(empProj.get(Project_.name));
As the JPA 2.0 specification forbids to use non-singular identification variable.
However, for singular attributes, I can access them using either JOIN or simply navigating to them using identification variable, so all of the following queries are valid and return the same result:
SELECT e.computer.model FROM Employee e
SELECT c.model FROM Employee e JOIN e.computer c
// Criteria API equivalents of the above JPQL (pseudo-code)
Root<Employee> emp = CriteriaQuery#from(Employee.class);
Join<Employee, Computer> empComp = emp.join(Employee_.computer);
CriteriaQuery#select(empComp.get(Computer_.model));
Root<Employee> emp = CriteriaQuery#from(Employee.class);
CriteriaQuery#select(emp.get(Employee_.computer).get(Computer_.model));
My questions are:
- when should I use explicit JOIN (either in JPQL or Criteria API's join(-) method)?
- what are the advantages / disadvantages of both approaches?
- is one of those considered more efficient than the other?
- if it's just a matter of style - which one would you prefer and why?
I just think about the type of the attribute. e.computer is a Computer, and I can thus call getModel() on it, so e.computer.model is OK. e.projects is a List, and I can't call getName() on a List, so e.projects.name is not OK. You need a join each time you need to access a member of a collection.
When using e.computer.id, a SQL join is not necessary (and not generated, at least by Hibernate), because the ID of the computer is in the employee table, as a foreign key. Using it is thus more efficient than using an explicit join. e.computer.model generates a SQL join, and it's just a matter of style and preference.
See 2.
I usually prefer explicit joins, because... it makes them explicit. It's also easier to transform them into left joins if needed.

hibernate define class from multiple columns in multiple tables

i have a class with some datafields:
class Call{
roomId
roomDisplay
roomLocation
typeId
name
staffAidId
}
now i would like to map this using hibernate annotations in java
but the original sql query that i used was something like this:
SELECT
c.roomId,
r.display,
r.location,
c.typeId,
c.staffAidId,
s.firstname,
s.lastname
FROM callalert c
JOIN staffmember s
LEFT JOIN roomGroup g ON g.groupId = s.roomGroupId
LEFT JOIN room r ON r.roomId = g.roomId
WHERE s.staffId = 4444 AND c.roomId = g.roomId
is there a way to map this
in other words:
is there a way to map columns from different tables to 1 custom class?
the class is no direct representation of 1 table
and from all the tables that are involved, not all columns are used
edit
I tried the view solution:
created a view with the above query
then I try to generate the hibernate classes using Netbeans
and I generates 2 classes:
the class Calls and an Embeddable class CallId
after searching the Internet this happens because hibernate needs a primary key so it creates one himself
how can I make sure only 1 class gets generated?
how do I give a view a primary key (a good primary key would be 1 of the primary keys of the underlying tables). how do i set this?
You should be able to do that if you create a database view for that query. It would work, but it has the downside that you can't auto-generate the ddl schema from the database models.
Check out this article