MyBatis SQL参数传递(掌握)java
SQL映射器Mapper接口(掌握)Mybmysql
atis批量操做(理解掌握)程序员
(多对一)关联映射(掌握)面试
(一对多,多对多)集合映射 算法
MyBatis原理回顾(Object Relational Mapping,简称ORM)spring
ORM的缺点是会牺牲程序的执行效率和会固定思惟模式。
从系统结构上来看,采用ORM的系统通常都是多层系统,系统的层次多了,效率就会下降。ORM是一种彻底的面向对象的作法,而面向对象的作法也会对性能产生必定的影响。
在咱们开发系统时,通常都有性能问题。性能问题主要产生在算法不正确和与数据库不正确的使用上。ORM所生成的代码通常不太可能写出很高效的算法,在数据库应用上更有可能会被误用,主要体如今对持久对象的提取和和数据的加工处理上,若是用上了ORM,程序员颇有可能将所有的数据提取到内存对象中,而后再进行过滤和加工处理,这样就容易产生性能问题。
在对对象作持久化时,ORM通常会持久化全部的属性,有时,这是不但愿的。
但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不能否认的。但咱们不能期望工具能一劳永逸的解决全部问题,有些问题仍是须要特殊处理的,但须要特殊处理的部分对绝大多数的系统,应该是不多的。sql
S(spring)S(springmvc)M(mybatis)集成(掌握)数据库
MyBatis是一个ORM持久化框架,应用到系统持久层(Dao);缓存
一个MyBatis的应用程序都以一个SqlSessionFactory对象(单例)的实例为核心安全
SqlSession对象彻底包含以数据库为背景的全部执行SQL操做的方法
MyBatis是针对数据库交互的一个辅助框架,也是对jdbc作了的简单封装,以xml配置代替Java代码来管理数据库的交互细节!!
MyBatis可使用简单的XML或注解用于配置和原始映射,将接口(Mapper)和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中一条记录。
MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎全部的JDBC代码和参数的手工设置以及对结果集的检索封装。
加入mybatis
- MyBatis SQL参数传递
#{OGNL表达式} 和 ${OGNL表达式} 的区别
1.1. #{OGNL表达式}
MyBatis会把这个表达式使用?(占位符)替换,做为一个sql参数使用:推荐使用
好比name的值为:
定义SQL: select * from t_user where name = #{name}
最终SQL: select * from t_user where name = ?
1.2. ${OGNL表达式}
MyBatis会把这个表达式的值替换到sql中,做为sql的组成部分;
该方式主要用于程序拼接SQL;
若是sql中使用${OGNL},而且参数的类型是(integer,string....)那么OGNL表达式能够写成任意东西;
1.3. ${OGNL}表达式的应用场景:
1.3.1. 不能用在登陆,会出现sql注入
好比登陆功能,在输入name的时候能够人为的制形成功:
User user=new User();
user.setName("\"admin\" or \"1=1\" ");
user.setPassword("\"admin\" ");
定义SQL: select id,name,password from t_user where name = ${name} and password=${password}
最终SQL: select id,name,password from t_user where name="test" or "1=1" and password="test" 出现sql注入
能够用在order by + limit的场景
#{}和${}的使用
resultMap和ParameterMap书写拼写要使用#{},resultType 和parameterType类型使用${},使用例子以下:
Select ID,COMMAND from Message where COMMAND=#{command}
Select ID,COMMAND from Message where COMMAND=‘${command}’
前者解析为:
Select ID,COMMAND from Message where COMMAND=?具备预编译效果
后者解析为:
Select ID,COMMAND from Message where COMMAND=段子 不具备预编译效果
可是,例如当页面向后台传递一个列名(属性名)的时候,是不但愿被预编译出一个?的,此时要用到$格式;
如:加上 order by${param} ,此时param是一个列名。
#{}和 ognl表达式
通常参数的拼写仍是保证统一风格为好,便于人读。
常常碰到这样的面试题目:#{}和${}的区别是什么?
网上的答案是:#{}是预编译处理,$ {}是字符串替换。mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;mybatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。使用 #{} 能够有效的防止SQL注入,提升系统安全性。
对于这个题目我感受要抓住两点:
(1)$ 符号通常用来看成占位符,常使用Linux脚本的人应该对此有更深的体会吧。既然是占位符,固然就是被用来替换的。知道了这点就能很容易区分$和#,从而不容易记错了。
(2)预编译的机制。预编译是提早对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。咱们知道,SQL注入是发生在编译的过程当中,由于恶意注入了某些特殊字符,最后被编译成了恶意的执行操做。而预编译机制则能够很好的防止SQL注入。
最后想说的是,对于mybatis 以及 sql 而言,每个考点背后都是有一个深入的思想存在的,应该好好的体会。这样才能真正的作到技术提高,成为技术大牛。
这第三个例子虽说的是#{}和{}通用的问题,也就是说在此种状况下#{}和
{}是通用的,只不过须要些小的转换.如例子中须要手动
拼接单引号 ' ' 到变量值的先后,确保sql语句正常.
简单说#{}是通过预编译的,是安全的,而${}是未通过预编译的,仅仅是取变量的值,是非安全的,存在sql注入.
这里先说一下只能的情况,从我们前面的例子中也能看出,ord
{}了,用#{}会多个' '致使sql语句失效.此外还有一个like 语句后也须要用${},简单想一下
就能明白.因为仅仅是简单的取值,所以以前sq
{},那么不作任何处理的时候是存在sql注入危险的.你说怎么防止,那我只
能悲惨的告诉你,你得手动处理过滤一下输入的内容,如判断一下输入的参数的长度是否正常(注入语句通常很长),更精确写查询一下输入的参数
- SQL映射器Mapper接口
MyBatis基于代理机制,可让咱们无需再编写Dao的实现。直接把之前的dao接口定义成符合规则的Mapper。
Mybatis的批量操做(foreach)
1 <!-- delete from product where id in ( ? , ? ) 批量删除: 2 collection="list":传入的list,至关于map的key,经过list获得传入的整个集合的值; 3 index="index" :每次循环的索引 4 item="id" :每次循环的这个值 5 open="(" :以什么开始 6 separator=",":分隔符 7 close=")":以什么结束 8 --> 9 <delete id="deleteBatch" parameterType="java.util.List"> 10 delete from product where id 11 in 12 <foreach collection="list" index="index" item="id" open="(" 13 separator="," close=")"> 14 #{id} 15 </foreach> 16 </delete>
1 <!-- 批量插入: 2 insert into product(productName,salePrice,costPrice,cutoff,supplier,brand,dir_id) 3 values (?,?,?,?,?,?,?) , (?,?,?,?,?,?,?) 4 parameterType:传入参数是:java.util.List的类型的; 5 对传入的list进行foreach循环:取出值填入插入的values中: 6 collection="list":这个不能修改,表示传入的一个list相似于一个key是list,获得传入的list集合 7 index="index":每一次遍历的序号 8 item="item":每次遍历的这个对象别名,能够修改 9 separator=",":每遍历一次后的分隔符 10 --> 11 <insert id="insertBatch" parameterType="java.util.List"> 12 insert into 13 product(productName,salePrice,costPrice,cutoff,supplier,brand,dir_id) 14 values 15 <foreach collection="list" index="index" item="item" 16 separator=","> 17 (#{item.productName},#{item.salePrice},#{item.costPrice},#{item.cutoff},#{item.supplier},#{item.brand},#{item.dir_id}) 18 </foreach> 19 </insert>
关联映射(多对一)
多对一:
多个员工属于一个部门,domain:在员工这方建立一个部门:在多方有一个外键
一对多:
一个部门有多个员工:Domain:在部门有一个员工list:在多方有一个外键
多对多:
角色和权限:一个角色拥有对个权限,一个权限属于多个角色
Domain:使用list表示:使用中间表维护关系
parameterType ,入参的全限定类名或类型别名 keyColumn ,设置数据表自动生成的主键名。对特定数据库(如PostgreSQL),若自动生成的主键不是第一个字段则必须设置 keyProperty ,默认值unset,用于设置getGeneratedKeys方法或selectKey子元素返回值将赋值到领域模型的哪一个属性中 useGeneratedKeys ,取值范围true|false(默认值),设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。MySQL和SQLServer执行auto-generated key field,所以当数据库设置好自增加主键后,可经过JDBC的getGeneratedKeys方法获取。但像Oralce等不支持auto-generated key field的数据库就不能用这种方法获取主键了 statementType ,取值范围STATEMENT,PREPARED(默认值),CALLABLE flushCache ,取值范围true(默认值)|false,设置执行该操做后是否会清空二级缓存和本地缓存 timeout ,默认为unset(依赖jdbc驱动器的设置),设置执行该操做的最大时限,超时将抛异常 databaseId ,取值范围oracle|mysql等,表示数据库厂家,元素内部可经过`<if test="_databaseId = 'oracle'">`来为特定数据库指定不一样的sql语句--------------------- 做者:零下