missing keyword error for jpa native query - spring-data-jpa

#Query(value = "SELECT * FROM wiz_deals INNER JOIN wiz_preferences p ON 1 = 1 INNER JOIN wiz_publish_invoice ON wiz_deals.invoice_id = wiz_publish_invoice.invoice_id WHERE wiz_deals.total_inv_remain_amt BETWEEN p.INV_AMT_MIN=?INV_AMT_MIN AND p.INV_AMT_MAX=?INV_AMT_MAX AND wiz_deals.credit_period BETWEEN p.TENURE_MIN=?TENURE_MIN AND p.TENURE_MAX=?TENURE_MAX ",nativeQuery=true)
public List<Deals> findByPrefrenceSorting(#Param("INV_AMT_MIN") int INV_AMT_MIN,#Param("INV_AMT_MAX") int INV_AMT_MAX,#Param("TENURE_MIN") int TENURE_MIN,#Param("TENURE_MAX") int TENURE_MAX);

Try this one, I just modified some thing
#Query(value = "SELECT * FROM Deals wiz_deals INNER JOIN wiz_preferences p
ON 1 = 1 INNER JOIN wiz_publish_invoice ON wiz_deals.invoice_id
=wiz_publish_invoice.invoice_id WHERE wiz_deals.total_inv_remain_amt
BETWEEN :INV_AMT_MIN AND :INV_AMT_MAX AND wiz_deals.credit_period BETWEEN
:TENURE_MIN AND :TENURE_MAX ",nativeQuery=true)
public List<Deals>findByPrefrenceSorting(#Param("INV_AMT_MIN") int INV_AMT_MIN,#Param("INV_AMT_MAX") int INV_AMT_MAX,#Param("TENURE_MIN") int TENURE_MIN,#Param("TENURE_MAX") int TENURE_MAX);

Related

JPA Native Query across multiple tables

I have the following defined as a native query in a repository (dispenseRepository) :
#Query(
value = "SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d "
+ " where p.patient_id=c.patient_id "
+ " and c.consult_id = d.consult_id "
+ " and c.fk_script_id =s.script_id"
+ " and c.consult_id=?1 ",
nativeQuery = true
)
List<Dispense> findInvoiceByConsultId(Long consultId);
The Rest Controller has :
#RequestMapping(value = "/api/invoice/{consultId}",method = {RequestMethod.GET})
public List<Dispense> invoice(#PathVariable(value="consultId")Long consultId){
return dispenseRepository.findInvoiceByConsultId(consultId);
}
When I hit the api I only get dispense details:
[
{
"dispenseId": 1,
"icd10": "J.10",
"tariffCode": "10010",
"dispenseItem": "Lenses",
"price": 400.0
},
{
"dispenseId": 3,
"icd10": "J.10",
"tariffCode": "111000",
"dispenseItem": "Other",
"price": 1500.0
},
{
"dispenseId": 4,
"icd10": "K.100",
"tariffCode": "10010",
"dispenseItem": "Eye Test",
"price": 550.0
}
]
I'd like all the data as per query which will be used for Jasper report
patient-consult 1-M
consult-script 1-1
consult-dispense 1-M
Since in your query you return all fields from all tables: SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d creating projections/DTOs for so many objects and fields is very cumbersome. There are 2 ways to proceed. Either specify exactly the fields you want from each table in your query and create a DTO to hold those fields.
e.g.
Approach 1:
I chose only one field from each table to make it as example. Please not that you have to convert your query from native to jpa one!
#Query("SELECT new com.example.demo.ResultDTO(p.patientName, c.reservationNumber, s.addition, d.dispenseItem) from Patient p, Consult c, Script s, Dispense d ...")
List<ResultDTO> findInvoiceByConsultId(Long consultId);
and ResultDTO class can be:
package com.example.demo;
public class ResultDTO {
private String patientName;
private String reservationNumber;
private String addition;
private String dispenseItem;
public ResultDTO(String patientName, String reservationNumber, String addition, String dispenseItem) {
this.patientName = patientName;
this.reservationNumber = reservationNumber;
this.addition = addition;
this.dispenseItem = dispenseItem;
}
public String getPatientName() {
return patientName;
}
public void setPatientName(String patientName) {
this.patientName = patientName;
}
public String getReservationNumber() {
return reservationNumber;
}
public void setReservationNumber(String reservationNumber) {
this.reservationNumber = reservationNumber;
}
public String getAddition() {
return addition;
}
public void setAddition(String addition) {
this.addition = addition;
}
public String getDispenseItem() {
return dispenseItem;
}
public void setDispenseItem(String dispenseItem) {
this.dispenseItem = dispenseItem;
}
}
UPDATE
Approach 1 won't work with a nativeQuery, you have to convert it to jpa one so unless you convert your query to jpql, the above code wont work.
OR the much easier but bulkier, keep the query as is and place the result on a List of Maps.
Approach 2:
#Query(
value = "SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d "
+ " where p.patient_id=c.patient_id "
+ " and c.consult_id = d.consult_id "
+ " and c.fk_script_id =s.script_id"
+ " and c.consult_id=?1 ",
nativeQuery = true
)
List<Map<String, Object>> findInvoiceByConsultId(Long consultId);

Executing Raw sql with Entity Framework Core

The below I can have a condition to execute view/table, which would load into AccountDataModel class.
dbcontext.AccountDataModel.FromSql($"select * from account where id=123").FirstOrDefault();
How can I retrieve without using a class model, if I want to retrieve just 1 or 2 columns
example: select name from account where id=123
Do I always need a class model?
ADO.NET works in EFCore =)
using Microsoft.EntityFrameworkCore;
using System.Data.Common;
using System.Data.SqlClient;
using System;
public void ExampleMethod(DbContext context)
{
SomeObjectResult result = null;
DbCommand cmd = context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = "Select C.ID, C.CarModelID as ModelID, C.VIN, C.RegNumber,cast(C.CountValue as int) as Course,A.BrandID from A inner join C on A.ID = C.KeyID Where A.ID = #appID";
cmd.Parameters.Add(new SqlParameter("#appID", appointmentID));
if (cmd.Connection.State != ConnectionState.Open)
{
cmd.Connection.Open();
}
using (var reader = await cmd.ExecuteReaderAsync())
{
if (reader.Read())
{
result = new SomeObjectResult()
{
BrandID = (int)reader["BrandID"],
Course = (int)reader["Course"],
ID = (int)reader["ID"],
ModelID = (int?)reader["ModelID"],
RegNumber = (string)reader["RegNumber"],
VIN = (string)reader["VIN"]
};
}
}
}
Yes. like this :
var account = dbcontext.AccountDataModel.FromSql(#"select a.id, a.name from account a where a.id=123");
source : FromSql for non entity type
This queries the database
var name = dbcontext.GetDBConnection().Query("select name from account where id=123").FirstOrDefault();

How to check if table exists in a migration?

This is as close as I've got...
public static class Helpers
{
public static bool TableExists(this MigrationBuilder builder, string tableName)
{
bool exists = builder.Sql($#"SELECT 1 FROM sys.tables AS T
INNER JOIN sys.schemas AS S ON T.schema_id = S.schema_id
WHERE S.Name = 'SchemaName' AND T.Name = '{tableName}'");
return exists;
}
}
But how does one get a result form the SQL call?
Here is one solution...
public override void Up()
{
if (!Exists("dbo.MyTable"))
{
... do something
}
}
private static bool Exists(string tableName)
{
using (var context = new DbContext(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
var count = context.Database.SqlQuery<int>("SELECT COUNT(OBJECT_ID(#p0, 'U'))", tableName);
return count.Any() && count.First() > 0;
}
}
This query runs immediately rather than being defered like other DbMigration commands are - but that's why it works. The result is known straight away so that other commands can be queued (or not queued) as required.
It's not a perfect solution, but you could use an IF in SQL:
builder.Sql(#"
IF (EXISTS(SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'MySchema'
AND TABLE_NAME = 'TableName'))
BEGIN
--DO SOMETHING
END
");

How to access JPQL query return value (List)

This is my method
public void makeDeposit(String WristID, double deposit) {
List resultList = em.createQuery(
"SELECT c FROM Tbleaccountcb005916 c WHERE c.wristid LIKE :wId")
.setParameter("wId", WristID)
.setMaxResults(1)
.getResultList();
int aNo = (int) resultList.get(0);
Tbleaccountcb005916 makeDeposit = em.find(Tbleaccountcb005916.class, aNo);
double balance = makeDeposit.getBalance();
double Mdeposit = balance + deposit;
makeDeposit.setBalance(Mdeposit);
em.persist(makeDeposit);
}
I would like to access resultList value. This image show the resultList values (debugged)
I need to access resultList value (accountno = value = 2) and use it.
I tried this but it's not working:
int aNo = (int) resultList.get(0);
The query you've used returns a list of Tbleaccountcb005916 since you're returning cin the query statement.
List resultList = em.createQuery(
"SELECT c FROM Tbleaccountcb005916 c WHERE c.wristid LIKE :wId")
.setParameter("wId", WristID)
.setMaxResults(1)
.getResultList();
You can return c.accountno instead or cast the resultList items to Tbleaccountcb005916and access it's value.
Thanks to #Samuel Kok I found an answer for this. I just change the query to "c.accountno"
#Override
public void makeDeposit(String WristID, double deposit) {
List resultList;
resultList = em.createQuery(
"SELECT c.accountno FROM Tbleaccountcb005916 c WHERE c.wristid LIKE :wId")
.setParameter("wId", WristID)
.setMaxResults(1)
.getResultList();
int aNo = (int) resultList.get(0);
Tbleaccountcb005916 makeDeposit = em.find(Tbleaccountcb005916.class, aNo);
double balance = makeDeposit.getBalance();
double Mdeposit = balance + deposit;
makeDeposit.setBalance(Mdeposit);
em.persist(makeDeposit);
}
Screen Shot of debugger
enter image description here

Why I can’t find any benefit of caching LINQ to Entity query?

Please look at my sourcecode.
public class EntityQuery
{
public static Func<AdventureWork2008Container, IQueryable<SalesPerson>> selectQuery = CompiledQuery.Compile
(
(AdventureWork2008Container aw) =>
(
from s in aw.SalesPerson
join e in aw.Employee on s.BusinessEntityID equals e.BusinessEntityID
join p in aw.Person on s.BusinessEntityID equals p.BusinessEntityID
join bea in aw.BusinessEntityAddress on s.BusinessEntityID equals bea.BusinessEntityID
join a in aw.Address on bea.AddressID equals a.AddressID
join sp in aw.StateProvince on a.StateProvince equals sp
select s
)
);
public decimal Select(AdventureWork2008Container aw)
{
SalesPerson result = selectQuery(aw).First();
return result.SalesYTD;
}
public decimal Select2(AdventureWork2008Container aw)
{
SalesPerson result =
(
from s in aw.SalesPerson
join e in aw.Employee on s.BusinessEntityID equals e.BusinessEntityID
join p in aw.Person on s.BusinessEntityID equals p.BusinessEntityID
join bea in aw.BusinessEntityAddress on s.BusinessEntityID equals bea.BusinessEntityID
join a in aw.Address on bea.AddressID equals a.AddressID
join sp in aw.StateProvince on a.StateProvince equals sp
select s
).First();
return result.SalesYTD;
}
}
I try to call Select method about 1000 times and call Select2 method about 1000 times. But the result shows me that Select2 method is a bit faster than Select method about 0.005 s.(0.052/0.057 s.) Moreover, this capture doesn't include time for creating EntityQuery object.
What's wrong with my source code?
PS. the following code show how to call methods.
private void button1_Click(object sender, EventArgs e)
{
using (AdventureWork2008Container aw = new AdventureWork2008Container())
{
EntityQuery eq = new EntityQuery();
eq.Select(aw);
long lastTime = DateTime.Now.Ticks;
for (int i = 0; i < 1000; i++)
{
eq.Select(aw);
}
listBox1.Items.Add("Select 1 : " + ShowTime(lastTime));
}
GC.Collect();
}
private void button2_Click(object sender, EventArgs e)
{
using (AdventureWork2008Container aw = new AdventureWork2008Container())
{
EntityQuery eq = new EntityQuery();
eq.Select2(aw);
long lastTime = DateTime.Now.Ticks;
for (int i = 0; i < 1000; i++)
{
eq.Select2(aw);
}
listBox1.Items.Add("Select 2 : " + ShowTime(lastTime));
}
GC.Collect();
}
In Select2() generated code is
SELECT TOP 1 * FROM ...
In Select() aggregating is done on top of request. Don't know for sure, but it could lead to .Compile() results being discarded.
Try to move .First() into the compiled query.
public static Func<AdventureWork2008Container, SalesPerson> selectQuery = CompiledQuery.Compile
(
(AdventureWork2008Container aw) =>
(
from s in aw.SalesPerson
join e in aw.Employee on s.BusinessEntityID equals e.BusinessEntityID
join p in aw.Person on s.BusinessEntityID equals p.BusinessEntityID
join bea in aw.BusinessEntityAddress on s.BusinessEntityID equals bea.BusinessEntityID
join a in aw.Address on bea.AddressID equals a.AddressID
join sp in aw.StateProvince on a.StateProvince equals sp
select s
).First();
);
Hope this will help.