MyBatis dynamically including script - mybatis

I am trying to dynamically include select query based on some input parameters.
The following is what I am trying to achieve.
<sql id="query1">
SELECT * from
table_1
WHERE a = #{param1}
</sql>
<sql id="query2">
SELECT * from
table_2
WHERE b = #{param2}
</sql>
<select id = "selectSomethingFromDB">
<include refid="#{readerIdName}" />
</select>
I am planning to pass the sql id name as parameter to the query and trying to dynamically choose the select query based on this param. (Sort of like a factory design implementation).
However #{readerIdName} is not getting replaced with the value I am passing as param.
Is something like this possible?

The xml attributes at this level are not evaluated in runtime by mybatis.
You can use a single <SQL id="..."> query and an <if test="..."> dynamic sql in it.

Related

How to execute sql by getting dynamic table from mybatis without using ${}?

I am trying to execute an sql statement by receiving a dynamic table.
If #{} is used, sql does not work because it is entered in the form of'layer_name'.
Therefore, I have to use ${}, but there is a problem that is vulnerable to sql injection.
<select id="test" parameterType="map" resultType="map">
select
*
from
${table_name}
</select>
I want to use a procedure to solve this problem, but the return type is ambiguous because I have to do 'select all'.
Any ideas would be appreciated.

Iterate over string in mybatis

my string parameter is like this: '(1,2,3,4)'
I want to iterate over this
SELECT * FROM table WHERE value IN #{myparameter}
How can I do this?
You can put the value into the query verbatim like this:
SELECT * FROM table WHERE value IN ${myparameter}
But note that this does not use prepared statements parameters. It has all the downsides of not using prepared statements, namely: it is not type save, vulnerable to SQL injection, requires escaping etc
You should better convert the string to a list and then generate the query in a type safe manner:
SELECT *
FROM table
WHERE value IN
<foreach item="item" index="index" collection="myparameter"
open="(" separator="," close=")">
#{item}
</foreach>
myparameter should be a Collection of whatever type the value column is.

How <selectKey> support multiple DataSource in MyBatis

In Mybatis, we use <selectedKey> for generated column when define the insert statement, but for different DB it has different content in selectedKey element.
For MySQL like this:
<selectKey resultType="java.lang.Long" order="AFTER" keyProperty="productId">
SELECT LAST_INSERT_ID()
</selectKey>
For Oracle like this:
<selectKey resultType="java.math.BigDecimal" order="BEFORE" keyProperty="id">
SELECT U_USER_INFO_SEQ.Nextval as ID from DUAL </selectKey>
So how this support multiple DataSource?
You can try using http://www.mybatis.org/mybatis-3/configuration.html#databaseIdProvider.
Doing so allows you to use _databaseId as described http://www.mybatis.org/mybatis-3/dynamic-sql.html#Multi-db_vendor_support

Does Mybatis support DDL?

My project is a Database center, like PLSQL but used in a web browser. Sometimes I need to create or alter a table, but I don't know if Mybatis supports DDL, and I haven't found any documents about this.
For the most part DDL works just like DML using mybatis. The one difference is that you will need to use ${} instead of #{} for parameters. Most databases do not support prepared statements with DDL. The $ notation is a string substitution rather than a parameter for a prepared statement.
<update id="exchangePartition" parameterType="java.util.Map">
alter table ${destinationTableName}
exchange partition ${destinationPartitionName}
with table ${sourceTableName}
including indexes
with validation
</update>
It is also helpful to know the call syntax with the statement type callable to invoke stored procedures.
<update id="gatherStatistics" statementType="CALLABLE" parameterType="Map">
{call
dbms_stats.gather_table_stats(
ownname => #{tableOwner},
tabname => #{tableName}
<if test="partitionName != null">
, partname => #{partitionName}
</if>
)
}
</update>
MyBatis supports any native SQL/PlSql commands.
So yes, it supports DDL statements.

MyBatis query not returning values when using a join

This is probably something stupid, but I've not been able to find it. I'm using MyBatis 3.2.2, PostgreSQL 9.2.2, and XML mappings, although I had the same experience with annotations. I've set up a simple select that returns a list of objects. This configuration works as expected:
<select id="getCasesBySite" parameterType="string" resultType="Case">
select c.* from cases c
</select>
and returns a list of Case objects. This however returns nothing:
<select id="getCasesBySite" parameterType="string" resultType="Case">
select c.* from cases c join siteinfo s on c.siteid = s.id where s.key=#{site}
</select>
My mapper interface has this:
List<Case> getCasesBySite(#Param("site") String site);
Debug logging for the version that uses a join is:
... ==> Preparing: select c.* from cases c join siteinfo s on c.siteid = s.id where s.key=?
... ==> Parameters: sw(String)
If I copy the above SQL and paste it into my psql command line (replacing ? with 'sw'), I receive a list of results, so it looks like the join query itself is OK.
Is there something else I should be doing? This is driving me nuts. I remember there being an issue with case sensitivity when working with PostgreSQL, but if that's the problem I'm not sure how to address it.
I can include more information. I just wasn't sure what was relevent.
After much debugging, the problem appears to be related to transactions and our testing framework. We're using Unitils to handle refreshing test data, and we found that after setting this property:
DatabaseModule.Transactional.value.default=disabled
in the unitils.properties file, the tests all ran as expected.