How to translate from native sql to querydsl expression right? - java

Given the following native SQL query:
#Query(
value =
"SELECT "
+ "jp.BLABSTATUSID BlabStatus, "
+ "s.BLABSTATUSBEZ BlabStatusBez, "
+ "COUNT(*) sumvalue "
+ "FROM JP jp "
+ " LEFT JOIN BLAB_STATUS s "
+ " ON jp.BLABSTATUSID = s.BLABSTATUSID "
+ "GROUP BY jp.BLABSTATUSID, s.BLABSTATUSBEZ",
nativeQuery = true)
that I use in my Java / spring context, I have to switch to querydsl.
I tried:
final QJpEntity e = jpEntity;
final QBlabStatusEntity f = blabStatusEntity;
return jpaQueryFactory
.from(e)
.leftJoin(e.blabStatus, blabStatusEntity)
.on(blabStatusEntity.blabstatusid)
.groupBy(e.blabStatus.blabstatusid, f.blabstatusbez)
.select(
Projections.constructor(
JPStatisticCounter.class,
e.blabStatus,
f.blabstatusbez,
e.count()))
.fetch();
but it cannot compile because it seems syntactically wrong.
Any ideas?

solved, it was a constructor type mismatch

Related

Bind #param in a Jpa repository native query inside single quotations

I am looking for a way to bind a given param in a native query where the value has to be inside single quotations, like so:
#Transactional(readOnly = true)
#Query(value = " SELECT c.ID " +
" FROM table1 clh " +
" LEFT JOIN table2 nks " +
" on clh.SERIAL = nks.SERIAL_REF " +
" WHERE clh.CREATED_DATE >= :now - interval ':timeThreshold' HOUR " +
" AND nks.SERIAL_REF IS NULL" , nativeQuery = true)
List<Long> getIdsWithoutAnswer (#Param("timeThreshold") Integer timeThreshold, #Param("now") LocalDateTime now);
However, when I try to run this, it results in hibernate not being able to bind the timeThreshold value as it is provided inside the single quotations ''.
Does anyone know how this can be resolved?
The problem you are having with your native Oracle query has to do with trying to bind a value to an interval literal. You can't do that. Instead, use the NUMTODSINTERVAL() function:
#Transactional(readOnly = true)
#Query(value = " SELECT c.ID " +
" FROM table1 clh " +
" LEFT JOIN table2 nks " +
" on clh.SERIAL = nks.SERIAL_REF " +
" WHERE clh.CREATED_DATE >= :now - numtodsinterval(:timeThreshold, 'hour') " +
" AND nks.SERIAL_REF IS NULL" , nativeQuery = true)
List<Long> getIdsWithoutAnswer (#Param("timeThreshold") Integer timeThreshold, #Param("now") LocalDateTime now);

Spring Boot Mybatis Dynamic query

Hello im pretty new to mybatis and is the first time im trying to use with annotations in spring boot.
My code is something like this :
#Select("<script>"
+ "SELECT t.something, s.somewhat, "
+ "FROM t.table1 t "
+ "LEFT JOIN table2 s ON t.id = s.id "
+ "WHERE s.delete_date IS NULL "
+ "<if test=\"isnew\"> "
+ "AND t.insert_date = t.update_date "
+ "AND (t.score >= s.min_score AND t.score <= s.max_score) "
+ "</if>"
+ "union "
+ "ANOTHER SIMILAR QUERY WITH ANOTHER <IF> + "</script>")
List<Map<String, Object>> methodName(#Param("isnew") Boolean isNew);
This is the error.
Caused by: java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Could not find value method on SQL annotation. Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 822;
Im almost sure there is an error of syntax very predictable but I cant find it.
Here are some examples of what I tried, none of them works:
"<if test="isnew = true">"
"<if test="isnew == true">"
"<if test="isnew != false">"
"<if test="isnew"> "
"<if test=#{isnew}"> "
"<if #{isnew} = true> "
Thanks in advance
For those who may have the same problem this is the solution:
You have to escape the character < , because mybatis takes it as an unopened tag, &lt will work :
+ "SELECT t.something, s.somewhat, "
+ "FROM t.table1 t "
+ "LEFT JOIN table2 s ON t.id = s.id "
+ "WHERE s.delete_date IS NULL "
+ "<if test=\"isnew\"> "
+ "AND t.insert_date = t.update_date "
+ "AND (t.score >= s.min_score AND t.score lt;= s.max_score) "
+ "</if>"
+ "union "
+ "ANOTHER SIMILAR QUERY WITH ANOTHER <IF> + "</script>")
List<Map<String, Object>> methodName(#Param("isnew") Boolean isNew);```

Implement JPA Projection with count

I want to implement JPA Projection with count. I tried this:
#Query(value = "SELECT new org.service.PaymentTransactionsDeclineReasonsDTO( id, count(id) as count, status, error_class, error_message) " +
" FROM payment_transactions " +
" WHERE terminal_id = :id AND (created_at > :created_at) " +
" AND (status != 'approved') " +
" GROUP BY error_message " +
" ORDER BY count DESC", nativeQuery = true)
List<PaymentTransactionsDeclineReasonsDTO> transaction_decline_reasons(#Param("id") Integer transaction_unique_id, #Param("created_at") LocalDateTime created_at);
But I get error: Caused by: java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.plugin.service.PaymentTransactionsDeclineReasonsDTO( id, count(id) as c' at line 1
How I can implement proper count when I have class based Projection?
Try Interface-based Projection instead of DTO:
public interface TransactionDeclineReason {
Integer getId();
Long getCount();
Status getStatus();
ErrorClass getErrorClass(); // I suppose it's enum...
String getErrorMessage();
}
#Query(value = "select " +
"id as id, " +
"count(id) as count, " +
"status as status, " +
"error_class as errorClass, " +
"error_message as errorMessage " +
"from " +
"payment_transactions " +
"where " +
"terminal_id = ?1 " +
"and created_at > ?2 " +
"and status != 'approved' " +
"group " +
"by error_message " +
"order by " +
"2 desc", nativeQuery = true)
List<TransactionDeclineReason> getTransactionDeclineReasons(Integer transactionId, LocalDateTime createdAt);
Pay attention on aliases (i.e. id as id) - they are mandatory.
You are mixing JPQL and SQL syntax.
The constructor expression (new ...) is JPQL, but in the annotation you mark it as a nativeQuery i.e. as SQL so you have to make up your mind.
If it is to be SQL I don't think you can use aliases in the ORDER BY clause, so you might have to either repeat the expression or wrap it in a subselect as described here: Using an Alias in a WHERE clause.
If it is to be JPQL it doesn't support aliases in a constructor expression, so I guess you have to repeat the expression in the order by clause.

EBean inner join on the same table

I need to execute an inner join on the same table. Below is the raw query I am currently executing.
String tagValueRowsSQL = "SELECT itv1.ItemTagValueID,itv1.FkItemID," +
"itv1.FkTagID,itv1.TagIndex,itv1.ValueIndex,itv1.Value,itv1.LastUpdateDateTime" +
" FROM tag.ItemTagValue itv1" +
" INNER JOIN tag.ItemTagValue itv2" +
" on itv1.fkTagID=" + tagIDsAndValues.get(LOCATION_STORE_CONFIG_TAG_NAME).getTagID() +
" and itv1.Value=" + storeId +
" and itv2.fkTagID = " + tagIDsAndValues.get(SENSOR_TYPE_TAG_NAME).getTagID() +
" and itv2.Value=" + sensorType;
RawSql rawSqlForSensorsInStoreAndOfType = RawSqlBuilder.parse(tagValueRowsSQL)
.columnMapping("itv1.ItemTagValueID", "ItemTagValueID")
.columnMapping("itv1.FkItemID", "FkItemID")
.columnMapping("itv1.FkTagID", "FkTagID")
.columnMapping("itv1.TagIndex", "TagIndex")
.columnMapping("itv1.ValueIndex", "ValueIndex")
.columnMapping("itv1.Value", "Value")
.columnMapping("itv1.LastUpdateDateTime", "LastUpdateDateTime")
.create();
Query<ItemTagValueModel> query = Ebean.find(ItemTagValueModel.class);
List<ItemTagValueModel> sensorsTagValueData = query.setRawSql(rawSqlForSensorsInStoreAndOfType).findList();
Executing the above using RawSQL seems pretty clumsy. How can I execute the above without using RawSQL? I checked this question Ebeans where columnA equals columnB in same table but I'm not sure how to apply that answer to my situation. Any help would be much appreciated.

Order By in #Query select not working

I have this Query in my JPA repository - and it works EXCEPT the " order by " part. Am i doing this wrong ? is it different in hql ?
#Query(value = "select wm.WagerIdentification, wm.BoardNumber, wm.MarkSequenceNumber, wm.MarkNumber," +
" pt.CouponTypeIdentification, pt.WagerBoardQuickPickMarksBoard " +
"from WagerBoard wb " +
"inner join wb.listOfWagerMarks wm " +
"inner join wb.poolgameTransaction pt " +
"where wb.WagerIdentification = wm.WagerIdentification and wb.BoardNumber = wm.BoardNumber and wb.GameIdentification = wm.GameIdentification and wm.meta_IsCurrent = 1 " +
"and wb.TransactionIdentification = pt.TransactionIdentification and pt.meta_IsCurrent = 1 " +
"and wb.meta_IsCurrent = 1 order by wm.WagerIdentification asc, wm.BoardNumber asc, wm.MarkNumber asc")
Instead of ordering result within the #Query, you can add a method parameter of type Sort, like in Spring Data JPA reference

Categories

Resources