Spring Boot Mybatis Dynamic query - java

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);```

Related

Column missing in Spring's namedParameterJdbcTemplate query when using UNION ALL

Fairly normal looking query, two basically identical selects, but in the second one the RVC table is omitted, and NULLS are used. Query works fine in the console, and column headers come from the first select in the join. Fully specifying the JDBC column names for the RV.* and RVC.* did not help, nor did putting single or double quotes around aliases in the second select i.e. Null as 'RVC.GUID' for instance.
The method
public int findColumn(String columnName, boolean
useColumnNamesInFindColumn, int indexBase) {
is being invoked and what is coming in is not RV.ID, but null.ID for the column name.
#Override
public List<ReferenceVariety> getAll() {
List<ReferenceVariety> chemicals;
MapSqlParameterSource namedParameters = new MapSqlParameterSource()
.addValue("maxCropId", maxCropId);
chemicals = namedParameterJdbcTemplate.query(
REFERENCE_VARIETIES_ALL_SQL,
namedParameters,
referenceVarietyRowMapper);
return chemicals;
}
public static final String REFERENCE_VARIETIES_ALL_SQL = "( SELECT RV.*, RVC.*, "
+ "PM.ID as PM_ID, PM.LAST_UPDATE_TIMESTAMP as PM_LAST_UPDATE_TIMESTAMP, "
+ "PM.GUID as PM_GUID, PM.ORGANIZATION_ID as PM_ORGANIZATION_ID, "
+ "PM.NAME as PM_NAME, PM.PRODUCT_SOURCE_TYPE, PM.PRODUCT_SOURCE_ID "
+ "FROM REFERENCE_VARIETY RV "
+ "LEFT JOIN PRODUCT_MANUFACTURER PM ON RV.MANUFACTURER_GUID = PM.GUID "
+ "LEFT JOIN REFERENCE_VARIETY_COUNTRY RVC ON RV.GUID = RVC.REFERENCE_VARIETY_GUID "
+ "WHERE SOURCE_SYSTEM IN (2, 3) "
+ "AND CROP_TYPE <= :maxCropId "
+ ") UNION ALL ("
+ "SELECT RV.*, "
+ "Null as GUID, "
+ "Null as SOURCE_SYSTEM_PRODUCT_ID, "
+ "Null as RETIRED_TIMESTAMP, "
+ "Null as REFERENCE_VARIETY_GUID, "
+ "Null as COUNTRY_CODE, "
+ "Null as CREATION_TIMESTAMP, "
+ "Null as LAST_UPDATE_TIMESTAMP, "
+ "Null as ID, "
+ " PM.ID as PM_ID, PM.LAST_UPDATE_TIMESTAMP as PM_LAST_UPDATE_TIMESTAMP, "
+ " PM.GUID as PM_GUID, PM.ORGANIZATION_ID as PM_ORGANIZATION_ID, "
+ " PM.NAME as PM_NAME, PM.PRODUCT_SOURCE_TYPE, PM.PRODUCT_SOURCE_ID "
+ "FROM REFERENCE_VARIETY RV "
+ "LEFT JOIN PRODUCT_MANUFACTURER PM ON RV.MANUFACTURER_GUID = PM.GUID "
+ "WHERE SOURCE_SYSTEM IN (2, 3) "
+ "AND CROP_TYPE <= :maxCropId )";
Root cause:
Caused by: java.sql.SQLException: Column 'RV.ID' not found.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.result.ResultSetImpl.findColumn(ResultSetImpl.java:584)
at com.mysql.cj.jdbc.result.ResultSetImpl.getLong(ResultSetImpl.java:862)
at com.deere.isg.products.common.repositories.referencevarieties.ReferenceVarietyRowMapper.mapRow(ReferenceVarietyRowMapper.java:23)
at com.deere.isg.products.common.repositories.referencevarieties.ReferenceVarietyRowMapper.mapRow(ReferenceVarietyRowMapper.java:18)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:723)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651)
... 78 more
Do unions not work here? Am I doing something wrong? Either half of the union select seems to work fine by itself. For now I am issuing two queries and combining the result sets by appending the objects the row mapper generates in a collection, but I would prefer one select statement.

What's the source of this HQL query error?

public List<UserDto> getTopUsersForDaysRankedByNumberOfQuestions(Integer daysCount, Integer usersCount) {
return entityManager.createQuery(
"select new com.javamentor.qa.platform.models.dto.UserDto(" +
"user.id, " +
"user.email, " +
"user.fullName, " +
"user.imageLink, " +
"user.city, " +
"(select sum(case when rep.count is null then 0 else rep.count end) " +
"from Reputation as rep where rep.author.id = user.id)), " +
"sum(case when vote.vote = 'UP_VOTE' then 1 when vote.vote = 'DOWN_VOTE' then - 1 else 0 end) as sumVotes, " +
"count(distinct answer.id) as answerCount " +
"from User as user " +
"inner join Answer as answer on answer.id = user.id " +
"left join VoteAnswer as vote on answer.id = vote.id " +
"where answer.persistDateTime > :date " +
"and answer.isDeleted = false " +
"and user.isDeleted = false " +
"group by user.id " +
"order by answerCount desc,sumVotes desc,user.id", UserDto.class)
.setParameter("date", LocalDateTime.now().minusDays(daysCount))
.setMaxResults(usersCount)
.getResultList();
}
So I have this method which should return List of UserDto but I'm getting the erorrs. Tried to fix this whole day but I still don't understand the source of these errors
o.h.hql.internal.ast.ErrorTracker : line 1:299: unexpected token: ,
o.h.hql.internal.ast.ErrorTracker : line 1:299: unexpected token: ,
o.h.hql.internal.ast.ErrorTracker : line 1:392: expecting EOF, found ')'
o.h.hql.internal.ast.ErrorTracker : line 1:392: expecting EOF, found ')'
Is this somehow syntax related or I'm doing something completely wrong?
Try doing a simple select dto from user, and if that works add the rest of the query sentence by sentence until you find the one that throws the error.

WITH Recursive query is not working when run using entityManager native query

I'm running this PostgreSQL query on Java and it is throwing an error "ERROR: syntax error at or near ":".
But the query is working on Postgresql when I run directly.
I'm thinking Array[]::integer[] is causing the issue. Can someone has any idea?
String query = "WITH RECURSIVE tree AS ( SELECT id, ARRAY[]::integer[] AS ancestors \n" +
" FROM regions \n" +
" WHERE parent_id IS NULL\n" +
" UNION ALL \n" +
" SELECT soato.id, tree.ancestors || regions.parent_id \n" +
" FROM regions, tree \n" +
" WHERE regions.parent_id = tree.id \n" +
") \n" +
" SELECT d.id FROM department d \n" +
" WHERE d.region_id IN (select id from tree where 1703 = ANY(tree.ancestors))";
Query q = entityManager.createNativeQuery(query);
q.getResultList();
Use an explicit cast to avoid the implicit PostgreSQL option :: for casting.
ARRAY[CAST(NULL AS INTEGER)] AS ancestors

Map a result of an SQL to a field using Hibernate

I am looking for a way of mapping an SQL result of type bool to a field of an entity.
Here's the code I need to work with:
#Formula("next_erds_id is null \n" +
"and exists(\n" +
" select * from processes p\n" +
" where p.message_uuid = message_uuid \n" +
" and exists(select * from process_tasks t\n" +
" where t.process_uuid = p.process_uuid and t.task_name = 'MP_MESSAGE_PROCESSED')\n" +
" and not exists(select * from process_tasks t\n" +
" where t.process_uuid = p.process_uuid and t.task_name = 'CH_NOTIFICATION_CREATED') \n" +
")")
private boolean canNotifyOnStartDeliveryAfter;
(Please ignore the field name. I've got no idea what it is supposed to mean...)
Of course, it does not work because it's not a valid MSSQL syntax.
Any idea how to fix it?

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