zoukankan      html  css  js  c++  java
  • mybatis增强

    MyBatis SQL参数传递(掌握)

    SQL映射器Mapper接口(掌握)Myb

    atis批量操作(理解掌握)

    (多对一)关联映射(掌握)

    (一对多,多对多)集合映射  

    MyBatis原理回顾(Object Relational Mapping,简称ORM)

        ORM的缺点是会牺牲程序的执行效率和会固定思维模式。 
            从系统结构上来看,采用ORM的系统一般都是多层系统,系统的层次多了,效率就会降低。ORM是一种完全的面向对象的做法,而面向对象的做法也会对性能产生一定的影响。 

            在我们开发系统时,一般都有性能问题。性能问题主要产生在算法不正确和与数据库不正确的使用上。ORM所生成的代码一般不太可能写出很高效的算法,在数据库应用上更有可能会被误用,主要体现在对持久对象的提取和和数据的加工处理上,如果用上了ORM,程序员很有可能将全部的数据提取到内存对象中,然后再进行过滤和加工处理,这样就容易产生性能问题。 
            在对对象做持久化时,ORM一般会持久化所有的属性,有时,这是不希望的。 
            但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。但我们不能指望工具能一劳永逸的解决所有问题,有些问题还是需要特殊处理的,但需要特殊处理的部分对绝大多数的系统,应该是很少的。

    S(spring)S(springmvc)M(mybatis)集成(掌握)

    MyBatis是一个ORM持久化框架,应用到系统持久层(Dao);

    一个MyBatis的应用程序都以一个SqlSessionFactory对象(单例)的实例为核心

    SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法

    MyBatis是针对数据库交互的一个辅助框架,也是对jdbc做了的简单封装,以xml配置代替Java代码来管理数据库的交互细节!!

    MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口(Mapper)和JavaPOJOPlain Old Java Objects,普通的Java对象)映射成数据库中一条记录。

    MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。

    加入mybatis  

    1. 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注入.

     

    这里先说一下只能,,orderby

     

    {}了,用#{}会多个' '导致sql语句失效.此外还有一个like 语句后也需要用${},简单想一下

     

    就能明白.由于,sql,orderby

     

    {},那么不做任何处理的时候是存在sql注入危险的.你说怎么防止,那我只

     

    能悲惨的告诉你,你得手动处理过滤一下输入的内容,如判断一下输入的参数的长度是否正常(注入语句一般很长),更精确写查询一下输入的参数

     

     

    1. 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语句
    ---------------------
    作者:零下

     

     

     

          

  • 相关阅读:
    安卓上的蓝牙数据传输
    算法题 整理--- 不定时更新
    Scrapy 框架的安装以及常用指令
    Flask 基础
    HTTP 请求包含: (请求行,请求头,请求体)
    Python 字符串,列表,字典,集合的常用方法
    Vue+Django 登录测试
    用view视图不含序列化写图书管理系统
    解决hao123恶意捆绑浏览器问题
    不同试图实现增删改查操作
  • 原文地址:https://www.cnblogs.com/wzscom/p/10539722.html
Copyright © 2011-2022 走看看