简体   繁体   English

MyBatis 3 - 从mapper获取SQL字符串

[英]MyBatis 3 - get SQL string from mapper

I'd like to use MyBatis3 only to produce SQL string (using the xml mapping) but the SQL i obtain is not valid. 我想仅使用MyBatis3来生成SQL字符串(使用xml映射),但我获得的SQL无效。

Example, I obtain the sql string: 例如,我获取了sql字符串:

SELECT * FROM USER WHERE NAME = john

In this sql isn't present the ' char sorrounding the string value john 在这个sql中不存在' char sorrounding string value john

in mybatis.xml : mybatis.xml中

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

sql1.xml 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>

in MyBatisSql.java : 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);

the result is 结果是

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

in this SQL, the string john , isn't enclosed by the ' char so it's not a valid SQL (my purpose is only to produce valid SQL string using myBatis). 在这个SQL中,字符串john没有被' char包围,所以它不是有效的SQL(我的目的只是使用myBatis生成有效的SQL字符串)。 I'd like to have: 我想:

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

thanks 谢谢

You should use #{name} instead of ${name} . 您应该使用#{name}而不是$ {name}

The sample below will generate a valid SQL 下面的示例将生成一个有效的SQL

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

MyBatis directly copies and pastes the string parameter if you use $ character. 如果使用$ character,MyBatis会直接复制并粘贴字符串参数。 On the other hand it uses parameter binding if you use # character. 另一方面,如果使用#character,则使用参数绑定。

You should then execute your sql using selectMap, selectList or selectOne, 然后,您应该使用selectMap,selectList或selectOne执行您的sql,

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

This call will automatically bind the parameters to the statement and execute it. 此调用将自动将参数绑定到语句并执行它。

WARNING: 警告:

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

might fail to execute since MyBatis cannot map multiple columns ( SELECT * ) to a single string ( resultType="String" ) two possible corrections to the query is shown below: 可能无法执行,因为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>

For solution two you should execute mybatis query using the java code below: 对于解决方案二,您应该使用以下java代码执行mybatis查询:

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

Details of Why getBoundSql Returns a Query with ?: 有关为什么getBoundSql返回查询的详细信息?:

Parameter binding is done at driver level so you will not get an sql string like this 参数绑定在驱动程序级别完成,因此您不会得到像这样的sql字符串

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

Instead you'll get sql query template which is ready for parameter binding, 相反,你将获得准备参数绑定的SQL查询模板,

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

Adding parameters into sql string allows sql injection . 在sql字符串中添加参数允许sql注入 Safe way is to use parameter binding method provided with SQL Driver and MyBatis always uses parameter binding. 安全的方法是使用SQL Driver提供的参数绑定方法,MyBatis总是使用参数绑定。

Suppose that you manually created your sql command as string, and suppose that I'm a malicius user trying to access your data. 假设您手动创建sql命令为字符串,并假设我是一个试图访问您的数据的appleius用户。 I can write 我可以写

john' or ''='

So this will generate the sql command below: 所以这将生成下面的sql命令:

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

Additional Benefits of Parameter Binding 参数绑定的其他好处

The second benefit of parameter binding is that it allows prepared statements. 参数绑定的第二个好处是它允许预处理语句。 Suppose that you need to execute same sql 1000 times with different parameters. 假设您需要使用不同的参数执行相同的sql 1000次。

If you generate sql strings with parameters bound, 如果生成带参数绑定的sql字符串,

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

database server will need to parse each sql command one by one and then execute them. 数据库服务器需要逐个解析每个sql命令然后执行它们。

With parameterized sql queries, 使用参数化的SQL查询,

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

SQL driver caches the query so parsing is done only once and then it binds different parameters to the same SQL command . SQL驱动程序缓存查询,因此只进行一次解析,然后将不同的参数绑定到同一SQL命令

Update: Using BoundSql Outside of MyBatis 更新:在MyBatis之外使用BoundSql

You can still use the parameterized sql (boundSql) with an another library or Java's java.sql.Connection. 您仍然可以将参数化的sql(boundSql)与另一个库或Java的java.sql.Connection一起使用。 Below is an example: 以下是一个例子:

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} '%' ");

You can use it and you must put a space(_) between '%' and #{} 您可以使用它,并且必须在'%'和#{}之间放置一个空格(_)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从 MyBatis 映射器获取 SQL 查询的字符串表示 - Getting string representation of an SQL query from MyBatis mapper mybatis删除映射器从对象获取参数 - mybatis delete mapper get param from object 在mapper文件中访问mybatis sql中的public static final字符串 - Access public static final string in mybatis sql in mapper files 将整个SQL查询作为参数传递给MyBatis中的映射器 - Passing an entire sql query as a parameter into a mapper in MyBatis mybatis中解析SQL Mapper配置出错 - Error parsing SQL Mapper Configuration in mybatis MyBatis log4j 配置只记录映射器 XML 中的 SQL 名称,而不记录 SQL - MyBatis log4j configuration to log only SQL names from mapper XMLs and not SQLs 如何从注释配置的Mybatis映射器读取生成的sql语句 - how to read generated sql statement from annotation-configured Mybatis mapper 如何从另一个映射器在 myBatis 映射器中设置参数 - How to set argument in myBatis mapper from another mapper 如何从 PostgreSQL function 获取通过 MyBatis mapper 方法调用的服务器消息(raise notice)? - How to get server messages (raise notice) from PostgreSQL function that was invoked through MyBatis mapper method? 为什么我不能从地图上获得价值 <String,String> 从基于mybatis的sql查询中获取的变量? - Why cann't I get a value from a Map<String,String> variable that got from mybatis-based sql query?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM