- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我只想使用 MyBatis3 来生成 SQL 字符串(使用 xml 映射)但我获得的 SQL 无效。
例如,我获取sql字符串:
SELECT * FROM USER WHERE NAME = john
在这个 sql 中不存在围绕字符串值 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 未包含在 ' 字符中所以它不是有效的 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>
如果使用 $ 字符,MyBatis 会直接复制粘贴字符串参数。另一方面,如果您使用 # 字符,它会使用参数绑定(bind)。
然后您应该使用 selectMap、selectList 或 selectOne 执行您的 sql,
List<String> resultSet = sessionFactory.openSession().selectList("sql1.select1", pars);
此调用会自动将参数绑定(bind)到语句并执行。
警告:
<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);
参数绑定(bind)是在驱动级别完成的,所以你不会得到这样的 sql 字符串
SELECT * FROM USERS
WHERE
name LIKE 'john' AND num = 12345
相反,您将获得已准备好进行参数绑定(bind)的 sql 查询模板,
SELECT * FROM USERS
WHERE
name LIKE ? AND num = ?
将参数添加到 sql 字符串中允许 sql 注入(inject)。安全的方法是使用 SQL Driver 提供的参数绑定(bind)方法,而 MyBatis 总是使用参数绑定(bind)。
假设您手动将 sql 命令创建为字符串,并假设我是一个试图访问您的数据的恶意用户。我会写
john' or ''='
所以这将生成下面的 sql 命令:
SELECT * FROM USERS
WHERE
name LIKE 'john' or ''='' AND num = 12345
参数绑定(bind)的第二个好处是它允许准备语句。假设您需要使用不同的参数执行相同的 sql 1000 次。
如果生成带有参数绑定(bind)的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 驱动程序缓存查询,因此只进行一次解析,然后将不同的参数绑定(bind)到相同的 SQL 命令。
您仍然可以将参数化的 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();
关于java - MyBatis 3 - 从映射器获取 SQL 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33197085/
SQL、PL-SQL 和 T-SQL 之间有什么区别? 谁能解释一下这三者之间的区别,并提供每一个的相关使用场景? 最佳答案 SQL 是一种对集合进行操作的查询语言。 它或多或少是标准化的,几乎所有关
这个问题已经有答案了: What is the difference between SQL, PL-SQL and T-SQL? (6 个回答) 已关闭 9 年前。 我对 SQL 的了解足以完成我的
我在数据库中有一个 USER 表。该表有一个 RegistrationDate 列,该列有一个默认约束为 GETDATE()。 使用 LINQ 时,我没有为 RegistrationDate 列提供任
我有一个可能属于以下类型的字符串 string expected result 15-th-rp 15 15/12-rp 12 15-12-th
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 9年前关闭
我有一个存储过程(称为 sprocGetArticles),它从文章表中返回文章列表。这个存储过程没有任何参数。 用户可以对每篇文章发表评论,我将这些评论存储在由文章 ID 链接的评论表中。 有什么方
我目前正在做一个 *cough*Oracle*cough* 数据库主题。讲师介绍embedded SQL作为让其他语言(例如 C、C++)与(Oracle)数据库交互的方式。 我自己做了一些数据库工作
SQL Server 中 SQL 语句的最大长度是多少?这个长度是否取决于 SQL Server 的版本? 例如,在 DECLARE @SQLStatement NVARCHAR(MAX) = N'S
这个问题已经有答案了: Simple way to transpose columns and rows in SQL? (9 个回答) 已关闭 8 年前。 CallType
预先感谢您对此提供的任何帮助。 假设我有一个查询,可以比较跨年的数据,从某个任意年份开始,永无止境(进入 future ),每年同一时期直到最后一个完整的月份(其特点是一月数据永远不会显示至 2 月
我在数据库中有一个 USER 表。该表有一个 RegistrationDate 列,该列的默认约束为 GETDATE()。 使用 LINQ 时,我没有为 RegistrationDate 列提供任何数
下面是我试图用来检查存储过程是否不存在然后创建过程的 sql。它会抛出一个错误:Incorrect syntax near the keyword 'PROCEDURE' IF NOT EXISTS
我有一个同事声称动态 SQL 在许多情况下比静态 SQL 执行得更快,所以我经常看到 DSQL 到处都是。除了明显的缺点,比如在运行之前无法检测到错误并且更难阅读,这是否准确?当我问他为什么一直使用
来自 lobodava 的动态 SQL 查询是: declare @sql nvarchar(4000) = N';with cteColumnts (ORDINAL_POSITION, CO
使用 SQL Server 中的存储过程执行动态 SQL 命令的现实优点和缺点是什么 EXEC (@SQL) 对比 EXEC SP_EXECUTESQL @SQL ? 最佳答案 sp_executes
我有这个有效的 SQL 查询: select sum(dbos.Points) as Points, dboseasons.Year from dbo.StatLines dbos i
我正在调试一些构建成功运行的 SQL 命令的代码。 然而,在查询结束时,查询结果似乎被写入了一个文本文件。 完整的查询如下 echo SELECT DATE,DATETABLE,DATE,APPDAT
我有一些创建表的 .sql 文件(MS SQL 数据库): 表_1.sql: IF OBJECT_ID (N'my_schema.table1', N'U') IS NOT NULL DROP TAB
我写了下面的 SQL 存储过程,它一直给我错误@pid = SELECT MAX(... 整个过程是: Alter PROCEDURE insert_partyco @pname varchar(20
我在 SQL Server 2005 中有包含两列 Fruit 和 Color 的表,如下所示 Fruit Colour Apple Red Orange
我是一名优秀的程序员,十分优秀!