Is it possible to create class annotated with #Entity that in #NamedNativeQuery joins two different tables? For example native query is something like:
SELECT a.id as id, b.name as name
FROM tableA a
JOIN tableB b on a.id = b.id
WHERE a.id = :someValue and b.id = :someValue
What should I write in #Table annotation in this case?
Yes it's possible. The key is to use the #SqlResultSetMapping annotation. See The javadoc for #SqlResultSetMapping
Related
I am using spring data jpa. And I have a inner join on two tables. This is my query.
SELECT A.NAME, A.CARD_NUMBER, A.ADDRESS, A.EMAIL FROM USER_INFO ABC INNER JOIN USR_DETAIL DEF ON (ABC.ID = DEF.ID) WHERE ABC.ID = '123456';
The two table here have no relationship. So one-to-one or many-to-one or many-to-many on the column name doesn't make sense. Can I define entities without relationship? The reason why we are doing a inner join on the two tables here is simply because doing a join on both of them will be a expensive query.
You can define both entities without any kind of relationship and then you can retrieve the data specifying nativeQuery=true in the #Query(..) annotation in the read method.
#Query(value = "SELECT ABC.NAME, ABC.CARD_NUMBER, ABC.ADDRESS, ABC.EMAIL " +
"FROM USER_INFO ABC " +
"INNER JOIN USR_DETAIL DEF ON (ABC.ID = DEF.ID) " +
"WHERE ABC.ID = :id", nativeQuery = true)
UserInfoDetails retrieveUserInfoAndDetailById(#Param("id") String id);
Side notes:
In the projection of the query, I correct the alias from A to ABC as the query was not written correctly. Feel free to edit the projection accordingly to your needs.
As a return type, I wrote a UserInfoDetails class, supposing it will be return something similar. Feel free to change it accordingly to your needs.
How do I get JPA & JPQL to pass a complete join query to the RDBMS? For example,
SELECT e
FROM Employee e
WHERE a.runkey = e.runkey
AND e.middle = 'M'
AND a.state = 'MA'
With the following Employee class
#Entity
public class Employee implements Serializable {
blah ... blah
#OneToOne
#JoinColumn(
name = "runkey",
referencedColumnName = "runkey",
insertable=false, updatable=false)
private Address address;
}
and the JPQL,
SELECT e
FROM Employee e
INNER JOIN FETCH e.address AS a
WHERE a.state = :state
AND e.middle = :middle
I am able to get Hibernate JPA to pull the data as expected.
However, eclipselink croaks that it cannot traverse associated field "address".
If so, how then should I design the Employee entity and how should I phrase the JPQL in order to get eclipselink to execute a table join with WHERE filters on both tables?
(Rant: Otherwise Eclipselink JPA is no better than JDO!!!)
~
Further edit: Does this post mean anything to my case ....
https://forums.oracle.com/forums/thread.jspa?threadID=1568659
The problem is that you are trying to alias a join fetch which is not allowed according to the JPQL specs. Hibernate allows this anyway.
You can still obtain the desired behavior with EclipseLink using query hints.
Take a look at the following posts:
jpa fetch join query
EclipseLink JPQL (Glassfish v3): join fetch syntax problem?
The following link can also be useful:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/QueryOptimization
I have defined a JPA entity "A" with a #ManyToOne relationship to another JPA entity "B".
#Entity
class A {
String name;
int sortOrder
#ManyToOne
B b;
}
This reference can be null or it can be populated. Now, I would like to query all the As and sort by B.name. Unfortunately, something like
find("order by B.name, sortOrder, name")
seems to drop any As such that (A.b = null). What is the best way to write this query?
I want all the As and I want them sorted by their B.name reference if it exists ... lumping all those with no B property together.
you need a left join.
select a from A a left join a.b b order by b.name, a.sortOder, a.name
or something like that.
There are several approaches … Sets/Comparators, HQL, Native Sql, #Sort annotations …
I'm using a rather old version of Hibernate (3.2.4) so it's possible this is related to that. Unfortunately the project requirements prevent me from upgrading.
I have a class Foo with many-to-one association to Bar. The association is flagged:
lazy="false" fetch="join"
Now when I do something like:
em.find(Foo.class, id);
I get the expected result: a single statement joining the FOO table with the BAR table. However, when I try something like:
em.createQuery("select f from Foo where f.id = :id")
.setParameter("id", id)
.getSingleResult();
I get the single join followed by an additional select query against BAR. The second query seems to be entirely superfluous; all the data needed to eagerly populate an instance of Foo should have been available from the initial join. It looks roughly like this:
select f.id, f.xyz, ..., b.id, b.xyz, ...
from foo f
join bar b on b.id = f.bar_id
where f.id = ?
select b.id, b.xyz, ...
from bar b
where b.id = ?
Any thoughts?
Hibernate doesn't respect fetch = "join" when executing HQL queries. From the documentation:
The fetch strategy defined in the mapping document affects:
retrieval via get() or load()
retrieval that happens implicitly when an association is navigated
Criteria queries
HQL queries if subselect fetching is used
In the case of HQL queries you have to use left join fetch:
em.createQuery("select f from Foo f left join fetch f.bar where f.id = :id")
.setParameter("id", id)
.getSingleResult();
I have some entity:
public class Album extends GenericAuditedEntity {
#OneToMany(fetch = FetchType.LAZY)
private Set<Item> itemSet = new HashSet<Item>();
}
And when i run HQL like this:
em.createQuery("select a from Album a").getResults()
it produses many SQL queries:
One for select data from Album's table. Smth like this: select .... from Album_table;
And one query for each fetched row, for selecting items. Smth like this:
select .... from Item_table iwhere i.Album_id = :Album_id;
But when i run em.createQuery("
select a.id, b.id
from Album a
left join Item i
").getResults()
it produses one SQL query. But it's result is list of some parameters, that i need put into the entities manually.
How can i build HQL with joins automatically and automatically put the results to the entities? Is it possible?
You need to use join fetch:
em.createQuery("select a.id, b.id from Album a left join fetch Item i ").getResults();
Note that there are certain side effects to that, described in detail the above link.
If you are using join fetch then you don't need the IDs, you can retrieve the Entity as Hibernate will also populate the association in it's first-level cache
em.createQuery("select a from Album a left join fetch a.itemSet").getResultList();
However if you are retrieving the IDs but want populated Objects/Entities then consider using a Constructor
em.createQuery("select new com.xxx.AlbumItem(a.id, b.id) from Album a left join fetch a.itemSet b").getResultList();
dont use lazy fetching. set fetch type to eager