Mybatis使用总结

一.最基本的配置文件

<?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>

二.生命周期与作用域

一次请求对应一个Session,如果在一次请求中多次从SessionFactory打开Session是一种浪费(虽然有连接池不至于重新建立连接,但函数调用过程也是一种损耗)。

不要在多个线程中访问同一个Session,SqlSession与一次请求是一对一的关系。

三.更改

要考虑更改,当更改一个地方时,是不是要更改好多个地方,是不是需要自己费力的去找并且一旦遗漏一处就会导致运行时错误。不论做何种事,不要觉得它现在很美观,很漂亮简洁,要使它易维护,易更改,而更改之后依旧能维持开始的美观状态。

如果修改了resultType中的类名并且不想费力的全改掉,那就可以使用typeAliases

类型处理器必不可少,然而不要自己去碰它,因为系统把常用的基本数据类型都给封装好了,尽量使用简单的类型,把复杂的转化和控制放到java代码中去。比如,不要在数据库定义中使用数据库的日期时间类型,因为日期时间在不同语言中大大不同,而long这种类型十分通用.

不要使用枚举类型,用数字来代替,不仅简单,而且不会出错,而且便于交流。

四.映射器三种注册方式

Mybatis中注册映射器有三种方式:Xml,Class,Url

<!-- Using classpath relative resources -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- Using url fully qualified paths -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- Using mapper interface classes -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

把一个包下的全部接口都注册

<!-- Register all interfaces in a package as mappers -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

要注册最原始的那一个!如果写了xml及其对应的封装接口,那么应该注册xml;如果通过注解+接口方式实现,那么需要注册class。

五.增删改示例

<insert id="insertAuthor">
  insert into Author (id,username,password,email,bio)
  values (#{id},#{username},#{password},#{email},#{bio})
</insert>

<update id="updateAuthor"> update Author set username = #{username}, password = #{password}, email = #{email}, bio = #{bio} where id = #{id} </update> <delete id="deleteAuthor"> delete from Author where id = #{id} </delete>

在这三中涉及到更改数据库的行为中,insert变化最多:

使用自动生成主键

首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就OK了。例如,如果上面的 Author 表已经对 id 使用了自动生成的列类型,那么语句可以修改为:

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>

         经验告诉我,主键生成的权力还是要牢牢掌握在Java手中,不要让数据库自动生成主键,因为有些数据库不支持自增长类型的主键.对于主键的处理不同数据库各有差异,经验就是,使用UUID作为主键,通过代码来生成.

多行插入

实际上foreach标签相当于产生一个字符串,需要规定好字符串之间的间隔符号

<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>

自定义主键

允许在插入主键时,先执行一次查询语句:

<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>

六. Sql+include语句

Sql+include相当于简单的文本复制粘贴,include还可以通过property给sql标签传参数

<sql id="sometable">
  ${prefix}Table</sql>
<sql id="someinclude">
  from
    <include refid="${include_target}"/></sql>
<select id="select" resultType="map">
  select
    field1, field2, field3
  <include refid="someinclude">
    <property name="prefix" value="Some"/>
    <property name="include_target" value="sometable"/>
  </include></select>

七.#{}和${}

#{}是值代入,${}相当于字符串替换.默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值(比如?)。这样做更安全,更迅速,通常也是首选做法,不过有时你只是想直接在 SQL 语句中插入一个不改变的字符串。比如,像 ORDER BY,你可以这样来使用:

ORDER BY ${columnName}

这里 MyBatis 不会修改或转义字符串。

NOTE 以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。

八.高级结果映射:会这一个就足够了

一个博客Blog,用B表示,它的作者Author是A,博客中有很多篇博文Post,用P表示,博文下面有很多评论Comment,用C表示.博文有很多标签Tag,用T表示.于是就有了BlogDetails这个VO,它包括Blog,Author,Post,Comment,Tag五个实体的属性.也就是说,传入一个参数BlogId,返回关于这个博客的所有信息,这是一个树形结构的信息.

<!-- 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>

这个查询语句的resultMap可以这么写

<!-- Very Complex Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="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"/>
    <result property="favouriteSection" column="author_favourite_section"/>
  </association>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection></resultMap>

九.id & result

id&result是结果集映射中常用的标签,例如

<id property="id" column="post_id"/>

<result property="subject" column="post_subject"/>

id 和 result 都映射一个单独列的值到简单数据类型(字符串,整型,双精度浮点数,日期等)的单独属性或字段。这两者之间唯一不同是 id 表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射) 。

十.动态Sql

动态Sql之if

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

动态Sql之switch

<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>

Mybatis主要功能是结果集映射,附加功能【动态sql】+【sql语句构建器】

十一.动态Sql之trim

where和set相当于trim的另一种写法,trim就是简单的字符串处理。

where是trim在查询语句select中的用法

set是trim在更新语句update中的用法

trim可以设定prefix和sufix作为前缀和后缀,还可以prefixOverride和sufixOverride擦除某种前缀和后缀。擦除前缀后缀时,可以使用“|”作为或符号,如and|or

十二.bind元素

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

如果只有一个参数,无需使用@Param()注解

你可以传递多个参数给一个映射器方法。 如果你这样做了, 默认情况下它们将会以它们 在参数列表中的位置来命名,比如:#{param1},#{param2}等。如果你想改变参数的名称(只在多参数 情况下) ,那么你可以在参数上使用@Param(“paramName”)注解.

原文地址:https://www.cnblogs.com/weiyinfu/p/5824438.html