mybatis mapper file escape characters - mybatis

In a mybatis mapper file for a sql select statement I am unable to use special characters (<=) in where expressions. For Example (a simplified select):
<select id="selectMonday" resultType="SheetGameRec">
select ColumnName
from Table
where ColumnName <= 2
order by ColumnName;
</select>
The following error is generated
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in Mapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper
Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: xx; columnNumber: xx; The content of elements must consist of well-formed character data or markup.
If I replace the <= with >= or =, the mapper file will work though this is not the select that I want.
How do I escape out these special characters. I have had trouble with other expressions like & as well. I am using mybatis 3.0.2.
Thanks.

You can use CDATA to escape special characters.
<select id="selectMonday" resultType="SheetGameRec">
select ColumnName
from Table
where ColumnName <![CDATA[ <= 2 ]]>
order by ColumnName;
</select>

Related

Pgsql query with empty HTML tags

I have a body column (data type text) in a posts table which is storing HTML string.
How can i write a query to get all the posts with body containing at least one empty link (e.g. <a href=".." whatever></a>)?
SELECT * FROM posts WHERE body ~* '^[^\>]*(>){1}</a>$';
It means that empty links must have only one single '>' character before the ending tag.

MyBatis XML access to incoming array without casting from string

In below code I get PgArray as an array of PrimaryKeys to template table, from another select query (<collection ... select='selectTemplate'/>). But the solution below seems like a little messy way of doing it. isn't there a way to access the array directly, so I wouldn't need to cast?
Hint: Having #{_parameter} doesn't work.
<select id="selectTemplate" parameterType="org.postgresql.jdbc.PgArray" resultMap="templateResultMap">
SELECT *
FROM template
WHERE template.id = ANY ('${_parameter}'::int[])
</select>

MyBatis: How to map underscore result to camelcase for one specific statement only?

I have a statement in the mybatis mapper.xml file:
<select id="queryCorpAndDept" parameterType="java.util.HashMap" resultType="java.util.HashMap">
SELECT ORGAN_NAME, ORGAN_ID FROM PUB_ORGAN
</select>
The statement above will return a list of HashMap. The keys of the hashmap will be ORGAN_NAME, ORGAN_ID. I know MyBatis has a setting named mapUnderscoreToCamelCase to map undercase to camelcase.
But is there another way to map underscore to camelcase without defining a JAVA Bean ?
Sorry for my english.
You can use column aliases to be able to do selective camelCasing as shown below:
<select id="queryCorpAndDept" parameterType="java.util.HashMap"
resultType="java.util.HashMap">
SELECT ORGAN_NAME "organName", ORGAN_ID "organId" FROM PUB_ORGAN
</select>

Laravel - SQL injection prevention with {{{ }}}

I have some forms in my page made in Laravel. According to documentation, triple braces - {{{ }}} can escape the output. So when I use:
{{{ Form::text('name') }}}
can I be 100% sure that there is no possibility to insert SQL injection command into this form input?
No you understood the {{{ }}} wrong. They escape the output.
So if you do
{{{ Form::text('name') }}}
The result is this:
<input name="test" type="text">
It still generates HTML code but it gets escaped so it's not interpreted as HTML but as plain text
Preventing SQL injection
You have to prevent SQL injection when saving data to the DB. Normally you do that in your controller. If you use Eloquent or Laravels Query Builder you don't have to worry to much. It will take care of possible SQL injection points. Only if you execute raw SQL you have to pay attention.
From the Laravel Docs:
Note: The Laravel query builder uses PDO parameter binding throughout to protect your application against SQL injection attacks. There is no need to clean strings being passed as bindings.

How to apply a method to a parameter in MyBatis

After reading about Mapper XMLs I can't help to wonder how one might go about appling some common transforms to a parameter. For example...
<select id="selectPerson" parameterType="String" resultType="hashmap">
<!-- #{name} should always be upper case and have a trailing % -->
SELECT * FROM PERSON WHERE FIRST_NAME like #{name}
</select>
After reading this and this I can make some observations.
Using SQL functions such as upper or concat or '||' or '+' to do transforms kills performance in DB2
I could always wrap the the mapper or expose the details in the service layer but that seems messy
What I want is to be able to do something like...
<select id="selectPerson" parameterType="String" resultType="hashmap">
<!-- #{name} should always be upper case and have a trailing % -->
SELECT * FROM PERSON WHERE FIRST_NAME like #{name.upperCase() + '%'}
</select>
Is something like this possible or what is the second best solution?
Update: it appears that MyBatis uses OGNL for some expression evaluation. For example, if and ${} expressions use OGNL but #{} does NOT appear to unless there is some way to trick it.
Bind
MyBatis allows for creating values from method and properties in the context using <bind/>.
Bind creates a new variable in the scope of the current statement. The OGNL statement that binds the value can use the passed in _parameter object to compute a new bound value that can then used by MyBatis to construct the prepared statement.
Example
Your example using bind:
<select id="selectPerson" parameterType="String" resultType="hashmap">
<!-- #{name} should always be upper case and have a trailing % -->
<bind name="nameStartsWith" value="_parameter.getName().upperCase() + '%'"/>
SELECT * FROM PERSON WHERE FIRST_NAME like #{nameStartsWith}
</select>
Source
MyBatis Dynamic SQL Documentation
I ran through the same problem too. But I didn't find any solution for this. So I had to preprocess the #{name} parameter from the calling function.