我所知的Mybatis03————mapper.xml的属性配置研究

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="com.asjy.dao.UserMapper">
</mapper>

全部写在<mapper>中

<!-- namespace:名称空间,对statement进行分类管理,类似于包名,Mapper代理时,namespace有特殊且重要的作用  -->

 

========================================================================================================================================

 

 

1.Mapper代理开发方式

要实现mapper代理的开发方式,需要遵循一些开发规范

 

|----需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中

 

|----mapper接口的全限定类名要和mapper映射文件的namespace的值相同。

|----mapper接口的方法入参只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。

接口:   xml:

|----mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;

接口:   xml:

|----mapper接口的方法名要和mapper映射文件中的id保持一致;

 

========================================================================================================================================

 

2.mapper.xml属性

 

根据用户ID查询用户信息

 

例:

<select id="findUserById" parameterType="int" resultType="com.aishang.domain.User">

       select * from user where uid = #{id}

</select>

1、#{}:表示一个占位符,如果入参是简单类型,那么#{}里面的入参名可以任意起名;

2、parameterType:入参对应的java类型;

3、resultType:输出结果所映射的java类型(对于单表查询的话用resultType是最合适的,多表联合用resultMap);

 

根据用户名称来模糊查询用户信息列表

例:

<select id="findUserByName1" parameterType="java.lang.String" resultType="com.aishang.domain.User">

      select * from user where username like '%${value}%'

</select>

 

添加用户

例:

<insert id="insertUser1" parameterType="com.aishang.domain.User">

      insert into user(username,password,name,email,phone,addr,state)

      values(#{username},#{password},#{name},#{email},#{phone},#{addr},#{state})

</insert>

1、占位符#{}里面写的名字和数据库字段名字一样

 

添加用户后返回主键 ------ 主键自增

我用过的地方是,当我添加完一个订单,需要同时添加订单项,这时就需要刚添加完的订单主键ID,添加完再查出ID,再保存,再调用,很麻烦,mybatis中提供了一个便捷方法

例:

<insert id="insertUser2" parameterType="com.aishang.domain.User">

  <selectKey keyProperty="uid" resultType="int" order="AFTER">

    select LAST_INSERT_ID()

  </selectKey>

  insert into user(username,password,name,email,phone,addr,state)

  values(#{username},#{password},#{name},#{email},#{phone},#{addr},#{state})

</insert>

1、selectKey:查询主键,在标签内需要输入查询主键的sql;

2、keyProperty:查询出来的主键值怎么返回?"User"类中"uid"列用来容纳查询出来的生成的主键的值,此配置指明在实体类中用来容纳查询出的主键的属性名;

3order:指定查询主键的sql和insert语句的执行顺序

  | ---- BEFORE: 如果是oracle数据库的话,不是主键自增机制,而是序列机制,

              需要先生成一个序列,拿到序列后再执行插入,因此采用的是order="BEFORE"

              如果是UUID,也需要先生成一个UUID,再执行插入,也采用order="BEFORE"

  | ---- AFTER:mysql中,采用自增主键策略 在insert的时候产生主键,所以在执行完insert之后,再来获取生成的主键,因而在这里配置,order="AFTER"

4、LAST_INSERT_ID():该函数是mysql函数,针对自增主键来获取主键的id,必须配合insert语句一起使用

 

添加用户后返回主键 --  UUID

例:

<insert id="insertUser3" parameterType="com.aishang.domain.User">

  <selectKey keyProperty="uid" resultType="java.lang.String" order="BEFORE">

    select UUDI()

  </selectKey>

  insert into user(uid,username,password,name,email,phone,addr,state)

  values(#{uid},#{username},#{password},#{name},#{email},#{phone},#{addr},#{state})

</insert>

1、UUDI():该函数是mysql函数,生成一个32位随机不重复的数据;

2、uid不是自增了,也需要插入进去,采用的值是上一步 select UUDI()的结果,已经封装到了User对象的uid属性了;

 

添加用户后返回主键 --  Oracle序列

<insert id="insertUser4" parameterType="com.aishang.domain.User">

  <selectKey keyProperty="uid" resultType="int" order="BEFORE">

    select seq.nextval() from dual

  </selectKey>

  insert into user(uid,username,password,name,email,phone,addr,state)

  values(#{uid},#{username},#{password},#{name},#{email},#{phone},#{addr},#{state})

</insert>

1、sequence:是Oracle主键生成策略;

2、uid不是自增了,也需要插入进去,采用的值是上一步 select UUDI()的结果,已经封装到了User对象的uid属性了;

 

=========================================================================================================================================

 

3.动态SQL

Mybatis提供的各种动态标签实现动态拼接sql,使得mapper映射文件在编写SQL时更加灵活,方便。常用动态SQL标签有:if、where、foreach;

例:

<select id="findUserList" parameterType="UserWapper" resultType="user">

  select * from user

  <where>

    <if test="user !=null">

      <if test="user.username != null and user.username !='' ">

        and username like '%${user.username}%'

      </if>

      <if test="user.password != null and user.password != '' ">

        and password= #{user.password}

      </if>

    </if>

  </where>

</select>

1、if标签:如果符合条件,则把if标签内的SQL语句拼接上;

2、where标签:会去掉第一个符合条件的and符号,其余正常拼接

 

SQL片段

类似于静态包含

例:

<sql id="whereNameAndSexClause">

  <if test="user !=null">

    <if test="user.username != null and user.username !='' ">

      and username like '%${user.username}%'

    </if>

    <if test="user.password != null and user.password != '' ">

      and password= #{user.password}

    </if>

  </if>

</sql>

<!------------------------------------- 引入sql片段 --------------------------------------------->

<select id="findUserCount" parameterType="UserWapper" resultType="int">

  select count(*) from user

  <where>

    <include refid="whereNameAndSexClause"></include>

  </where>

</select>

 

========================================================================================================================================

 

4.关联映射查询

 

复杂查询时,单表对应的po类已不能满足输出结果集的映射。所以要根据需求建立一个扩展类来作为resultType的类型

一对一映射

例:现在要查看一个订单,订单里也要有用户的某些信息。就需要同时包含有user信息(用户)和order信息(订单)的OrdersExt扩展类。

domain/po/bean/源材料类:

Mapper映射文件:

Mapper接口:

 

 

 

直接就都出来了,或者不用 resultType 用 resultMap。

 

Mapper映射文件:

SQL没有变化,select属性里的resultType变成了resultMap,然后随便给resultMap里起个名,这里叫"ordersAndUserRstMap"

<resultMap>标签里的type是全限定类名,id就是刚才随便起的名

column 是对应数据库中表的字段名称 

property 是对应的po类里面的属性名称

<association> 1对1关联映射

一对多映射

一对多查询和一对一查询的配置基本类似。只是如果使用resultMap的话,映射一对多关联关系要使用collection标签

例:每个一级类目中有多个二级类目。需要category(一级类目)和categorySecond(二级类目),创建一个同时包含两者的CategoryAndSecondExt扩展类。

category: catrgorySecond:

CategoryAndSecondExt:一个一级类目包含多个二级类目集合

PS:这里我试过没用继承而直接将属性写在里面,但是映射失败我也不知道为什么

 

Mapper映射文件:

已经不是一对一的association而是一对多的collection了,别忘了接口;

 

多对多映射

例:Product商品类,Orders订单类,Orderitem订单项类,User用户类。

分析

User和Order

user —— orders:一个用户可以创建多个订单,一对多

orders —— user:一个订单只由一个用户创建,一对一

 

ordersorderitem

orders —— orderitem:一个订单可以包括多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderitem记录,一对多关系

orderitem —— orders:一个订单明细只能包括在一个订单中,一对一

 

orderitemproduct

orderitem —— product:一个订单明细只对应一个商品信息,一对一

product —— orderitem:一个商品可以包括在多个订单明细 ,一对多

 

Ordersproduct

这两张表没有直接的外键关系,通过业务及数据库的间接关系分析出它们是多对多的关系。

orders —— orderitem —— product:一个订单可以有多个订单明细,一个订单明细对应一个商品,所以一个订单对应多个商品

product —— orderitem —— orders:一个商品可以对应多个订单明细,一个订单明细对应一个订单,所以一个商品对应多个订单

 

userproduct

这两张表没有直接的外键关系,通过业务及数据库的间接关系分析出它们是多对多的关系。

user —— orders —— orderitem —— product一个用户有多个订单,一个订单有多个订单明细、一个订单明细对应一个商品,所以一个用户对应多个商品

Items —— orderitem —— orders —— user:一个商品对应多个订单明细一个订单明细对应一个订单一个订单对应一个用户所以一个商品对应多个用户

 

这里不详细说类里的属性了,也不重要,下面说一下包装类,这里为了演示省事写一起了:

 

Mapper映射文件:

 

Mapper接口:

 

 

小结

实现一对一查询:

resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列的别名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType这是一种平铺式的映射

resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的对象属性中。这是一种层叠式的映射

resultMap可以实现延迟加载,resultType无法实现延迟加载。

posted @ 2018-03-09 16:49  输入贩卖元  阅读(397)  评论(0编辑  收藏  举报