Springboot-Mybatis-进阶

数据库关系

ResultMap

ResultMap是Mybatis最强大的元素,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中。

一般的简单查询用ResultType即可,对于复杂的查询才需要使用ResultMap。

<resultMap id="唯一的标识" type="映射的pojo对象">
  <id column="表的主键字段,或者可以为查询语句中的别名字段"  property="映射pojo对象的主键属性" />
  <result column="表的一个字段(可以为任意表的一个字段)"  property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属性)"/>
  <association property="pojo的一个对象属性" javaType="pojo关联的pojo对象">
    <id column="关联pojo对象对应表的主键字段"  property="关联pojo对象的主席属性"/>
    <result  column="任意表的字段"  property="关联pojo对象的属性"/>
  </association>
  <!-- 集合中的property须为oftype定义的pojo对象的属性-->
  <collection property="pojo的集合属性" ofType="集合中的pojo对象">
    <id column="集合中pojo对象对应的表的主键字段"  property="集合中pojo对象的主键属性" />
    <result column="可以为任意表的字段"  property="集合中的pojo对象的属性" />  
  </collection>
</resultMap>

association

用于多对一的关系,即association包括只是一个对象。例如查询学生信息,一个学生只有一个老师

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Student implements Serializable {
    private Integer id;
    private String name;
    private Teacher teacher;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Teacher implements Serializable {
    private Integer id;
    private String name;
}
<?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="com.lexiaoyao.mybatisdemo.mapper.StudentMapper">
    <resultMap id="res" type="student">
        <result column="sid" property="id"></result>
        <result column="sname" property="name"></result>
        <!--        一对多采用association-->
        <association property="teacher" javaType="teacher">
            <result column="tid" property="id"></result>
            <result column="tname" property="name"></result>
        </association>
    </resultMap>

    <select id="listAll" resultMap="res">
        SELECT s.id sid,s.`name` sname,s.t_id sid,t.`name` tname,t.`id` tid
        FROM `student` s,`teacher` t
        WHERE s.t_id = t.id
    </select>
</mapper>

collection

是一对多的关系,ofType是集合中的范型类型,比如一个老师有多个学生


@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Student implements Serializable {
    private Integer id;
    private String name;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Teacher implements Serializable {
    private Integer id;
    private String name;
    private List<Student> students;
}
@Repository
public interface TeacherMapper {
    Teacher getById(@Param("id") Integer id);
}

<?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="com.lexiaoyao.mybatisdemo.mapper.TeacherMapper">

    <resultMap id="res" type="teacher">
        <result column="tname" property="name"></result>
        <result column="tid" property="id"></result>
        <collection property="students" ofType="student">
            <result column="sid" property="id"></result>
            <result column="sname" property="name"></result>
        </collection>
    </resultMap>

    <select id="getById" parameterType="int" resultMap="res">
        SELECT s.id sid,s.`name` sname,s.t_id sid,t.`name` tname,t.`id` tid
        FROM
        `student` s,`teacher` t
        WHERE
        s.t_id = t.id
        AND
        t.`id` = #{id}
    </select>

</mapper>

动态sql

if

如果有字段则加入sql

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog where
   <if test="title != null">
      title = #{title}
   </if>
   <if test="author != null">
      and author = #{author}
   </if>
</select>

where

这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <if test="title != null">
          title = #{title}
       </if>
       <if test="author != null">
          and author = #{author}
       </if>
   </where>
</select>

set

set能够处理进行update操作时,set时候多余的逗号处理

<update id="updateBlog" parameterType="map">
  update blog
     <set>
         <if test="title != null">
            title = #{title},
         </if>
         <if test="author != null">
            author = #{author}
         </if>
     </set>
  where id = #{id};
</update>

choose

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句
note只有一个条件触发

<select id="queryBlogChoose" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <choose>
           <when test="title != null">
                title = #{title}
           </when>
           <when test="author != null">
              and author = #{author}
           </when>
           <otherwise>
              and views = #{views}
           </otherwise>
       </choose>
   </where>
</select>

foreach

一般用于集合中遍历搜索

<select id="queryBlogForeach" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!--
       collection:指定输入对象中的集合属性
       item:每次遍历生成的对象
       open:开始遍历时的拼接字符串
       close:结束时拼接的字符串
       separator:遍历对象之间需要拼接的字符串
       select * from blog where 1=1 and (id=1 or id=2 or id=3)
     -->
       <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
          id=#{id}
       </foreach>
   </where>
</select>

缓存

一级缓存

mybatis的一级缓存是默认打开的,只在一个session内有效。
一级的缓存的使用价值不大,所以一般使用二级缓存

二级缓存

开启二级缓存

mybatis的二级缓存默认也是开启的,但是在使用的时候,一般手动显式开启。

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <setting name="cacheEnabled" value="true"/>
    </settings>

配置

直接在mapper中加入标签即可。

<?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="com.lexiaoyao.mybatisdemo.mapper.TeacherMapper">

    <cache eviction="FIFO" flushInterval="60000" size="512" type="true"></cache>
    <resultMap id="res" type="teacher">
        <result column="tname" property="name"></result>
        <result column="tid" property="id"></result>
        <collection property="students" ofType="student">
            <result column="sid" property="id"></result>
            <result column="sname" property="name"></result>
        </collection>
    </resultMap>

    <select id="getById" parameterType="int" resultMap="res">
        SELECT s.id sid,s.`name` sname,s.t_id sid,t.`name` tname,t.`id` tid
        FROM
        `student` s,`teacher` t
        WHERE
        s.t_id = t.id
        AND
        t.`id` = #{id}
    </select>

</mapper>

异常

DataAccessException

DataAccessException用于处理数据处理的异常,包括插入数据时有唯一性约束导致失败等问题。
如果插入重复的主键数据,mybatis会抛出异常。

Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '10' for key 'PRIMARY'

; Duplicate entry '10' for key 'PRIMARY'; nested exception is java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '10' for key 'PRIMARY'
只需要在定义接口时,抛出异常

    void insertUser(User user) throws DataAccessException;

调用时候不活

    @Test
    void test() {
        try {
            User user = new User().setId(10).setAge(11).setName("11");
            mapper.insertUser(user);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
//        User user = new User().setId(10).setAge(11).setName("11");
//        mapper.insertUser(user);
    }

git

posted @ 2020-08-17 19:19  刃牙  阅读(197)  评论(0编辑  收藏  举报