There are about 20000 records in my DB but I only want to fetch 500 records at a time. I am using named queries for fetching data. So, how can I put a limit to named queries?
I tried like this,
#NamedQuery(name = "qryChildEventByOrganization", query = "select childEvent from ChildEvent childEvent limit 500"
+ "left outer join fetch childEvent.child as ceChild "
+ "left outer join fetch ceChild.address as address "
+ "left outer join fetch ceChild.user as cuser "
+ "left outer join fetch childEvent.user as ceuser "
+ "left outer join fetch cuser.address as caddress "
+ "left outer join fetch ceuser.address as ceaddress "
+ "left outer join fetch ceChild.immunization as cimmunization "
+ "left outer join fetch ceChild.insurance as cinsurance "
+ "left outer join fetch ceChild.healthHistory as chealthHistory "
+ "left outer join fetch ceChild.emergencyContact as cemergencyContact "
+ "left outer join fetch ceChild.doctor as cdoctor "
+ "left outer join fetch ceChild.dietActivityRestriction as cdietActivityRestriction "
+ "left outer join fetch ceChild.allergy as cAllergy "
+ "left outer join fetch ceChild.medication as cMedication "
+ "left outer join fetch ceChild.provider as cProvider "
+ "left join fetch childEvent.event as ceEvent "
+ "left join fetch ceEvent.organization as eOrganization "
+ "left join fetch eOrganization.address as oAddress "
+ "left outer join fetch ceChild.childEvent as cChildEvent "
+ "left join fetch cChildEvent.event as ceEventChildCe "
+ "left join fetch ceEventChildCe.organization as eCeOrganization "
+ "left join fetch eCeOrganization.address as oCeAddress "
+ "left outer join fetch cChildEvent.child as cCEChild "
+ "left outer join fetch cCEChild.address as address "
+ "left outer join fetch cCEChild.user as cuser "
+ "left outer join fetch cuser.address as ceaddress "
+ "left outer join fetch cCEChild.immunization as cimmunization "
+ "left outer join fetch cCEChild.insurance as cinsurance "
+ "left outer join fetch cCEChild.healthHistory as chealthHistory "
+ "left outer join fetch cCEChild.emergencyContact as cemergencyContact "
+ "left outer join fetch cCEChild.doctor as cdoctor "
+ "left outer join fetch cCEChild.dietActivityRestriction as cdietActivityRestriction "
+ "left outer join fetch cCEChild.allergy as cAllergy "
+ "left outer join fetch cCEChild.medication as cMedication "
+ "where childEvent.event.organization.organizationId = :organizationId AND (childEvent.status is null OR childEvent.status LIKE 'Active')"),
You can achieve this task by using hibernate criteria query language as follows:-
Crietria c=session.createCriteria(XYZ.class);
c.setFirstResult(1);
c.setMaxResult(500);
Related
I'm using JpaRepository and I'm creating a #Query in my repository:
this is my query:
#Query( "SELECT SUM(p.prima) as prima, p.producto as producto, p.tipoProducto as tipoProducto, p.compania as compania, p.cliente as cliente, p.vendedor as vendedor " +
"FROM Poliza p " +
"JOIN Producto pr ON p.producto=pr " +
"JOIN TipoProducto tp ON p.tipoProducto=tp " +
"JOIN Compania c ON p.compania=c " +
"JOIN Cliente cl ON p.cliente=cl " +
"LEFT JOIN Vendedor v ON p.vendedor=v " +
"WHERE p.comienzo >=?1 " +
"AND p.comienzo <= ?2 " +
"GROUP BY p.producto")
and I realize that I only get the rows where "Vendedor" is present.
I used the spring.jpa.show-sql=true property to check what was going on and I realize that the query is creating an inner join for each property in the SELECT STATEMENT
inner join producto producto1_ on (poliza0_.producto=producto1_.id)
inner join tipo_producto tipoproduc2_ on (poliza0_.tipo_producto=tipoproduc2_.id)
inner join compania compania3_ on (poliza0_.compania=compania3_.id)
inner join cliente cliente4_ on (poliza0_.cliente=cliente4_.id)
inner join vendedor vendedor5_ on (poliza0_.vendedor=vendedor5_.id)
join producto producto6_ on poliza0_.producto=producto6_.id
join tipo_producto tipoproduc7_ on poliza0_.tipo_producto=tipoproduc7_.id
join compania compania8_ on poliza0_.compania=compania8_.id
join cliente cliente9_ on poliza0_.cliente=cliente9_.id
left join vendedor vendedor10_ on poliza0_.vendedor=vendedor10_.id
As you can see in the first part I have an inner join from Vendedor which makes the query wrong.
How should I create my query to get the expected result?
if understand clearly
#Query( "SELECT SUM(p.prima) as prima, p.producto as producto, p.tipoProducto as tipoProducto, p.compania as compania, p.cliente as cliente, p.vendedor as vendedor " +
"FROM Poliza p " +
"JOIN Producto pr ON p.producto=pr " +
"JOIN TipoProducto tp ON p.tipoProducto=tp " +
"JOIN Compania c ON p.compania=c " +
"JOIN Cliente cl ON p.cliente=cl " +
"LEFT JOIN Vendedor v ON p.vendedor=v " +
"WHERE p.comienzo >=?1 " +
"AND p.comienzo <= ?2 " +
"GROUP BY p.producto")
i think you can using v instead p.vendedor as vendedor in select field.
If I read correctly, you are defining your own query. So, you can edit the JOIN in your query and write LEFT JOIN instead.
Am I right on your intentions?
I have the following model:
public class BaseModel {
List<DataA> lazyCollectionA;
List<DataB> lazyCollectionB;
}
public class DataA {
OtherEntity otherEntity;
}
public class OtherEntity {
List<DataC> lazyCollectionC;
}
When I visit a particular page I need to use all this data. This is creating a performance select n+1 problem.
I already partly solved the issue by eagerly fetching the collections using:
List<BaseModel> result = entityManager.createQuery(
"select m from BaseModel m " +
"left join fetch m.lazyCollectionA " +
"where m.id in (:ids) ", BaseModel.class)
.setParameter("ids", ids)
.getResultList();
result = entityManager.createQuery(
"select m from BaseModel m " +
"left join fetch m.lazyCollectionB " +
"where m.id in (:ids) ", BaseModel.class)
.setParameter("ids", ids)
.getResultList();
Note that I had to perform 2 queries instead of only 1 because otherwise I would get a MultipleBagFetchException.
However, I'm having problems eagerly loading lazyCollectionA.otherEntity.lazyCollectionC. I tried several variations of the query to try to eagerly fetch the results, but when otherEntity.lazyCollectionC is accessed, the select n+1 problem keeps surfacing.
I think this should work, but unfortunately it is not:
entityManager.createQuery(
"select a from BaseModel m " +
"left join m.lazyCollectionA a " +
"left join fetch a.otherEntity o " +
"left join fetch o.lazyCollectionC " +
"where m.id in (:ids) ", BaseModel.class)
.setParameter("ids", ids)
.getResultList();
Do you have any ideas why this is not working?
Also, I don't fully understand how my first 2 queries to load lazyCollectionA and lazyCollectionB are working. I mean, since they are loaded at different times, I would expect that only the last query would have the loaded instances. Is it because hibernate is caching the results and therefore it does not need to query the database again?
Thanks for any help you can provide!
I assume that all connections between your models are #OneToMany. In this case you could try simething like this:
#Autowired
private EntityManager em;
#Transactional
public List<BaseModel> getAllByThreeQueries() {
List<Long> ids = Arrays.asList(1L);
List<BaseModel> first = em.createQuery(
"select distinct m from BaseModel m " +
"left join fetch m.lazyCollectionB " +
"where m.id in (:ids) ", BaseModel.class)
.setParameter("ids", ids)
.getResultList();
List<BaseModel> second = em.createQuery(
"select distinct m from BaseModel m " +
"left join fetch m.lazyCollectionA a " +
"left join fetch a.otherEntity o " +
"where m in (:models) ", BaseModel.class)
.setParameter("models", first)
.getResultList();
em.createQuery("select distinct a from BaseModel m " +
"left join m.lazyCollectionA a " +
"left join fetch a.otherEntity o " +
"left join fetch o.lazyCollectionC " +
"where m in (:models) ", DataA.class)
.setParameter("models", second)
.getResultList();
return second;
}
Full code
Do you have any ideas why this is not working?
entityManager.createQuery(
"select a from BaseModel m " +
"left join m.lazyCollectionA a " +
"left join fetch a.otherEntity o " +
"left join fetch o.lazyCollectionC " +
"where m.id in (:ids) ", BaseModel.class)
.setParameter("ids", ids)
.getResultList();
Because you get a MultipleBagFetchException in this case. You need to do one more request.
I have the following query with all of these join/fetches:
public interface InitiativeRepository extends JpaRepository<Initiative, Long> {
#Query("select distinct i from Initiative i " +
"left join fetch i.theme t " +
"left join fetch t.themeQuestions tq " +
"left join fetch tq.initiativeProfileQuestion ipq " +
"left join fetch ipq.answers " +
"left join fetch ipq.answerLogs al " +
"where al.revision = i.revision " +
"order by ipq.question asc")
public List<Initiative> getThemeAndQuestionsAndAnswerLogs();
}
Because I'm doing so many joins, obviously hibernate is fetching all attributes of each object. For example, left join fetch i.theme t fetches all attributes of theme. What if I only want to fetch the theme name and themeQuestions attribute within the theme object (I don't want any unnecessary ones)?
I'm not sure if this is doable through only an annotated query. Any ideas would be appreciated.
Left outer join is supposed to get all data from left table no matter if there is matching record from B table, however if left tables right_id column is null, records cant be got.
I am explaining more
In Data model: Order.java, it is my LEFT table, there is a one to one relation
#OneToOne(targetEntity = OrderShippingDetail.class, optional=true, cascade = {CascadeType.ALL})
#JoinColumn(name = "SHIPPING_DETAIL_ID", referencedColumnName = "ID")
private OrderShippingDetail shippingDetail;
and HQL is:
hql = "SELECT " +
"o.id as id, " +
"o.createTime as createTime, " +
"o.customerEmailAddress as customerEmailAddress, " +
"o.customerPhoneNumber as customerPhoneNumber, " +
"o.customerNote as customerNote, " +
"o.invoicePrintedFlag as invoicePrintedFlag, " +
"shippingAddress.address.personName as shippingPersonName, " +
"shippingDetail.shippingCompany.id as shippingCompanyId, "+
"shippingDetail.shippingCompany.name as shippingCompanyName, "+
"shippingDetail.receiptNumber as shippingReceiptNumber, "+
"shippingDetail.trackingNumber as shippingTrackingNumber, "+
"shippingDetail.price as shippingPrice, "+
"o.invoiceNumber as invoiceNumber " +
"FROM Order AS o " +
"LEFT OUTER JOIN o.shippingAddress AS shippingAddress " +
"LEFT OUTER JOIN o.shippingDetail AS shippingDetail ";
But there comes just records which "SHIPPING_DETAIL_ID" is NOT null. Is there an error with HQL? It is created by modelling SQL command which is automatically created when hibernate runs.
I found this,
HQL supports two forms of association joining: implicit and explicit.
The queries shown in the previous section all use the explicit form,
that is, where the join keyword is explicitly used in the from clause.
This is the recommended form.
The implicit form does not use the join keyword. Instead, the
associations are "dereferenced" using dot-notation. implicit joins can
appear in any of the HQL clauses. implicit join result in inner joins
in the resulting SQL statement.
And I remove my dot notation in the SELECT part, so my new HQL:
hql = "SELECT " +
"o.id as id, " +
"o.createTime as createTime, " +
"o.customerEmailAddress as customerEmailAddress, " +
"o.customerPhoneNumber as customerPhoneNumber, " +
"o.customerNote as customerNote, " +
"o.invoicePrintedFlag as invoicePrintedFlag, " +
"shippingDetail, " +
"o.invoiceNumber as invoiceNumber " +
"FROM Order AS o " +
"LEFT OUTER JOIN o.shippingAddress AS shippingAddress " +
"LEFT OUTER JOIN o.shippingDetail AS shippingDetail ";
So, it works, it returns all records in Order table, however, I dont want to select all columns and relations in the ShippingDetail object. What can I do to solve this issue?
Add another explicit left join to the query:
SELECT o.id as id,
...,
shippingCompany.id as shippingCompanyId,
shippingCompany.name as shippingCompanyName,
...
FROM Order AS o
LEFT OUTER JOIN o.shippingAddress AS shippingAddress
LEFT OUTER JOIN o.shippingDetail AS shippingDetail
LEFT OUTER JOIN shippingDetail.shippingCompany AS shippingCompany
I have run into a bit of nag. In order to get some data from one of my drupal SQL databases, I need quite an elaborate query. The problem is that in console/MysqlWorkBench the query works fine, while in my JAVA program using JDBC it does not work at all.
The original query is:
# Tag use from the perspective of all tag entries belonging to nodes in table 'field_data_field_topic'
SELECT fdf.entity_type, node.nid, td.name, td.tid, ti.created, users.uid
FROM field_data_field_topic fdf LEFT OUTER JOIN taxonomy_term_data td
ON(fdf.field_topic_tid = td.tid)
LEFT OUTER JOIN taxonomy_index ti
ON(fdf.field_topic_tid = ti.tid AND fdf.entity_id = ti.nid)
LEFT OUTER JOIN node
ON(fdf.entity_id = node.nid)
LEFT OUTER JOIN field_data_body fd
ON(fd.entity_id = node.nid)
LEFT OUTER JOIN users
ON(users.uid = node.uid)
#Restricting to content from 01-02-2012 up to 11-06-2012
WHERE node.created > 1328054400
#Restricting to either Nodes or Comments
AND fdf.entity_type = "node"
#Restricting to node status=1
AND node.status=1
#Remove defective node with nid=1594
AND node.nid not like "1594"
UNION
# Tag use from the perspective of all tag entries belonging to comments in table 'field_data_field_topic'
SELECT fdf.entity_type, comment.cid, td.name, td.tid, ti.created, users.uid
FROM field_data_field_topic fdf LEFT OUTER JOIN taxonomy_term_data td
ON(fdf.field_topic_tid = td.tid)
LEFT OUTER JOIN taxonomy_index ti
ON(fdf.field_topic_tid = ti.tid AND fdf.entity_id = ti.nid)
LEFT OUTER JOIN comment
ON(fdf.entity_id = comment.cid)
LEFT OUTER JOIN field_data_comment_body fc
ON(comment.cid=fc.entity_id)
LEFT OUTER JOIN users
ON(users.uid = comment.uid)
#Restricting to content from 01-02-2012 up to 11-06-2012
WHERE comment.created > 1328054400
#Restricting to Comments
AND fdf.entity_type = "comment"
#Restricting to node status=1
AND comment.status=1
In Java I put:
String sql = "SELECT fdf.entity_type, node.nid, td.name, td.tid, ti.created, users.uid "
+ "FROM field_data_field_topic fdf LEFT OUTER JOIN taxonomy_term_data td " +
"ON(fdf.field_topic_tid = td.tid) " +
"LEFT OUTER JOIN taxonomy_index ti " +
"ON(fdf.field_topic_tid = ti.tid AND fdf.entity_id = ti.nid) " +
"LEFT OUTER JOIN node " +
"ON(fdf.entity_id = node.nid) " +
"LEFT OUTER JOIN field_data_body fd " +
"ON(fd.entity_id = node.nid) " +
"LEFT OUTER JOIN users " +
"ON(users.uid = node.uid " +
"WHERE node.created > 1328054400 " +
"AND fdf.entity_type = 'node' " +
"AND node.status = 1 " +
"AND node.nid not like '1594' " +
"UNION " +
"SELECT fdf.entity_type, comment.cid, td.name, td.tid, ti.created, users.uid " +
"FROM field_data_field_topic fdf LEFT OUTER JOIN taxonomy_term_data td " +
"ON(fdf.field_topic_tid = td.tid) " +
"LEFT OUTER JOIN taxonomy_index ti " +
"ON(fdf.field_topic_tid = ti.tid AND fdf.entity_id = ti.nid) " +
"LEFT OUTER JOIN comment " +
"ON(fdf.entity_id = comment.cid) " +
"LEFT OUTER JOIN field_data_comment_body fc " +
"ON(comment.cid=fc.entity_id) " +
"LEFT OUTER JOIN users " +
"ON(users.uid = comment.uid) " +
"WHERE comment.created > 1328054400 " +
"AND fdf.entity_type = 'comment' " +
"AND comment.status=1"
;
And the error I get is this:
MySQL Database connection established
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right **syntax to use near 'WHERE node.created > 1328054400 AND fdf.entity_type = "node" AND node.status = 1' at line 1**
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2683)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2144)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2310)
at pp.orientTest.Orient4GraphUsersCreatedTagsTaggedNodes.main(Orient4GraphUsersCreatedTagsTaggedNodes.java:51)
MySQL Database connection terminated
Looks to be a close bracket missing from this line:
"ON(users.uid = node.uid " +
fdf.entity_type = "node",
this should be in single quotes
like:
fdf.entity_type = 'node'