Mapper.xml配置文件解读

mapper.xml配置文件解读

①. namespace:与对应mapper接口关联,使其方法与xml定义的标签id相对应。

②. resultType:设置sql语句返回的类型,可以是基本类型,也可以是实体类类型,实体类一般全包名作为参数设置,也可以在mybatis配置文件中设置实体类的别名来设置其resultType。其优点在于简单方便,缺点在于需要创建实体类才能这么用,在于一些多表关联,复杂的结果映射关系中不适用。

③. resultMap:设置sql语句返回的结果集,为自定义映射,在嵌套查询、嵌套结果中使用,可以很方便的对结果集进行配置映射关系,在嵌套查询中甚至不需要写连接语句即可完成关联1对1或1对多查询,底层是做了两次查询,所以嵌套查询存在一个N+1的问题,有时候不需要关联查询但每次都会把关联结果查出来,这就是N+1问题,可以通过在Mybatis配置文件中的<settings/>标签中开启懒加载,底层原理是用了一个动态代理去代理结果集,当用到或是取出结果集中关联的对象时,才进行第二次查询,否则只进行一次查询。

④. Mybatis提供了CRUD四种查询标签例如<select/>等来帮助编写SQL语句,几个标签中常用属性如id需要与mapper接口方法名称一致,用来对应namespace中的mapper接口。如resultType、resultMap上面介绍过了。在<insert/>标签中有useGeneratedKeys属性会自动使用JDBC的getGeneratedKeys方法来取出数据库自增的主键(需要有自增字段),在MySql与SQL Server中可以使用,但在oracle需要创建序列,然后使用<selectKey/>来自增主键,例:

  <insert id="insert" parameterType="com.demo.Pojo" useGeneratedKeys="true" keyProperty="id" >
    insert into DEMO (ID, NAME)
    values (${id}, #{name})
    <selectKey keyProperty="id" order="BEFORE" resultType="int">
      SELECT SEQ_DEMO_ID.NEXTVAL FROM dual
    </selectKey>
  </insert>

⑤. 动态SQL:Mybatis提供动态SQL标签,类似与JSP中的JSTL,有使用过JSP的应该可以很容易看得懂,这部分内容在官网http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html中有详细解释,有了这些动态SQL标签,在编写SQL语句的时候可以非常灵活的自定义SQL语句,下面讲到批量插入的时候会提到<foreach/>标签的使用,这里不过多赘述。

批量操作

当需要批量insert时,如果是insert多少就调用多少次mapper,应该是不合理的,不推荐使用,性能会很低。这时候就需要上面提到的动态SQL来执行批量的SQL操作。

  <insert id="insertBatch" parameterType="list">
    insert into test (id, nums, name
    )
    values
    <foreach collection="list" item="item" separator=",">
    (#{item.id,jdbcType=INTEGER}, #{item.nums,jdbcType=INTEGER}, #{item.name,jdbcType=VARCHAR}
    )
    </foreach>
  </insert>

 只需要一条SQL语句即可完成批量的操作,性能最高,但缺点是SQL语句长度有限制,可以判断一下list中的条数来限制一下SQL语句长度。

还有一种方法是在获取SqlSession的时候设置ExecutorType为BATCH。

sqlSessionFactory.openSession(ExecutorType.BATCH);

这种方法我用的不多,不多赘述。

联合查询

上面有提到在联合查询的时候有两种方式,一种是嵌套结果,一种是嵌套查询。

嵌套结果(1对1):

扫描二维码关注公众号,回复: 3777528 查看本文章
  <!-- 嵌套结果 start  1:1-->
  <resultMap id="blogResultMap2" type="com.dal.resultmap.BlogResultMap">
    <id column="bid" jdbcType="INTEGER" property="bid" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <association property="author" javaType="com.gupao.dal.dao.Author">
      <id column="aid" jdbcType="INTEGER" property="aid" />
      <result column="author_name" jdbcType="VARCHAR" property="authorName" />
    </association>
  </resultMap>

  <select id="selectBlogAuthor2" resultMap="blogResultMap2" parameterType="int">
    select
    *
    from blog b,author a
    where bid = #{id,jdbcType=INTEGER}
    and
    b.author_id = a.aid
  </select>
  <!-- 嵌套结果 end  1:1-->

需要在SQL语句中连接多表查询,在resultMap中映射对应字段即可,1对1都是用<association/>来对应关系

嵌套查询(1对1):

  <!-- 嵌套查询 start  1:1-->
  <resultMap id="blogResultMap" type="com.dal.resultmap.BlogResultMap">
    <id column="bid" jdbcType="INTEGER" property="bid" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <association property="author" column="author_id"
                 select="com.gupao.dal.dao.AuthorMapper.selectByPrimaryKey" />
  </resultMap>

  <select id="selectBlogAuthor" resultMap="blogResultMap" parameterType="int">
    select
    <include refid="Base_Column_List" />
    from blog
    where bid = #{id,jdbcType=INTEGER}
  </select>
  <!-- 嵌套查询 end -->

不需要在SQL语句中写连接语句,正常查询即可,不同于嵌套结果的是在resultMap中的<association/>里有一个属性select,需要指定mapper接口的方法,其原理就是再去对应的mapper中再做一次查询,将结果封装到类中属性,所以这里会有一个N+1的问题,上面也有提到过,需要开启懒加载避免N+1问题。

嵌套结果(1对多):

  <!-- 嵌套结果 1:N start  -->
  <resultMap id="blogPostsResultMap2" type="com.dal.resultmap.BlogPostsResultMap">
    <id column="bid" jdbcType="INTEGER" property="bid" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="author_id" jdbcType="INTEGER" property="authorId" />
    <collection property="posts" ofType="com.dal.dao.Posts" >
      <id column="pid" jdbcType="INTEGER" property="pid" />
      <result column="post_name" jdbcType="VARCHAR" property="postName" />
    </collection>
  </resultMap>

  <select id="selectBlogPosts2" resultMap="blogPostsResultMap2" parameterType="int">
    select
    *
    from blog b,posts p
    where b.bid = #{id,jdbcType=INTEGER}
    and b.bid = p.blog_id
  </select>
  <!-- 嵌套结果 1:N end -->

不同于1对1的就是<association/>标签换成了<collection/>表示映射多个实体,也就是1对多,嵌套结果都是要在SQL语句中做连接操作,设置对应的映射即可。还有就是<collection/>标签多了一个属性ofType,可以看作是List存放结果的类型(泛型)。

嵌套查询(1对多):

  <!-- 嵌套查询 1:N start  -->
  <resultMap id="blogPostsResultMap" type="com.dal.resultmap.BlogPostsResultMap">
    <id column="bid" jdbcType="INTEGER" property="bid" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="author_id" jdbcType="INTEGER" property="authorId" />
    <collection column="bid" property="posts"
                select="selectByBlogId" ofType="com.dal.dao.Posts" >
    </collection>
  </resultMap>

  <select id="selectByBlogId" parameterType="java.lang.Integer"
                  resultType="com.dal.dao.Posts">
    select
    pid,post_name as postName,blog_id as blogId
    from posts
    where blog_id = #{id,jdbcType=INTEGER}
  </select>

嵌套查询的SQL语句都是不需要写连接语句,都是在resultMap中的<collection/>或是另一个关联标签中加上一个select属性设置另一个mapper的查询方法,这里的<collection/>也需要一个ofType(泛型)。这里的N+1问题仍然存在,开启懒加载避免。

猜你喜欢

转载自blog.csdn.net/qq_41737716/article/details/83546409