How to compare dates with less than operator in mybatis XML in <if test = " "> block - mybatis

<if test= "birthdate lt '20-10-2000'">
it works but is there a better way which mybatis documentation approves?

Related

parameters in sql fragment substitute error

I write a sql fragment, like this:
<sql id="day">
<choose>
<when test="${property} == 'day'">
substring(datachange_createtime, 1, 10)
</when>
<otherwise>
${property}
</otherwise>
</choose>
</sql>
and include this sql like this:
select * from my_table
<if test="groupBy != null">
group by
<foreach collection="groupBy" item="groupByAttr" separator=",">
<include refid="day">
<property name="property" value="groupByAttr"/>
</include>
</foreach>
</if>
But I got an error, mybatis didn't substitute property with a real parameter, but with groupByAttr. The result sql is like:
select * from my_table group by groupByAttr
In the otherwise clause, if I replace ${property} with #{${property}}, The result sql becomes:
select * from my_table group by ?
It is indeed correct, but for some reasons, I don't want a prepared sql.
I think the problem is the behavior of substitution in test and otherwise clauses is different.
Is the a bug, or just some mistakes I took? How to solve this problem?
Short answer:
You need to change the <include /> as follows.
<sql id="day">
<choose>
<when test="${property} == 'day'">
substring(datachange_createtime, 1, 10)
</when>
<otherwise>
\\${${property}}
</otherwise>
</choose>
</sql>
Long answer:
With your original code, the statement will look as follows after the <include /> substitution.
select * from my_table
<if test="groupBy != null">
group by
<foreach collection="groupBy" item="groupByAttr" separator=",">
<choose>
<when test="groupByAttr == 'day'">
substring(datachange_createtime, 1, 10)
</when>
<otherwise>
groupByAttr
</otherwise>
</choose>
</foreach>
</if>
As you can see, <when /> is OK, but <otherwise /> is not.
<otherwise /> should look like this:
<otherwise>
${groupByAttr}
</otherwise>
In the expression in the short answer \\${${property}}, the first two backslashes is the escape syntax which avoids the outer ${} from being treated as a variable.
Note that #{groupByAttr} does not work here because, in java.sql.PreparedStatement, a placeholder ? is not allowed for a table/column name.
Please see the wiki page for the details.

Mybatis When test condition with Internal query

I am looking for a query where i can use either internal query returned value or direct SQL in when test= in Mybatis.
<foreach item="ID"
index="index"
collection="selectionIds"
separator=";">
UPDATE TABLE_1 SET
ACT_IND ='N', upd_by = 1234
WHERE SLCT_ID = #{ID}
AND rem= select REM from TABLE_1 where SLCT_ID=#{ID}
<choose>
<when test="rem == 3">
AND Bbsid=#{nsid}
</when>
<otherwise>
AND asid=#{asid}
</otherwise>
</choose>
</foreach>
From the above query, how can i get the rem value and use in when condition.
Thanks

Collection size in mybatis query

I have a MyBatis query that looks like this:
<if test="userIdList != null and userIdList > 0">
AND galleries.id IN (
SELECT gallery_id
FROM gallery_users
WHERE gallery_id IN (
<foreach collection="userIdList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
)
GROUP BY gallery_id HAVING COUNT(gallery_id) = ???
)
</if>
That part I'm stuck on is getting the collection size which will be dynamic. So how can I get the collection size so that I can properly fill in the '???' value?
You can invoke the Collection#size() method using OGNL expression. i.e.
GROUP BY gallery_id HAVING COUNT(gallery_id) = ${userIdList.size}
Note that #{userIdList.size} won't work here because the expression in #{} is parsed by MyBatis' internal expression parser and not by OGNL.

LIMIT in PostgresQL

I have query written in Oracle in MyBatis Mapper xml file like below:
<select id="getUserList" resultMap="userListResult" parameterType="org.user.UserNumber>
select * from user
WHERE (1=1)
<if test="num != null">AND rownum <= #{num}</if>
</select>
I need to make this Postgres Compliant. So, converted as below:
<select id="getUserList" resultMap="userListResult" parameterType="org.user.UserNumber>
select * from user
WHERE (1=1)
<if test="num != null">AND LIMIT #{num}</if>
</select>
But it is not working and throwing exception:
PSQLException: ERROR: syntax error at or near \"LIMIT\"\n
Can anyone help me please how to replace rownum here in Postgres?

Dynamic SQL using mybatis not fetching the mail id

I am trying myBatis recently and I have been facing a problem when forming dynamic sqls.
When using myBatis to form dynamic sql like below, it works well with all the fields except when I send value in email field.
No data is fetched when emailId is passed. I have a doubt if the # symbol in emailId column is having a problem?
<select id = "getAllWithFilter" parameterType="java.util.Map" resultMap="result">
SELECT * FROM EMPLOYEE_LOOKUP
<where>
<if test = "firstName != null">
FIRST_NAME LIKE #{firstName}
</if>
<if test = "phoneNo != null">
AND PHONE LIKE #{phoneNo}
</if>
<if test = "emailId != null">
AND EMAIL LIKE #{emailId}
</if>
<if test = "analystGroup != null">
AND GROUP LIKE #{empGroup}
</if>
<choose>
<when test = "activeFlag != null">
AND EXPIRATION_DATE IS NULL
</when>
<when test = "inactiveFlag != null">
AND EXPIRATION_DATE IS NOT NULL
</when>
</choose>
</where>
</select>
This is the DEBUG Logs in myBatis - Log4J.
DEBUG [http-bio-9081-exec-1] - ==> Preparing: SELECT * FROM EMPLOYEE_LOOKUP WHERE EMAIL LIKE ? AND GROUP LIKE ? AND EXPIRATION_DATE IS NULL
DEBUG [http-bio-9081-exec-1] - ==> Parameters: abc(String), F(String)
Database, contains the following values
EMAIL | GROUP
----------------------
abc#gsf.com | F
You have simply forgotten the % surrounding the parameter value:
AND EMAIL LIKE '%' + #{emailId} + '%'
or
AND EMAIL LIKE '%' || #{emailId} || '%'
depending on DB vendor.
Alternatively, you can add the % in the param value after escaping those that might be in the param value.
otherwise it behaves as =