mybatis学习

1.全局配置文件相关

    1)properties元素来引入其他properties的内容,url属性用来引入网络或者磁盘路径下的资源;resource属性用来引入类路径下的资源

    2)settings元素用来配置很多重要的设置学习

    3)typeAliases元素为java类型命名别名,方面xml中填写,子元素<typeAlias type=""/>为指定类型取别名,默认类名开头小写;<package name=""/>子元素,通过指定包的方式,为包下类型批量取别名(别名不区分大小写);当用package批量取别名发生别名冲突的时候(包下的子包下有和包下相同名字的类型),可以用个对其中一个加上@Alias("别名");的方式来指定别名(mybatis中以及有对常见java类型的 别名了)

    4)typeHandlers类型处理器,每一中java类型到数据库类型的映射是由每一种类型处理器来完成的

    5)environments元素用于配置多个环境(比如开发环境和正式环境;mysql环境和oracle环境等),其属性default的值表示使用哪个环境信息。每一个environment子元素表示一种环境,且environment子元素中必须包含transactionManager和dataSource元素;事务管理器默认有2中jdbc和manager,也可以自定义,实现TransactionFactory接口即可;数据源默认有3中POOLED,UNPOOLED,JNDI,也可以自定义数据源,实现DataSourceFactory接口

    6)databaseIdProvider元素(<databaseIdProvider type="DB_VENDOR">)用于提供移植性的支持。在这个元素下配置对应数据库产品的别名,然后在需要跨平台的sql配置中通过databaseId属性指定对应的别名

    7)mappers元素用于将sql配置文件注册得到全局配置文件中,resource属性注册类路径下的配置文件,url配置网络上的,class注册接口(但是要求配置文件和接口在同一个目录下,且配置文件的名字和接口的名字相同;如果sql通过注解配置上去,那么只需要填写接口的全限定名)(重要的复杂的sql通过配置文件映射,不太重要不多变的sql可以通过注解的方式映射)

 以上标签的配置顺序是由要求的,不然会报错

  2.sql映射文件相关

    1)sql语句结束不要写分号;parameterType可以省略,传入的值直接用#{属性名}即可,session要手动提交事务,数据才能持久化到数据库中

    2)mybatis允许增删改直接定义一下类型:Integer(int),Long(long)(这俩个表示操作影响的行数),Boolen(影响行大于0就返回true),void ;如果定义的返回值是这种情况,则不用再对应sql上添加resultType属性

    3)mybatis支持获取自增主键的值,比如插入数据后获取插入数据的主键值,通过在insert元素上添加userGeneratorKeys="true"以及keyProperty=“java ban 存放主键的字段名” 即可

    4)mybatis对非自增主键的支持(比如uuid以及oracle的序列)是通过在sql映射元素添加<selectKey keyProperty="java bean 的id 属性名" order="BEFORE" resultType="string"></selectKey>。其中order属性表示该配置项中的sql是在insert语句之前还是之后执行的。

    5)mybatis对传参的处理

        规则:

        a。传递单个参数:mybatis不做特殊处理  :#{随便命名}获得参数值

        b。传递多个参数:mybatis将多个参数封装多个map对象,而map的key的规则参数的索引(0开始)或者param1,param2....paramn;

                为了取值更佳方便,可以在参数前面加上@param("参数别名")的方式为map的key命名,这样取值就直接通过  #{对应参数别名}获得

        举例:

        a。可以传递pojo:当传递的参数正好是业务逻辑的数据模型的数据,可以直接传入pojo。取值的方式为#{属性名};(将多个参数封装为单个参数)

        b.Map传递:如果多个参数不是业务逻辑的数据模型也没有对应的pojo,且不常用,可以手动将参数在业务层封装成Map对象传递进去,取值的方式为#{key}

        c.TO传递:如果多个对象不是业务逻辑数据模型,但是常用(比如分页数据),可以封装成一个数据传输对象TO传递,取值为#{To对象的属性名}

        特别注意:Collection(list和map)类型或者是数组,mybatis也会做特殊处理封装为Map对象。key的规则为:Collection类的key是collection,List对象更加精确为list。数组为array

#{}和${}的区别

   相同点:都是有取值的作用

   不同点:#{}取值是以预编译的形式(即使用?占位符)将参数设置到sql语句中,底层使用PreparedStatement,可以防止sql注入

       ${}是将取出的值直接拼接到sql中,有安全性问题,所有开发绝大多数使用#{}

      但是因为原生sql不支持占位符的地方就需要使用${}将值直接拼上去,比如分表查询的表名,排序的字段名等

    6)resultType元素

        a。当查询出来是个list,resultType的值配置为list中存放的对象的类型

        b.当查询出来是个Map,resultType的值配置问Map。且需要在对应的接口方法上用@MapKey(“指定用哪个列的值来作为map key 的值”)来指定map可以的值

    7)resultMap元素/属性(resultMap属性和resultType属性只能使用其中一个)用来自定义数据库字段和java bean属性的映射规则,自定定义的字段安装自定义的规则,其他的字段安装mybatis的默认规则(名字一一对应),即使是这样,还是建议只要使用resultMap元素,就将所有的字段规则都写上,不管是否属于默认规则就可以完成的,方便后续维护

    8)关联对象映射

       a。多对一/一对一关系:

           映射关联方法有:

              嵌套结果集(一条sql语句查出所有对象):

                第一种的方式通过resultMap中<result>元素采用级联属性的方式关联

                第二种通过association元素来针对1方字段进行映射,,javaType属性指定映射的类型(推荐)

              分步查询(先查出n方对象,然后再用关联的字段值再发送一条sql去查询1方数据):

                使用association元素的基础上,去掉javaType属性,新增select属性指明已经配置好的用来查找1方的sql的唯一id,在新增column属性指明关联的字段名(这个时候不需要使用javaType属性,因为select属性指定的sql已经在它的配置中配置好了)

              以上查询都是立即查询出所有信息,如果要使用延迟加载机制需要在使用分步查询的基础上,在全局配置文件中添加配置 <setting name="lazyLoadingEnabled" value="true"/>配置即可(这个和hibernate差不多),在此基础上可以使用消极延迟加载(hibernate中的增加延迟加载)需要配置<setting name="aggressiveLazyLoading" value="true"/>即可

      b。一对多关系:

            映射的方法有:

              嵌套结果集的方式:

                使用resultMap元素的子元素collection来配置n方,这个时候要通过ofType属性指明n方的类型(即域模型中list中存放的对象类型)

              分步查询:

                同样的在在collection元素上去掉ofType属性,新增select属性指明查询n方的已经配置好的sql的唯一id,同时新增column属性用来指明查询n方需要的1方提供的字段名          

              延迟加载的方法同上

        association和collection元素都有fetchType属性,默认值为lazy表示延迟加载(在全局配置文件设置延迟加载的前提下)。如果想要变成立即加载,改变值为eager即可   

        俩表关联的时候有可能有多个字段,这个时候column的值设置为Map类型,比如column = “{deptId=dId,DeptName = dName}”

      8)可以通过resultMap元素的子元素discriminator 来实现按照指定字段的值实现switch...case..的逻辑来动态改变封装的类型规则:

<discriminator javaType="" column="">
<case value="">
</case>
</discriminator>

动态sql相关

     比如<where> (用于动态拼接条件,自动去掉第一个多余的and)<if> <set>(用于动态拼接更新字段,自动去掉最后以后逗号)<bind name="" value=""/>(用来给指定的值绑定得到一个变量中,方便其他元素中引用该值),其中的条件比如if元素的test属性中是采用ognl表达式来表示的。这些元素是那些具有填写sql的元素的子元素,比如select元素,update元素,sql元素

    foreach可以实现批量插入数据的功能

mysql支持inset  into 表 ()values(),(),()的方式,oracle不支持,oracle支持将多个insert into 语句放入begin和end之间的形式以及通过中间表插入的形式

<include refid=""></include>标签和<sql id=""></sql>标标签一起使用可以抽出重复的sql片段 ;include元素用来引用外部定义的sql语句,还可以自定义属性,采用property元素,取值采用${}不能使用#{}(占位符),sql定义重复的sql片段

mybatis的俩个内置参数:

    1)_databaseId(在配置了数据库别名的情况看下有值)和_parameter(表示传递进来的参数)。这俩个参数配置if标签一起使用,可以实现夸数据库的sql语句只写一条就可以,以及一些参数的控制

mybatis缓存机制相关

     1)一级缓存同样是SqlSession的,默认开启一级缓存,当俩次查询中间有增删改(属性flushCache=true)找后,一级缓存就会失效即第二次查询会重写连接数据库;当调用SqlSession的cleanCache方法(只清空当前一级缓存数据,不清空二级缓存数据)清空缓存,一级缓存也会失效

     2)mybatis的二级缓存是基于namespace级别的缓存(这个和hibernate的基于sessionFactory级别的缓存还是有很大差别的),一个namespace(接口编程中表示为接口的全名)对应一个缓存,即不同接口查询出的相同数据其实是放在各自的缓存区域(注意只有在sqlsession提交或者关闭后,数据才会重一级缓存迁移到二级缓存中)

      执行完增删改后,二级缓存的数据也会被清空,第二次查询时会重写发送sql语句

     开启二级缓存的步骤为,现在全局配置文件中<setting name="cacheEnabled" value="true"/>配置开启二级缓存,然后在针对每一个namespace开启二级缓存即在对应的配置文件中添加   <cache></cache>元素,同时通过该元素的属性,为缓存配置对应的缓存策略;同时可以通过select元素的useCache属性来指定该selet是否使用二级缓存

      update,delete,insert的属性flushCache=true:一级缓存和二级缓存都会被情况;select的属性falushCache=false

      关闭一级缓存的方法只有:设置对应元素的flushCache=false,一级在全局配置文件中配置localCacheScope=Statement(了解即可,基本上不会关闭一级缓存)

使用缓存后查询数据的顺序是:先看二级缓存中有没有数据,没有再看一级缓存是否有数据,没有最后才连接数据库

  <cache>元素的readOnly=true时表示mybatis相信用户拿到数据不会修改数据,直接将缓存中对象的引用交给用户,不安全,但是是速度快;readOnly=false时,mybatis会利用序列化和反序列化技术克隆一个对象交给用户,速度稍慢,但是安全(要求需要放入二级缓存的对象必须实现Serializable接口)

原文地址:https://www.cnblogs.com/wanjn/p/7582085.html