MyBatis 3 – 从mapper获取SQL字符串

我想仅使用MyBatis3来生成SQL字符串(使用xml映射),但我获得的SQL无效。

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

SELECT * FROM USER WHERE NAME = john 

在这个sql中不存在 char sorrounding string value john

mybatis.xml中

 ...    ... 

sql1.xml

     SELECT * FROM USERS WHERE name LIKE ${name} AND num = ${number}   

MyBatisSql.java中

 SqlSessionFactory sessionFactory = ConnectionFactory.getSqlSessionFactory(); Configuration configuration = sessionFactory.getConfiguration(); Map pars = new HashMap(); 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

    

如果您使用$ character,MyBatis会直接复制并粘贴字符串参数。 另一方面,如果使用#character,则使用参数绑定。

然后,您应该使用selectMap,selectList或selectOne执行您的sql,

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

此调用将自动将参数绑定到语句并执行它。

警告:

  

可能无法执行,因为MyBatis无法将多个列( SELECT * )映射到单个字符串( resultType =“String” ),查询的两个可能的更正如下所示:

     

对于解决方案二,您应该使用以下java代码执行mybatis查询:

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

您可以使用它,并且必须在’%’和#{}之间放置一个空格(_)