前言:在我上篇已经学习了Mybatis简介以及如何去连接数据库,具有增删改查的方法。那么我们今天来学习Mybatis的第二节关于1.mybatis动态sql,2.模糊查询(3种方式),3.查询返回结果集。希望大家学了可以对你们的学习,工作具有帮助。
经典面试题:
问题一:#{...}与${...}区别?
1.$是占位值赋值,#是预处理SQL
2. 参数类型为字符串,#会在前后加单引号['],$则直接插入值
注: mybatis中使用OGNL表达式传递参数
3.${...}方式存在SQL注入风险
4.${...}可以做动态列,完成动态sql开发。
注意: 优先使用#{...},因为: ${...}方式存在SQL注入风险
补充:SQL注入风险:SQL注入风险是指通过植入恶意的SQL代码,攻击者可以绕过正常的安全验证机制,执行恶意的数据库操作,导致数据泄露、破坏或未授权访问。这种风险在报表中也存在。通过在报表的查询条件中注入恶意的SQL代码,攻击者可以利用这个漏洞获取敏感数据或对数据库进行破坏。此外,由于报表工具往往直接拼接用户输入的条件串作为SQL语句的一部分,如果没有对用户输入进行充分的验证和过滤,就容易受到SQL注入攻击。因此,为了防范SQL注入风险,在报表开发中需要采取相应的安全措施,如对用户输入进行严格的验证和过滤,使用参数化查询等。
举实例:我们在使用sql查询时使用的两种方式:
deptid=822520
select * from t_oa_employee where deptid = #{deptid}
select * from t_oa_employee where deptid = 822520
select * from t_oa_employee where deptid = ${deptid} select * from t_oa_employee where deptid =822520 or 1 = 1
第二种sql会查出来所有员工信息的不安全哦
问题二:在mybatis中 resultMap,resultType区别?
在MyBatis中,resultMap和resultType是用于在查询中进行结果映射的两种方式。它们的区别如下:
- 对象不同:resultType是直接指定返回类型,而resultMap是一个定义了结果映射规则的对象。
- 描述不同:resultType通过属性名来进行结果映射,只有查询出来的列名与属性名一致时才能成功映射。而resultMap可以通过配置来定义复杂的映射规则,可以自由地对查询结果进行处理和映射。
- 类型适用不同:resultType适用于简单的查询结果映射,当查询结果的列名和属性名一致时比较方便。而resultMap适用于复杂的查询结果映射,可以灵活地处理和映射不同的查询结果。
1.mybatis动态sql
介绍:MyBatis动态SQL是一种基于OGNL表达式的技术,可以在SQL语句中实现一些逻辑判断。总体上,MyBatis动态SQL主要包含以下几类语句:
1. if语句:用于简单的条件判断。
2. choose语句(相当于Java语言中的switch):包含when和otherwise子句,类似于JSTL中的choose语句。
3. trim语句:在包含的内容上添加前缀或后缀,可以用于动态地拼接SQL语句。
4. where语句:主要用于简化SQL语句中的where条件判断,能够智能地处理and和or,防止多余导致语法错误。
5. set语句:主要用于更新操作。
6. foreach语句:在实现MyBatis的in语句查询时特别有用。
以上是MyBatis动态SQL的几种主要用法,可以根据具体需求选择适合的方式来编写动态SQL语句。
MyBatis Dynamic SQL是一个与MyBatis配套的项目,它解决了MyBatis在动态SQL方面的一些缺点,并提供了更灵活、强大的动态SQL功能。该项目可以帮助开发人员更方便地编写复杂的SQL语句,提高开发效率。你可以在官方文档中了解更多关于MyBatis Dynamic SQL的信息。
例如在我们的Mapper文件中修改方法的if标签
例如在我们的自定义Mapper文件中查询的foreach标签
使用foreach去得到指定id的查询指定的值
Mapper.xml
<select id="selectBooksIn" resultType="com.lya.model.Book" parameterType="java.util.List"> select * from t_mvc_book where bid in <foreach collection="bookIds" open="(" close=")" separator="," item="bid"> #{bid} </foreach> </select>
BookMapper的接口
List<Book> selectBooksIn(@Param("bookIds") List bookIds);
IBookService接口
List<Book> selectBooksIn(@Param("bookIds") List bookIds);
BookServiceImpl
@Override public List<Book> selectBooksIn(List bookIds) { return bookMapper.selectBooksIn(bookIds); }
运行结果:
2.模糊查询(3种方式)
2.1 参数中直接加入%%
<!-- 模糊查询--> <!-- 1--> <select id="like1" resultType="com.lya.model.Book" parameterType="java.lang.String"> SELECT <include refid="Base_Column_List" /> from t_mvc_book where bname like #{bname} </select> <!--2--> <select id="like2" resultType="com.lya.model.Book" parameterType="java.lang.String"> SELECT <include refid="Base_Column_List" /> from t_mvc_book where bname like ${bname}; </select> <!-- 3--> <select id="like3" resultType="com.lya.model.Book" parameterType="java.lang.String"> SELECT <include refid="Base_Column_List" /> from t_mvc_book where bname like concat('%','圣墟','%'); </select>
这里我们运行第二种会有个报错
解决方法:传值添加单引号
2.3 SQL字符串拼接CONCAT
3.查询返回结果集
resultMap:适合使用返回值是自定义实体类的情况
resultType:适合使用返回值的数据类型是非自定义的,即jdk的提供的类型
3.1 使用resultMap返回自定义类型集合
返回单表的对应的实体类,仅有一个查询结果,可以用resultType/resultMap。
使用了resultType
<select id="selectresultType" resultType="com.lya.model.Book" parameterType="java.lang.Integer"> select <include refid="Base_Column_List"/> from t_mvc_book where bid = #{bid,jdbcType=INTEGER} </select>
编写接口实现接口
Book selectresultType(Integer bid); @Override public Book selectresultType(Integer bid) { return bookMapper.selectresultType(bid); }
测试方法
@Test public void selectresultType() { System.out.println("测试resultType查询"); Book book = bookbiz.selectByPrimaryKey(12); System.out.println(book); }
测试结果
2.返回单表的对应的实体类,有多个查询结果,可以用resultType/resultMap。
1.resultType/resultMap。resultType一个或多个都用实体对象
<select id="selectresultType01" resultType="com.lya.model.Book"> select <include refid="Base_Column_List"/> from t_mvc_book </select> <select id="selectresultMap01" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from t_mvc_book </select>
编写接口方法和实现接口
List<Book> selectresultType01(); List<Book> selectresultMap01(); @Override public List<Book> selectresultType01() { return bookMapper.selectresultType01(); } @Override public List<Book> selectresultMap01() { return bookMapper.selectresultMap01(); }
测试方法
@Test public void selectresultType01() { bookbiz.selectresultType01().forEach(System.out::println); } @Test public void selectresultMap01() { bookbiz.selectresultMap01().forEach(System.out::println);
- 返回多表的对应的实体类,仅有一个查询结果,通常用resultType,也可以用resultMap。
- 返回多表的对应的实体类,有多个查询结果,通常用resultType,也可以用resultMap。
- 返回单个列表,仅有一个查询结果,就用resultType。
- 返回单个列表,有多个查询结果,就用resultType。
配置xml
<!--单个-->
<select id="selectByString01" resultType="java.lang.String" parameterType="java.lang.Integer"> select bname from t_mvc_book where bid = #{bid,jdbcType=INTEGER} </select>
<!--多个-->
<select id="selectByString02" resultType="java.lang.String" parameterType="java.lang.String"> select bname from t_mvc_book where bname like concat('%', #{bname}, '%') </select>
编写接口和实现接口
String selectByString01(Integer bid); List<String> selectByString02(String bname); @Override public String selectByString01(Integer bid) { return bookMapper.selectByString01(bid); } @Override public List<String> selectByString02(String bname) { return bookMapper.selectByString02(bname); }
测试方法
@Test public void selectByString01() { System.out.println(bookbiz.selectByString01(60)); } @Test public void selectByString02() { Map map = new HashMap(); map.put("sid", "01"); map.put("cid", "01"); bookbiz.selectByString02("圣墟").forEach(System.out::println);
总结:
总结来说,resultType是一种简单的结果映射方式,适用于列名和属性名一致的情况;而resultMap是一种更为灵活和强大的结果映射方式,可以自定义映射规则来处理复杂的查询结果