Order by date not working with distinct using native query - java

Currently I have a repository where I'm using a native query to find out the first 10 unique ids and these ids should be fetched with the recent ones first. To do this I'm using the following query in my repository class:
#Repository
public interface HomePageRepository extends JpaRepository<TransferEntity, Integer> {
#Query(value="select DISTINCT transfer_to from transfers_table where transfer_from= :transfer_from ORDER BY transaction_date DESC LIMIT 10;", nativeQuery=true)
public ArrayList<Integer> getTransferRequests(Integer transfer_from);
}
The following is my entity class I'm using:
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table(name = "transfers_table")
public class TransferEntity {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer Id;
private Integer transfer_from;
private Integer transfer_to;
private Double transaction_amount;
#Column(nullable = false, updatable = false)
#CreationTimestamp
private Date transaction_date;
}
Now this is giving me the following error when I try to run it:
java.sql.SQLException: Expression #1 of ORDER BY clause is not in SELECT list, references column 'db.transfers_table.transaction_date' which is not in SELECT list; this is incompatible with DISTINCT
This same query works when I remove the Order by clause from the statement, but then I cannot fetch the recent ids first.

use subquqries:
select DISTINCT transfer_to from (
select transfer_to, transaction_date from transfers_table where transfer_from= 6 ORDER BY transaction_date DESC LIMIT 10
) as x
Demo

Related

sqlException : column not found JPA #query

I'm using #query annotation but when I try to fetch count of records it throws
java.sql.SQLException: Column 'allowPartialPay' not found.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094) ~[mysql-connector-java-5.1.31.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:997) ~[mysql-connector-java-5.1.31.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:983) ~[mysql-connector-java-5.1.31.jar:na]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:928) ~[mysql-connector-java-5.1.31.jar:na]
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1162) ~[mysql-connector-java-5.1.31.jar:na]
at com.mysql.jdbc.ResultSetImpl.getBoolean(ResultSetImpl.java:1781) ~[mysql-connector-java-5.1.31.jar:na]
I'm writing my custom queries in repository.
InvoiceRepository.java
public interface InvoiceRepository extends JpaRepository<Invoice, Integer>{
Invoice findByInvoiceNumber(String invoiceNumber);
List<Invoice> findByUserId(int id);
#Query(value = "select c.id,c.business_name,count(i.id) from client c join invoice i on c.id = i.client_id where i.date <= :agingDate group by c.id",nativeQuery=true)
List<Invoice> findInvoiceCount(#Param("agingDate")Date agingDate);
}
ReportService.java
if(report.getReportBy().equals("invoiceCount")){
result = invoiceRepository.findInvoiceCount(report.getAgingDate());
}
Invoice.java
#Entity
#Table
public class Invoice {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private int id;
#ManyToOne
private Client client;
#Column
private boolean allowPartialPay;
}
Database
It comes during mapping result set into java Invoice class (as you declared it as return type List for method findInvoiceCount() ). native query return in your case Object[] instead of List.
You can see it in log exception
ResultSetImpl.findColumn(ResultSetImpl.java:1162
So it happens in result mapping stage ,after query has executed.
#Query(value = "select c.id,c.business_name,count(i.id) from client
c join invoice i on c.id = i.client_id
where i.date <= :agingDate group by c.id",nativeQuery=true)
List<Invoice> findInvoiceCount(#Param("agingDate")Date agingDate);
spring data gets result set from query result and tries to map it into Invoice field by field (try to contruct Invoice class ). But actual type it's Object[].
If you need get some DTO as result your query , with fields like is result set : 'c.id,c.business_name,count(i.id)' use #SqlResultSetMapping (you can map result columns from select query into your dto). Or change return type from List to Object[] and iterate it as you need.
Here is example for Result Set Mapping: The Basics.

How to convert inner native sql to JPQL

Hi Here is my entity
#Entity
#Table(name = "COMMENTS")
public class Comment {
private static final long serialVersionUID = -1606236771730211148L;
#NotNull
private Instant created_On; // immutable
#Id
#NotNull
#Column(updatable = false)
private String uuid;
#NotNull
private DomainReference domainRef; // immutable
}
Here is my table looks like.
UUID Varchar Unique id
CREATED_ON TIMESTAMP Instant
Encounter Varchar encounter
I need a query that looks up the latest N Number of rows by each encounter. So if there are 3 encounters they each can have up to N Number rows.
Here is my native sql query
SELECT a.* FROM (
SELECT COMMENTS.UUID ,COMMENTS.DOMAINREF, COMMENTS.CREATED_ON
ROW_Number() OVER(PARTITION BY COMMENTS.DOMAINREF ORDER BY COMMENTS.CREATED_ON DESC) AS rn
FROM COMMENTS WHERE COMMENTS.DOMAINREF IN ('1','2')) a
WHERE a.rn <= 1;
Here is my partially converted JPQL query.
SELECT a.UUID,a.domainRef,a.CREATED_ON FROM
( SELECT COMMENT.UUID,COMMENT.domainRef,COMMENT.CREATED_ON,
ROW_Number() OVER(PARTITION BY IAW_COMMENT.domainRef ORDER BY COMMENT.CREATED_ON DESC) AS rn
FROM COMMENT WHERE COMMENT.domainRef IN :domainrefs) a
WHERE a.rn <= :maxNum";
This query will create table called "a" which is not my entity. I'm not sure if JPA handles inner queries and returns the matching entity.
Can we convert this query into JPQL query?

create and populate pojos in jpql query and get as list

I have following entities and pojo:
#Entity
public class TableA {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
long id;
string name;
}
#Entity
public class TableB {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
long id;
double price;
#ManyToOne
#JoinColumn(name = "tableAId")
TableA tableA;
//setters & getters
}
statistics
public class Statistics {
long tableAId;
double price;
long count;
public Statistics(long tableAId, double price, long count) {
this.tableAId = tableAId;
this.price = price;
this.count = count;
}
//setters & getters
}
I want to do a jpql query to get resultlist of statistics objects which is populated with reference id to tableA object and sum of price columns and count of rows in TableB table.
I've tried with following code without success:
Query query = em.createQuery("SELECT NEW se.exampel.Statistics"
+ "(b.tableAId, sum(price) ,count(b)) from TableB b ");
List<Statistics> statistics = query.getResultList();
Exception
java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: tableAId
of: se.exampel.TableB [SELECT NEW se.exampel.Statistics(b.tableAId,count(b), sum(price))
from se.exampel.TableB b ]
What am i doing wrong?
now it's fixed:
"select new se.exampel.Statistic(s.id, sum(p.price),count(p)) from tabelB p JOIN p.tabelA s GROUP BY s"
You are mixing SQL concepts into JPQL. The query needs to me made on Entity TableB, and so can only use mapped attributes within the TableB java class. So you will need to use something like:
"SELECT NEW se.exampel.Statistics(b.tableA.id, sum(b.price) ,count(b)) from TableB b "
Note that Hibernate is likely to do an inner join from tableB to tableA to get A's ID. If you want to be able to access the foreign key field in TableB directly in a JPA neutral way, you may need to add a read-only field in the TableB class for it. Something like
#Column(name="tableA_ID", insertable=false, updatable=false);
long tableAId;
which then allows you to access b.tableAId in queries:
"SELECT NEW se.exampel.Statistics(b.tableAId, sum(b.price) ,count(b)) from TableB b "
and should avoid the table join.
query should contain b.tableA which is property name instead of column name tableAId
Update: with reference to comment from #Chris query should be
SELECT NEW se.exampel.Statistics(b.tableA.id,sum(b.price),count(b)) from TableB b

Native Query (JPA ) not reset and return the same old result

I have a native sql query as the following :
for (init i=0; i<=2 ; i++) {
String sql = "Select * from accounts where id = ?";
Query query = em.createNativeQuery(sql,AccountBean.class);
query.setParameter(1, i );
AccountBean accountBean = (AccountBean)query.getSingleResult();
}
For the first loop it works correctly but any loop after the first one returns the same result as the first one , i debug it, the parameter changed , it works correctly if i change
Query query = em.createNativeQuery(sql,AccountBean.class);
to
Query query = em.createNativeQuery(queryString);
Regards
Wish79
Every JPA entity must have a primary key. Your JPA entities may not properly reflect the primary key, if any, on the database table.
I ran into the same problem. In my model class I had only one class variable annotated with #Id. However, that was not an accurate reflection of the table itself, which has a composite primary key. Thus, my query results returned the correct number of rows, but each confoundingly contained the same values, even though the actual data was different in the db. For example, this query:
Query query = entityManager.createQuery
("SELECT tbl FROM Tbl tbl WHERE tbl.id = 100
and tbl.code in ('A','B','C')");
...returned 10 rows, each showing a code of 'A'. But in actuality 9 of those 10 rows had a different code value ('B' or 'C'). It seemed as if the results were being cached and/or the tbl.code predicate was ignored. (That happened whether I used JPQL or Native SQL.) Very confusing.
To fix this I added an additional #Id annotation to my model to reflect the composite primary key:
#Id
#Column(name = "Code")
public String getCode() {
return this.code;
}
Now the query returns the data correctly and the code select criteria is no longer effectively ignored.
Edit: Although the above worked for me, on further research it seems a better approach to configure a separate JPA Entity composite primary key class. See http://docs.oracle.com/cd/E16439_01/doc.1013/e13981/cmp30cfg001.htm.
For example, here's an Entity class with an embedded primary key (see #EmbeddedId):
/**
* The persistent class for the SOME_TABLE database table.
*/
#Entity
#Table(name = "SOME_TABLE")
public class SomeTable implements Serializable {
#EmbeddedId
private SomeTablePk id;
#Column(name = "NUMBER_HRS")
private BigDecimal numberHrs;
...
...and here's the composite primary key class (see #Embeddable):
#Embeddable
public class SomeTablePk implements Serializable {
#Column(name = "SOME_ID")
private String someId;
#Column(name = "ANOTHER_ID")
private BigDecimal anotherId;
public String getSomeId() {
return someId;
}
...

Hibernate query composite key

I'm trying to perform a composite key query using #embeddable.
Here's what I have thus far.
#Embeddable
public class IfasvVendorPK implements Serializable{
#Column(length = 4, nullable = false)
protected String peId;
#Column(length = 8, nullable = false)
protected String peAddrCd;
Entity
#Entity
public class IfasvVendor implements Serializable {
#EmbeddedId
private IfasvVendorPK ifasvVendorPK;
Query
List contains two pks. Not sure if I should be using a list for this.
Query query = session.createQuery("from IfasvVendor t0 where t0.ifasvVendorPK.peId=:id");
query.setParameter("id", list);
query.list();
I also wasn't sure how to get the object once I get the query working.
I believe that the following should work:
Query query = session.createQuery("from IfasvVendor t0 where t0.ifasvVendorPK.peId in (:id)");
query.setParameterList("id", list);
query.list();
You must enclose the named parameter in parenthesis in your query and use setParameterList. See the javadoc for setParameterList here.
The query results will be in the list returned by: query.list(). This returns an unchecked list which you may want to cast to List<IfasvVendor>.
btw. this is not a composite key query. see #Perception comment...

Categories

Resources