MyBatis学习笔记

持久层框架,将接口和java的pojo映射成数据库中的记录。

目录:
         1.简介
         2.xml配置
               2.1     properties
               2.2     settings
               2.3     typeAliases
               2.4     typeHandlers
               2.5     objectFactory
               2.6     plugins
               2.7     environments
               2.9     databasedProvider
               2.10   mappers
         3.mapper配置
         4.动态Sql



1. 简介
           1. pom.xml
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>
2.以SqlSessionFactory的实例为中心
     SqlSessionFactoryBuilder从xml或者Configuration实例中构建出SqlSessionFactory实例。
3.xml中包含DataSource,事务作用域,事务管理器TransactionManager,mappers。
4.SqlSession session = sqlSessionFactory.openSession();
5.作用域
SqlSessionFactoryBuilder     方法(局部变量)     释放对资源文件的占用
SqlSessionFactory            应用(单例、静态单例)
SqlSession                       请求、方法(不是线程安全的,不能被共享) 不能SqlSession实例引用放在一个类的静态域,也不能放在一个类的实例变量,应该跟http请求在一个域,每次结束之后需要确认关闭session。
2.xml配置<configuration>  
    1. properties属性      设置的属性可以在整个配置文件中使用${username}
      1. <properties resource="com/emar/example/config.properties">
        1. <property name="" value=""/>
      2. </properties>
      3. 如果配置加载在多个文件中,加载顺序如下:
        1. properties元素
        2. properties中指定的resource文件
        3. SqlSessionFactoryBuilder.build(reader,props)方法参数传进来的
      4. (后面的会覆盖前面的同名属性)
      5. 在Mybatis3.4.2之后支持设置默认值
        1. //设置开启默认值(此属性默认是关闭的)
        2. <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
        3. //指定属性和默认值的分隔符,默认是:
          <property   name = "org.apache.ibatis.parsing.PropertyParser.default-value-separator"   value = "?:" />
        4. <property name="username" value="${username?:ut_user}"/>
    2.      settings设置, 用于改变mybatis的运行时行为
      1. <settings>
         
        <setting name="cacheEnabled" value="true"/>   缓存全局开关
         
        <setting name="lazyLoadingEnabled" value="false"/> 延迟加载,特定关联关系用fetchType覆盖此设置
          <setting name="
        aggressiveLazyLoading " value="false"/>   每次调用都加载对象所有属性,3.4.2之前默认是true                                                  
      2. <setting name="multipleResultSetsEnabled" value="false"/> 允许单一语句返回多结果集                                              
         
        <setting name="useColumnLabel" value="true"/> 类标签代替列名
         
        <setting name="useGeneratedKeys" value="false"/> 允许jdbc支持自动生成主键
         
        <setting name="autoMappingBehavior" value="PARTIAL"/> NONE取消自动映射PARTIAL自动映射没定义嵌套结果集的 FULL自动映射
         
        <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> 发现自动映射未知列:NONE 没反应 WARN提醒日志 FAILING 映射失败(SqlSessionException)
         
        <setting name="defaultExecutorType" value="SIMPLE"/>SIMPLE普通执行器;REUSE使用prepared statement;Batch批量更新
         
        <setting name="defaultStatementTimeout" value="25"/>驱动等待db响应的秒数
         
        <setting name="defaultFetchSize" value="100"/>
         
        <setting name="safeRowBoundsEnabled" value="false"/> false允许嵌套中使用分页
      3.    <setting name=" safeResultHandlerEnabled " value="false"/> false允许嵌套中使用分页
         
        <setting name="mapUnderscoreToCamelCase" value="false"/> 开启自动驼峰命名规则映射
         
        <setting name="localCacheScope" value="SESSION"/> myBatis通过LocalCache加速重复嵌套查询:SESSION缓存一个会话的所有查询;STATEMENT仅缓存语句执行过程中的

         
        <setting name="jdbcTypeForNull" value="OTHER"/> NULL/VARCAHR/OTHER未空值设置JDBC类型
         
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> 针对指定方法触发延迟加载 </settings>
    3.      typeAliases类型命名,
      1. 为xml配置中的java类型设置短名字
        <typeAlias   alias = "Author"   type = "domain.blog.Author" />
      2. 设置包名
        <package   name = "domain.blog" />
      3. 按照设置的包名去下面找@Alias("author")注解的类,没有注解的类使用Bean的首字母小写作为别名。
    4.      typeHandlers类型处理器
      1. mybatis直到语句被执行了才清楚数据类型,所以必须在参数和结果映射中指定字段类型。
      2. 自定义类型处理器 MyTypeHandler
        1. @MappedJdbcTypes(JdbcType.VARCHAR)    指定jdbc中的类型(优先)
        2. <typeHandler handler="com.emar.example.MyTypeHandler" jdbcType="VARCHAR"/>
        3. MyTypeHandler extends BaseTypeHandler<String>  将覆盖原有String和VARCHAR的映射器
        4. <typeHandlers><typeHandler handler="com.emar.example.MyTypeHandler"/></typeHandlers>
        5. @MappedTypes("String")指定java类型(优先)
        6. <typeHandler handler="com.emar.example.MyTypeHandler" javaType="String"/>
      3. EnumTypeHandler(名字)和EnumOrdinalTypeHandler(值)都是泛型类型处理器
        public class GenericTypeHandler < extends   MyObject >   extends   BaseTypeHandler < E >
        1. EnumTypeHandler比较特别,它会处理所有继承了Enum的类     
    5. objectFactory对象工厂  (每次创建结果对象的新实例时,使用ObjectFactory的实例完成)
      1. <objectFactory   type = "org.mybatis.example.ExampleObjectFactory" >
         
        <property   name = "someProperty"   value = "100" /> </objectFactory>
      2. 自定义ObjectFactory
      3. public class ExampleObjectFactory extends DefaultObjectFactory 
    6.      plugins插件(暂时不考虑)
    7.      environments环境(可配置多个环境,但每个SqlSessionFactory实例只能选择一个environment,比如:如果2个db则2个SqlSessionFactory对应)
      1. <environments default="development"> 默认的环境ID
         
        <environment id="development">
           
        <transactionManager type="JDBC"> 2种事务管理器:JDBC和MANAGED(容器来管,默认会关闭连接
        <property   name = "closeConnection"   value = "false" />则不关闭连接
        )
             
        <property name="..." value="..."/>
           
        </transactionManager>
           
        <dataSource type="POOLED">数据源类型:UNPOOLED每次请求时打开和关闭连接;POOLED将jdbc连接对象组织起来,避免创建连接时必须的初始化和认证时间;JNDI为了在容器中使用,可引用外部定义的数据源
             
        <property name="driver" value="${driver}"/>
             
        <property name="url" value="${url}"/>
             
        <property name="username" value="${username}"/>
             
        <property name="password" value="${password}"/>
           
        </dataSource>
         
        </environment></environments>
      2.           environment环境变量
      3.           transactionManager事务管理器
      4.           dataSource数据源
    8.      databasedProvider数据库厂商标示 (可根据不同db执行不同语句,基于映射中databaseId属性)
      1. <databaseIdProvider   type = "DB_VENDOR"   />
      2. <databaseIdProvider   type = "DB_VENDOR" >
         
        <property   name = "SQL Server"   value = "sqlserver" />
         
        <property   name = "DB2"   value = "db2" />        
         
        <property   name = "Oracle"   value = "oracle"   /> </databaseIdProvider>
    9.      mappsers映射器<mappers></mappers>
      1. 类路径:<mapper   resource = "org/mybatis/builder/AuthorMapper.xml" />
      2. 文件路径:<mapper   url = "file:///var/mappers/AuthorMapper.xml" />
      3. 内部类路径:<mapper   class = "org.mybatis.builder.AuthorMapper" />
      4. 包:<package   name = "org.mybatis.builder" />
3.mapper映射配置
     <cache/>开启二级缓存
<cache
  eviction = "FIFO"  LRU(默认)移除最长时间不用的;FIFO先进先出;SOFT软引用;WEAK弱引用
  flushInterval = "60000" 刷新时间,毫秒
  size = "512"          引用数目。默认1024
  readOnly = "true" />

  • 映射语句文件中的所有 select 语句将会被缓存。
  • 映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。
  • 缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。
  • 根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
  • 缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
  • 缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
     查询:
<select
 id="selectPerson"   在命名空间中唯一
 parameterType="int" 可选,参数类;可根据TypeHandler推断
 parameterMap="deprecated" 废弃,使用内联参数映射和paramerType属性
 resultType="hashmap"    返回对象,如果是集合,应该是集合包含的类型
 resultMap="personResultMap" 引用外部resultMap,和resultType只能有一个
 flushCache="false" true表示只要调用,都会清空本地缓存和二级缓存
 
useCache="true" true表示本条结果被二级缓存
 
timeout="10000"  驱动程序等待db的秒数
 fetchSize="256"  尝试影响驱动程序每次批量返回的行数
 statementType="PREPARED" STATEMENT,PREPARED(默认PreparedStatement),CALLLABLE(CallableStatement)
 resultSetType="FORWARD_ONLY" FORWARD_ONLY,SCROLL_SENSITIVE,SCORLL_INSENSITIVE
         修改:
<insert
 
id = "insertAuthor"
 
parameterType = "domain.blog.Author"
 
flushCache = "true"
  statementType = "PREPARED"
  keyProperty = ""  仅对insert和update有用,通过getGeneratedKeys或是selectKey设置
  keyColumn = ""    仅对insert和update有用,通过生成键值设置表中列名
 
useGeneratedKeys = "" 仅对insert和update有用,使mybatis使用jdbc的getGeneratedKeys从db取出生成的主键
 
timeout = "20" >

<update
 
id = "updateAuthor"
 
parameterType = "domain.blog.Author"
 
flushCache = "true"
 
statementType = "PREPARED"
 
timeout = "20" >

<delete
 
id = "deleteAuthor"
 
parameterType = "domain.blog.Author"
 
flushCache = "true"
 
statementType = "PREPARED"
  timeout = "20" >
插入:
     db生成id:
<insert   id = "insertAuthor"   useGeneratedKeys="true"
   
keyProperty="id" >
  insert into Author (username, password, email, bio) values
 
<foreach   item = "item"   collection = "list"   separator = "," >
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach> </insert>
     自定义id:
<insert   id = "insertAuthor" >
 
<selectKey keyProperty="id" resultType="int" order="BEFORE"
    select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
 
</selectKey>
  insert into Author
    (id, username, password, email,bio, favourite_section)
  values
    (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>
<selectKey>元素:keyProperty目标属性,keycolumn返回结果集中列名,order(BEFORE|AFTER)BEFORE会先选主键再插入。

Sql:重复使用
<sql   id = "userColumns" >  ${alias}.id,${alias}.username,${alias}.password  </sql>
<select   id = "selectUsers"   resultType = "map" >
  select
    <include   refid = "userColumns" >
          <property   name = "alias"   value = "t1" />这个t1还可以是sql元素的id
     </include> ,
    <include   refid = "userColumns" ><property   name = "alias"   value = "t2" />
</include>
  from some_table t1
    cross join some_table t2
</select>
参数:
1.简单#{age}
2.详细配置
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
3.小数(保留2位小数)
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
4.其他属性mode为OUT/INOUT时会改变原属性值,需要指定resultMap
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
5.不需要转义或修改的字符串
ORDER BY $ { columnName }
ResultMaps结果集:
当列名和属性名不一致时:
方法一:
<!-- In mybatis-config.xml file -->
<typeAlias type="com.someapp.model.User" alias="User"/>
<select   id = "selectUsers"   resultType = "User" >
  select
    user_id             as "id",
    user_name           as "userName",
    hashed_password     as "hashedPassword"
  from some_table
  where id = #{id}
</select>
或是
方法二:

<resultMap   id = "userResultMap"   type = "User" >
 
<id   property = "id"   column = "user_id"   />
 
<result   property = "username"   column = "user_name" />
 
<result   property = "password"   column = "hashed_password" /> </resultMap>
<select   id = "selectUsers"   resultMap = "userResultMap" >
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>
关联结果映射:
<!-- Very Complex Statement --> <select   id = "selectBlogDetails"   resultMap = "detailedBlogResultMap" >
  select
       B.id as blog_id,
       B.title as blog_title,
       B.author_id as blog_author_id,
       A.id as author_id,
       A.username as author_username,
       A.password as author_password,
       A.email as author_email,
       A.bio as author_bio,
       A.favourite_section as author_favourite_section,
       P.id as post_id,
       P.blog_id as post_blog_id,
       P.author_id as post_author_id,
       P.created_on as post_created_on,
       P.section as post_section,
       P.subject as post_subject,
       P.draft as draft,
       P.body as post_body,
       C.id as comment_id,
       C.post_id as comment_post_id,
       C.name as comment_name,
       C.comment as comment_text,
       T.id as tag_id,
       T.name as tag_name
  from Blog B
       left outer join Author A on B.author_id = A.id
       left outer join Post P on B.id = P.blog_id
       left outer join Comment C on P.id = C.post_id
       left outer join Post_Tag PT on PT.post_id = P.id
       left outer join Tag T on PT.tag_id = T.id
  where B.id = #{id}
</select>
<!-- Very Complex Result Map -->
<resultMap   id = "detailedBlogResultMap"   type = "Blog"  > autoMapping开启自动映射,覆盖全局autoMappingBehavior
  <constructor>   类的构造方法:idArg 和 arg
    <idArg   column = "blog_id"   javaType = "int" />                       B.id
  </constructor>
  <result   property = "title"   column = "blog_title" />                   B.title
  <association   property = "author"   javaType = "Author" >  association类型关联              B.author_id=A.id
    <id   property = "id"   column = "author_id" />                         A.id
    <result   property = "username"   column = "author_username" />         A.username
    <result   property = "password"   column = "author_password" />         A.password
    <result   property = "email"   column = "author_email" />               A.email
    <result   property = "bio"   column = "author_bio" />                   A.bio
    <result   property = "favouriteSection"   column = "author_favourite_section" />A.favouriteSection
  </association>
  <collection   property = "posts"   ofType = "Post" >    List<Post>                 P.blog_id=B.id
    <id   property = "id"   column = "post_id" />                           P.id
    <result   property = "subject"   column = "post_subject" />             P.subject
    <association   property = "author"   javaType = "Author" />             P.author_id
    <collection   property = "comments"   ofType = "Comment" >              C.post-id=P.id  
      <id   property = "id"   column = "comment_id" />                   
    </collection>
    <collection   property = "tags"   ofType = "Tag"   >                     PT.post_id=P.id and                                                                PT.tag_id=T.id
      <id   property = "id"   column = "tag_id" />
    </collection>
    <discriminator   javaType = "int"   column = "draft" >  鉴别器,类似于switch             
      <case   value = "1"   resultType = "DraftPost" />
    </discriminator>
  </collection> </resultMap>
嵌套查询:
<resultMap   id = "blogResult"   type = "Blog" >
     column="{prop1=col1,prop2=col2}"
  <association   property = "author"   column = "author_id"   javaType = "Author"   select = "selectAuthor" /> </resultMap>

<select   id = "selectBlog"   resultMap = "blogResult" >
  SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select   id = "selectAuthor"   resultType = "Author" >
  SELECT * FROM AUTHOR WHERE ID = #{id}
</select>
嵌套结果:
select B.id,B.title,B.author_id,A.id,A.username,A.password,A.email,A.bio
from Blog B left outer join Author A on B.author_id=A.id
left outer join Author CA on B.co_author_id=CA.id
where B.id=#{id}
<resultMap   id = "blogResult"   type = "Blog" >
 
<id   property = "id"   column = "blog_id"   />
 
<result   property = "title"   column = "blog_title" />
 
<association   property = "author"   column = "blog_author_id"   javaType = "Author"   resultMap = "authorResult" /> </resultMap>

<resultMap   id = "authorResult"   type = "Author" >
 
<id   property = "id"   column = "author_id" />
 
<result   property = "username"   column = "author_username" />
 
<result   property = "password"   column = "author_password" />
 
<result   property = "email"   column = "author_email" />
  <result   property = "bio"   column = "author_bio" /> </resultMap>
如果Blog中还有co_author_id联合作者的话,可如下配置
select B.id,B.title,B.author_id,A.id,A.username,A.password,A.email,A.bio
from Blog B left outer join Author A on B.author_id=A.id
where B.id=#{id}
<resultMap   id = "blogResult"   type = "Blog" >
 
<id   property = "id"   column = "blog_id"   />
 
<result   property = "title"   column = "blog_title" />
 
<association   property = "author"
   
resultMap = "authorResult"   />
 
<association   property = "coAuthor"
   
resultMap = "authorResult"
   
columnPrefix = "co_"   /> </resultMap>
4.动态SQL
     if:
<if   test = "title != null" ></if>
     choose:
<select   id = "findActiveBlogLike"
     
resultType = "Blog" >
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
 
<choose>
   
<when   test = "title != null" >
      AND title like #{title}
   
</when>
   
<when   test = "author != null and author.name != null" >
      AND author_name like #{author.name}
   
</when>
   
<otherwise>
      AND featured = 1
   
</otherwise>
 
</choose> </select>
     trim:
<trim   prefix = "WHERE"   prefixOverrides = "AND |OR " >
  ... 
</trim>
<trim   prefix = "SET"   suffixOverrides = "," >
  ...
</trim>
     foreach:
<select   id = "selectPostIn"   resultType = "domain.blog.Post" >
  SELECT *
  FROM POST P
  WHERE ID in
 
<foreach   item = "item"   index = "index"   collection = "list"
     
open = "("   separator = ","   close = ")" >
        #{item}
 
</foreach> </select>
     bind:
<select   id = "selectBlogsLike"   resultType = "Blog" >
 
<bind   name = "pattern"   value = "'%' + _parameter.getTitle() + '%'"   />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>






附录:配置Mapper映射的方式:
方法一:代码中注解
package  org . mybatis . example ; public   interface   BlogMapper   {
 
@Select ( "SELECT * FROM blog WHERE id = #{id}" )
 
Blog  selectBlog ( int  id ); }
方法二: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 = "org.mybatis.example.BlogMapper" >
  <select   id = "selectBlog"   resultType = "Blog" >
    select * from Blog where id = #{id}
 
</select> </mapper>




附录:加载SqlSessionFactory的两种方式:
方法一:代码加载
DataSource  dataSource  =   BlogDataSourceFactory . getBlogDataSource ();
TransactionFactory  transactionFactory  =   new   JdbcTransactionFactory ();
Environment  environment  =   new   Environment ( "development" ,  transactionFactory ,  dataSource );
Configuration  configuration  =   new   Configuration ( environment );
configuration . addMapper ( BlogMapper . class );
SqlSessionFactory  sqlSessionFactory  =   new   SqlSessionFactoryBuilder (). build ( configuration );
方法二:xml加载
<? xml version = "1.0"  encoding = "UTF-8"   ?> <!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
 
<environments   default = "development" >
   
<environment   id = "development" >
     
<transactionManager   type = "JDBC" />
     
<dataSource   type = "POOLED" >
       
<property   name = "driver"   value = "${driver}" />
       
<property   name = "url"   value = "${url}" />
       
<property   name = "username"   value = "${username}" />
       
<property   name = "password"   value = "${password}" />
     
</dataSource>
   
</environment>
 
</environments>
 
<mappers>
   
<mapper   resource = "org/mybatis/example/BlogMapper.xml" />
 
</mappers> </configuration>
String  resource  =   "org/mybatis/example/mybatis-config.xml" ;
InputStream  inputStream  =   Resources . getResourceAsStream ( resource );
SqlSessionFactory  sqlSessionFactory  =   new   SqlSessionFactoryBuilder (). build ( inputStream );  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值