簡體   English   中英

MyBatis 3 - 從mapper獲取SQL字符串

[英]MyBatis 3 - get SQL string from mapper

我想僅使用MyBatis3來生成SQL字符串(使用xml映射),但我獲得的SQL無效。

例如,我獲取了sql字符串:

SELECT * FROM USER WHERE NAME = john

在這個sql中不存在' char sorrounding string value john

mybatis.xml中

...
    <mappers>
        <mapper resource="sql1.xml"/>
    </mappers>
...

sql1.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

   <mapper namespace="sql1">
       <select id="select1" parameterType="map" resultType="String" >
           SELECT * FROM USERS
           WHERE 
           name LIKE ${name} AND num = ${number}
       </select>
   </mapper>

MyBatisSql.java中

SqlSessionFactory sessionFactory = ConnectionFactory.getSqlSessionFactory();
Configuration configuration = sessionFactory.getConfiguration();

Map pars = new HashMap<String, Object>();
pars.put("name", "john");    
pars.put("number", 1345);

MappedStatement ms = configuration.getMappedStatement("sql1.select1);   
BoundSql boundSql = ms.getBoundSql(params);
String sql = boundSql.getSql();
System.out.println(sql);

結果是

SELECT * FROM USERS
WHERE 
name LIKE john AND num = 12345

在這個SQL中,字符串john沒有被' char包圍,所以它不是有效的SQL(我的目的只是使用myBatis生成有效的SQL字符串)。 我想:

SELECT * FROM USERS
WHERE 
name LIKE 'john' AND num = 12345

謝謝

您應該使用#{name}而不是$ {name}

下面的示例將生成一個有效的SQL

<mapper namespace="sql1">
    <select id="select1" parameterType="map" resultType="String" >
        SELECT * FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
    </select>
</mapper>

如果使用$ character,MyBatis會直接復制並粘貼字符串參數。 另一方面,如果使用#character,則使用參數綁定。

然后,您應該使用selectMap,selectList或selectOne執行您的sql,

List<String> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);

此調用將自動將參數綁定到語句並執行它。

警告:

<select id="select1" parameterType="map" resultType="String" >
    SELECT * FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
</select>

可能無法執行,因為MyBatis無法將多個列( SELECT * )映射到單個字符串( resultType =“String” ),查詢的兩個可能的更正如下所示:

<!--Solution One-->
<select id="select1" parameterType="map" resultType="String" >
    SELECT name FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
</select>

<!--Solution Two-->
<select id="select1" parameterType="map" resultType="java.util.LinkedHashMap" >
    SELECT * FROM USERS
        WHERE 
        name LIKE #{name} AND num = #{number}
</select>

對於解決方案二,您應該使用以下java代碼執行mybatis查詢:

List<Map<?, ?>> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);

有關為什么getBoundSql返回查詢的詳細信息?:

參數綁定在驅動程序級別完成,因此您不會得到像這樣的sql字符串

SELECT * FROM USERS
WHERE 
name LIKE 'john' AND num = 12345

相反,你將獲得准備參數綁定的SQL查詢模板,

SELECT * FROM USERS
    WHERE 
    name LIKE ? AND num = ?

在sql字符串中添加參數允許sql注入 安全的方法是使用SQL Driver提供的參數綁定方法,MyBatis總是使用參數綁定。

假設您手動創建sql命令為字符串,並假設我是一個試圖訪問您的數據的appleius用戶。 我可以寫

john' or ''='

所以這將生成下面的sql命令:

SELECT * FROM USERS
WHERE 
name LIKE 'john' or ''='' AND num = 12345

參數綁定的其他好處

參數綁定的第二個好處是它允許預處理語句。 假設您需要使用不同的參數執行相同的sql 1000次。

如果生成帶參數綁定的sql字符串,

SELECT * FROM USERS WHERE name LIKE 'john' AND num = 12345;
SELECT * FROM USERS WHERE name LIKE 'foo' AND num = 67890;

數據庫服務器需要逐個解析每個sql命令然后執行它們。

使用參數化的SQL查詢,

SELECT * FROM USERS WHERE name LIKE ? AND num = ?

SQL驅動程序緩存查詢,因此只進行一次解析,然后將不同的參數綁定到同一SQL命令

更新:在MyBatis之外使用BoundSql

您仍然可以將參數化的sql(boundSql)與另一個庫或Java的java.sql.Connection一起使用。 以下是一個例子:

Connection myConnection;
PreparedStatement preparedStatement = myConnection.prepareStatement(boundSql);
preparedStatement.setString(1, "john"); //First parameter starts with 1 not 0!
preparedStatement.setInt(2, 12345);
ResultSet results = preparedStatement.executeQuery();
            SELECT(" * ");
            FROM(" student ");
            WHERE(" ten LIKE '%' #{ten} '%' ");

您可以使用它,並且必須在'%'和#{}之間放置一個空格(_)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM