Mybatis (three) configure the basic operation of mapper.xml

Reference: https://www.cnblogs.com/wuzhenzhao/p/11101555.html

XML mapping file

  This article refers to mybatis Chinese official website for learning summary: http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

  The real power of MyBatis lies in its mapping statement, which is its magic. Due to its exceptional power, the XML file of the mapper is relatively simple. If you compare it with the JDBC code with the same function, you will immediately find that almost 95% of the code is saved. MyBatis is built to focus on SQL to reduce the trouble for you as much as possible.

  The SQL mapping file has only a few top-level elements (listed in the order they should be defined):

  • cache  -cache configuration for a given namespace.
  • cache-ref  -a reference to the cache configuration of other namespaces.
  • resultMap  -is the most complex and powerful element used to describe how to load objects from the database result set.
  • sql  -reusable statement blocks that can be referenced by other statements.
  • insert  – map insert statement
  • update  -map update statement
  • delete  – map delete statement
  • select  -map query statement

select

  Query statements are one of the most commonly used elements in MyBatis. Light energy is not of great value for storing data in a database. It is only useful if it can be retrieved again. Most applications are also more frequent than modified. For each insert, update or delete operation, there are usually multiple query operations at intervals. This is one of the basic principles of MyBatis, and it is also the reason why the focus and effort are placed on query and result mapping. The select element of a simple query is very simple. such as:

Copy code
<resultMap id="BaseResultMap" type="blog">
     <id column="bid" property="bid" jdbcType="INTEGER"/>
     <result column="name" property="name" jdbcType="VARCHAR"/>
     <result column="author_id" property="authorId" jdbcType="INTEGER"/>
</resultMap>
<!--****************************************************************************************-->
<!--简单查询-->
<select id="selectBlogById" resultMap="BaseResultMap" statementType="PREPARED" useCache="false">
     select * from blog where bid = #{bid}
</select>
Copy code

  # {bid} This tells MyBatis to create a prepared statement (PreparedStatement) parameter. In JDBC, such a parameter is identified by a "?" in SQL and passed to a new prepared statement, like this:

// Approximate JDBC code, not MyBatis code ... 
String selectBlogById = "SELECT * FROM BLOG WHERE BID =?"; 
PreparedStatement ps = conn.prepareStatement ( selectBlogById); 
ps.setInt (1, bid);

  Of course, using JDBC means that more code is needed to extract the results and map them to the object instance, and this is where MyBatis saves you time. The select element allows you to configure many attributes to configure the details of each statement.

Copy code
<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">
Copy code

   Related attribute description:

Attributes description
id A unique identifier in the namespace can be used to refer to this statement.
parameterType The fully qualified name or alias of the parameter class that will be passed into this statement. This attribute is optional because MyBatis can infer the parameters of the specific incoming statement through the TypeHandler. The default value is unset.
parameterMap This is a deprecated method of referencing external parameterMap. Please use inline parameter mapping and parameterType attribute.
resultType The fully qualified name or alias of the class of the desired type returned from this statement. Note that if a collection is returned, it should be set to the type contained in the collection, not the collection itself. You can use resultType or resultMap, but not both.
resultMap Named reference to external resultMap. The mapping of the result set is the most powerful feature of MyBatis. If you understand it thoroughly, many complex mapping situations can be solved. You can use resultMap or resultType, but not both.
flushCache After setting it to true, as long as the statement is called, it will cause the local cache and the secondary cache to be cleared. The default value is false.
useCache Setting it to true will cause the result of this statement to be cached by the second-level cache. The default value is true for the select element.
timeout This setting is the number of seconds the driver waits for the database to return the request result before throwing an exception. The default value is unset (drive dependent).
fetchSize This is a prompt for the driver. Try to make the number of result rows returned by the driver in batches equal to this setting value. The default value is unset (drive dependent).
statementType One of STATEMENT, PREPARED or CALLABLE. This will cause MyBatis to use Statement, PreparedStatement or CallableStatement respectively, the default value is PREPARED.
resultSetType One of FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE or DEFAULT (equivalent to unset), the default value is unset (drive-dependent).
databaseId If the database vendor ID (databaseIdProvider) is configured, MyBatis will load all statements without databaseId or matching the current databaseId; if there are statements with or without, the statements without or without them will be ignored.
resultOrdered This setting applies only to nested result select statements: if true, it is assumed that a nested result set or group is included, so that when a main result row is returned, no reference to the previous result set will occur Happening. This will not cause insufficient memory when fetching nested result sets. Default value: false .
resultSets This setting is only applicable to multiple result sets. It will list the result sets returned after the statement is executed and give each result set a name, the names are separated by commas.

 insert, update 和 delete:

  The implementation of the data change statements insert, update and delete are very close:

Copy code
<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  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">
Copy code

   Related attribute description:

Attributes description
id The unique identifier in the namespace can be used to represent this statement.
parameterType The fully qualified class name or alias of the parameter that will be passed into the statement. This attribute is optional because MyBatis can infer the parameters of the specific incoming statement through the type processor. The default value is unset.
parameterMap This is a deprecated method of referencing external parameterMap. Please use inline parameter mapping and parameterType attribute.
flushCache After it is set to true, as long as the statement is called, the local cache and the second-level cache will be cleared. The default value is true (for insert, update, and delete statements).
timeout This setting is the number of seconds the driver waits for the database to return the request result before throwing an exception. The default value is unset (drive dependent).
statementType STATEMENT, PREPARED or CALLABLE. This will cause MyBatis to use Statement, PreparedStatement or CallableStatement respectively, the default value is PREPARED.
useGeneratedKeys (Only useful for insert and update) This will cause MyBatis to use JDBC's getGeneratedKeys method to retrieve the primary key generated inside the database (for example: auto-increment fields in relational database management systems like MySQL and SQL Server), default value: false.
keyProperty (Only useful for insert and update) Only mark an attribute, MyBatis will set its key value through the return value of getGeneratedKeys or through the selectKey sub-element of the insert statement, the default value: unset ( unset ). If you want to get multiple generated columns, it can also be a comma-separated list of attribute names.
keyColumn (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。
databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

下面就是 insert,update 和 delete 语句的示例:

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

  如前所述,插入语句的配置规则更加丰富,在插入语句里面有一些额外的属性和子元素用来处理主键的生成,而且有多种生成方式。首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就 OK 了。如果你的数据库还支持多行插入, 你也可以传入一个 Blog数组或集合,并返回自动生成的主键。

Copy code
<!--批量插入-->
<insert id="insertBlogs" useGeneratedKeys="true"
            keyProperty="bid">
     insert into blog (name, author_id) values
     <foreach item="item" collection="list" separator=",">
         (#{item.name}, #{item.authorId})
     </foreach>
</insert>
Copy code

sql

  这个元素可以被用来定义可重用的 SQL 代码段,这些 SQL 代码可以被包含在其他语句中。它可以(在加载的时候)被静态地设置参数。 在不同的包含语句中可以设置不同的值到参数占位符上。mybatis中sql标签与include标签进行配合,灵活的查询需要的数据。

Copy code
<sql id="ref">
    bid,name,authorId
</sql>

<select id="selectbyId" resultMap="BaseResultMap">
    select
    <include refid="ref"/>
    from
    blog where bid = #{bid}
</select>
Copy code

  sql标签中id属性对应include标签中的refid属性。通过include标签将sql片段和原sql片段进行拼接成一个完成的sql语句进行执行。include标签中还可以用property标签,用以指定自定义属性。

Copy code
<select id="selectbyId" resultMap="BaseResultMap">
    select
    <include refid="ref">
        <property name="abc" value="bid"/>
    </include>
    from
    blog where bid = #{bid}
</select>
Copy code

  此时,可以在sql标签中取出对应设置的自定义属性中的值,例如接上代码例子:

Copy code
<sql id="ref">
    ${abc},name,authorId
</sql>

<select id="selectbyId" resultMap="BaseResultMap">
    select
    <include refid="ref">
        <property name="abc" value="bid"/>
    </include>
    from
    blog where bid = #{bid}
</select>
Copy code

   在sql标签中通过${}取出对应include标签中设置的属性值。

  关联(association)元素处理“有一个”类型的关系。 比如,在我们的示例中,一个博客有一个用户。关联结果映射和其它类型的映射工作方式差不多。 你需要指定目标属性名以及属性的javaType(很多时候 MyBatis 可以自己推断出来),在必要的情况下你还可以设置 JDBC 类型,如果你想覆盖获取结果值的过程,还可以设置类型处理器。关联的不同之处是,你需要告诉 MyBatis 如何加载关联。MyBatis 有两种不同的方式加载关联:

  • 嵌套 Select 查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。
  • 嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。

关联的嵌套 Select 查询

Copy code
<!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题 -->
    <resultMap id="BlogWithAuthorQueryMap" type="com.wuzz.demo.associate.BlogAndAuthor">
        <id column="bid" property="bid" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <association property="author" javaType="com.wuzz.demo.entity.Author"
                     column="author_id" select="selectAuthor"/>
    </resultMap>

    <!-- 嵌套查询 -->
    <select id="selectAuthor" parameterType="int" resultType="com.wuzz.demo.entity.Author">
        select author_id authorId, author_name authorName
        from author where author_id = #{authorId}
    </select>

    <!-- 根据文章查询作者,一对一,嵌套查询,存在N+1问题,可通过开启延迟加载解决 -->
    <select id="selectBlogWithAuthorQuery" resultMap="BlogWithAuthorQueryMap" >
        select b.bid, b.name, b.author_id, a.author_id , a.author_name
        from blog b
        left join author a
        on b.author_id=a.author_id
        where b.bid = #{bid, jdbcType=INTEGER}
    </select>
Copy code

  就是这么简单。我们有两个 select 查询语句:一个用来加载博客(Blog),另外一个用来加载作者(Author),而且博客的结果映射描述了应该使用 selectAuthor 语句加载它的 author 属性。其它所有的属性将会被自动加载,只要它们的列名和属性名相匹配。这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的:

  • 你执行了一个单独的 SQL 语句来获取结果的一个列表(就是“+1”)。
  • 对列表返回的每条记录,你执行一个 select 查询语句来为每条记录加载详细信息(就是“N”)。

  这个问题会导致成百上千的 SQL 语句被执行。有时候,我们不希望产生这样的后果。MyBatis 能够对这样的查询进行延迟加载,因此可以将大量语句同时运行的开销分散开来。mybatis.configuration.lazy-loading-enabled=true 可以开启延时加载 mybatis.configuration.aggressive-lazy-loading=true 可以指定哪些方法调用查询, 然而,如果你加载记录列表之后立刻就遍历列表以获取嵌套的数据,就会触发所有的延迟加载查询,性能可能会变得很糟糕。所以还有另外一种方法。

关联的嵌套结果映射

Copy code
<!-- 根据文章查询作者,一对一查询的结果,嵌套查询 -->
    <resultMap id="BlogWithAuthorResultMap" type="com.wuzz.demo.associate.BlogAndAuthor">
        <id column="bid" property="bid" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <!-- 联合查询,将author的属性映射到ResultMap -->
        <association property="author" javaType="com.wuzz.demo.entity.Author">
            <id column="author_id" property="authorId"/>
            <result column="author_name" property="authorName"/>
        </association>
    </resultMap>
    <!-- 根据文章查询作者,一对一,嵌套结果,无N+1问题 -->
    <select id="selectBlogWithAuthorResult" resultMap="BlogWithAuthorResultMap" >
        select b.bid, b.name, b.author_id, a.author_id , a.author_name
        from blog b,author a
        where b.author_id=a.author_id and b.bid = #{bid, jdbcType=INTEGER}
    </select>
Copy code

   查询文章带评论的结果(一对多)映射:

Copy code
<!--  查询文章带评论的结果(一对多) -->
    <resultMap id="BlogWithCommentMap" type="com.wuzz.demo.associate.BlogAndComment" extends="BaseResultMap" >
        <collection property="comment" ofType="com.wuzz.demo.entity.Comment">
            <id column="comment_id" property="commentId" />
            <result column="content" property="content" />
            <result column="bid" property="bid" />
        </collection>
    </resultMap>
    <!-- 根据文章查询评论,一对多 -->
    <select id="selectBlogWithCommentById" resultMap="BlogWithCommentMap" >
        select b.bid, b.name, b.author_id , c.comment_id , c.content,c.bid
        from blog b, comment c
        where b.bid = c.bid
        and b.bid = #{bid}
    </select>
Copy code

  按作者查询文章评论的结果(多对多):

Copy code
<!--  按作者查询文章评论的结果(多对多) -->
    <resultMap id="AuthorWithBlogMap" type="com.wuzz.demo.associate.AuthorAndBlog" >
        <id column="author_id" property="authorId" jdbcType="INTEGER"/>
        <result column="author_name" property="authorName" jdbcType="VARCHAR"/>
        <collection property="blog" ofType="com.wuzz.demo.associate.BlogAndComment">
            <id column="bid" property="bid" />
            <result column="name" property="name" />
            <result column="author_id" property="authorId" />
            <collection property="comment" ofType="com.wuzz.demo.entity.Comment">
                <id column="comment_id" property="commentId" />
                <result column="content" property="content" />
                <result column="bid" property="bid" />
            </collection>
        </collection>
    </resultMap>

    <!-- 根据作者文章评论,多对多 -->
    <select id="selectAuthorWithBlog" resultMap="AuthorWithBlogMap" >
        select b.bid, b.name, a.author_id , a.author_name , c.comment_id , c.content,c.bid
        from blog b, author a, comment c
        where b.author_id = a.author_id and b.bid = c.bid
    </select>
Copy code

动态 SQL

  MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

  1. if
  2. choose (when, otherwise)
  3. trim (where, set)
  4. foreach

  其中  choose再实际开发中应用的较少,我们这里就其他3个标签进行测试

Copy code
<!--动态sql-->
    <select id="selectBlogById2" resultMap="BaseResultMap" statementType="PREPARED" useCache="false"
        parameterType="blog">
        select * from blog
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
            <if test="bid != null and bid !='' ">
                bid = #{bid}
            </if>
            <if test="name != null and name !='' ">
                AND name = #{name}
            </if>
            <if test="authorId != null and authorId != ''">
                AND author_id = #{author_id}
            </if>
        </trim>
    </select>
Copy code

   foreach: Another common operation requirement of dynamic SQL is to traverse a collection, usually when constructing IN conditional statements. such as:

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

Guess you like

Origin www.cnblogs.com/flgb/p/12688311.html