I'm using MyBatis to map some queries where I need to compare a String
argument (myString
).
My Mapper interface is:
public Map<Integer, String> findSomething(@Param("myString") String myString);
My XML is as follow:
<select id="findSomething" parameterType="String" resultType="Map">
SELECT column1 as key,
column2 as value
FROM my_table
<where>
<choose>
<when test="myString == 'xxx'">
column3 = 1
</when>
<when test="myString == 'yyy'">
myColumn = 2
</when>
<when test="myString == 'zzz'">
myColumn = 3
</when>
</choose>
</where>
ORDER BY value;
</select>
When I execute this statement the following error is throwed:
ERROR [stderr] Caused by: org.apache.ibatis.exceptions.PersistenceException:
ERROR [stderr] ### Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'myString' in 'class java.lang.String'
A String
comparison made this way, smells bad. Unfortunately it was the way database was modeled.
MyBatis version: 3.2.2
typeHandlers. Whenever MyBatis sets a parameter on a PreparedStatement or retrieves a value from a ResultSet, a TypeHandler is used to retrieve the value in a means appropriate to the Java type.
select * from patient where last_name like '%'|| #{lastName} ||'%'.
Background information. MyBatis is a persistence framework for Java that supports custom SQL statements, stored procedures, and advanced mappings. MyBatis eliminates the need to use JDBC code, manually configure parameters, and retrieve result sets.
In general, you should consider using #{} for string substitution instead of ${} . This is because #{} causes Mybatis to create a preparedStatement which prevents SQLInjection compared to ${} which would inject unmodified string into SQL.
Tested with MyBatis 3.2.8
<select id="findSomething" parameterType="String" resultType="Map">
SELECT column1 as key,
column2 as value
FROM my_table
<where>
<choose>
<when test='"xxx".equals(myString)'>
column3 = 1
</when>
<when test='"yyy".equals(myString)'>
myColumn = 2
</when>
<when test='"zzz".equals(myString)'>
myColumn = 3
</when>
</choose>
</where>
ORDER BY value;
</select>
Note the single quotes around test and the double quotes around de constant values. The trick is to use equals as you can see.
Definitely I had to go through a complicated approach.
Changed mapper method signature:
public Map<Integer, String> findSomething(@Param("myPojo") MyPojo myPojo);
The XML must be:
<select id="findSomething" resultType="Map">
SELECT column1 as key,
column2 as value
FROM my_table
<where>
<choose>
<when test="myPojo == 'xxx'">
column3 = 1
</when>
<when test="myPojo == 'yyy'">
myColumn = 2
</when>
<when test="myPojo == 'zzz'">
myColumn = 3
</when>
</choose>
</where>
ORDER BY value;
Just don't forget, being a POJO, the parameter class must have it's respective getters and setters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With