A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

【南京校区】非诚勿扰《mybatis》之再判断
                                                                                    德艺双馨杨老师


    哈喽我又来了,上次咱们介绍到了mybatis的基本用法,接下来要介绍一些的动态代理,关联关系映射,

一、首先呢说一说mybatis里的事物控制,当你单纯在使用mybatis的时候会是什么样子的呢
              1.mybatis里查询动作不会触发事务提交动作,即便定义了session.commit()也不会触发,除非明确
                      提出session.commit(true).
   
              2.默认情况下,mybatis不会对insert update delete做事务提交,如果需要真正完成数据库更新操作
                   则需要在代码中明确写出session.commit();

二、Mapper动态代理方式是干什么的?
      Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,
                     代理对象的方法体同上边Dao接口实现类方法。
      Mapper接口开发需要遵循以下规范:
            1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。
            2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
            3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
            4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
         
          定义mapper映射文件UserMapper.xml(内容同Users.xml),需要修改namespace的值为 UserMapper接口路径。
          将UserMapper.xml放在classpath 下mapper目录下。

          接口定义有如下特点:
               1、 Mapper接口方法名和Mapper.xml中定义的statement的id相同
               2、 Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
               3、 Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
  
   使用:
         //获取mapper接口的代理对象
                      UserMapper userMapper = session.getMapper(UserMapper.class);
          //调用代理对象方法
                      User user = userMapper.findUserById(1);
     selectOne和selectList
         动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,
              如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。
    namespace
         mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,
          使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

三、接下来就是最最重要的时刻了 关联关系映射它是我们数据库表和实体之最重要的关系了
     一对一 :    
    1)数据库里建表: db里表示数据间的一对一关系,需要选择一方建立外键,同时在fk上添加uk
    create table person(
            id number(7) primary key,
            name varchar2(15) not null,
            email varchar2(30) not null,
            cid number(7) references IdentifyCard(id) unique
    );
    create table IdentifyCard(
              id number(7) primary key,
             serial varchar2(18) not null check(length(serial)=18),
              expire number(2)
    );  

    2)java程序里描述数据
          双向一对一:互相保留对方的一个引用
          单向一对一:只在关系主要方保留对方的一个引用(尽量与db里表关系的方向保持一致)
    class Person{
    private Integer id;
    private String name;
    private String email;
    private IdentifyCard card;  //关系属性
    }
    class IndentifyCard{
    private Integer id;
    private String serial;
    private int expire;
    private Person Person;    //关系属性
    }  

    3)写dao(PersonDao,IndentifyCardDao)
          PersonDaoImpl.xml映射文件
    <resultMap type="实体的全限定名" id="该resultMap的唯一标识">
                          <id     property="属性名"     column="数据库字段名"></id>
                         <result property="属性名"     column="数据库字段名"></result>
                         <association property="实体类里关系属性名" javaType="关系属性的类型">
                                <id      property="属性名" column="数据库字段名"></id>
                                <result  property="属性名" column="数据库字段名"></result>
                         </association>
    </resultMap>  
一对多:
        1)数据库里建表 :一对多是db最擅长描述的关系,只需要在“多的一方”建立外键即可
   create table dept(                //一
           id number(7) primary key,
           name varchar2(15) not null
   );
   create table emp(                //多
            id number(7) primary key,
            name varchar2(15) not null,
            salary number(5),
           did number(7) references dept(id)
   );
   
  2)java程序里定义实体类
    双向一对多:一的一方(保留多的一个集合)  多的一方(保留一的一个引用)
       单项一对多:通常都是多到一的单向
   class Dept{
      private Integer id;
      private String name;
      private List<Emp> emps = new ArrayList<Emp>();
   }
   class Emp{
      private Integer id;
      private String name;
      private double salary;
      private Dept dept;
   }
        3)dao(DeptDao  EmpDao)
    <resultMap type="实体的全限定名" id="该resultMap的唯一标识">
                     <id     property="" column=""></id>
                     <result property="" column=""></result>
                   <collection property="实体类里关系属性名" ofType="集合里元素的类型">
                                 <id     property="" column=""></id>
                               <result property="" column=""></result>
                    </collection>
    </resultMap>

四、动态sql
    动态sql。通过mybatis提供的各种标签方法实现动态拼接sql。
      1. if
      <select id="findUserList" parameterType="user" resultType="user">
               select * from user
               where 1=1
     <if test="id!=null">
               and id=#{id}
     </if>
     <if test="username!=null and username!=''">
               and username like '%${username}%'
     </if>
     </select>

     注意要做不等于空字符串校验。
     <!-- 多条件使用   and  而不是  && -->
     <if test="username!=null and username!='' ">
                   and username LIKE '%${username}%'
     </if>

      2. where
    <select id="findUserList" parameterType="user" resultType="user">
              select * from user
     <where>
     <if test="id!=null and id!=''">
               and id=#{id}
     </if>
     <if test="username!=null and username!=''">
                and username like '%${username}%'
     </if>
     </where>
      </select>
            注意:<where />可以自动处理第一个and。
   
   3. foreach 向sql传递数组或List,mybatis使用foreach解析
         例如;
       传入多个id查询用户信息,用下边两个sql实现:
    SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
    SELECT * FROM USERS WHERE username LIKE '%张%'  id IN (10,89,16)
            <if test="ids!=null and ids.size>0">
    <foreach collection="ids" open=" and id in(" close=")" item="id" separator="," >
               #{id}
    </foreach>
            </if>
      4. choose
   <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>
            以上例子中: 当title和author都不为null的时候, 那么选择二选一(前者优先), 如果都为null, 那么就选择 otherwise中的, 如果tilte和author只有一个不为null, 那么就选择不为null的那个
   
   5. trim      
   <trim prefix="WHERE" prefixOverrides="AND |OR ">
   ...
   </trim>
   它的意思就是: 当WHERE后紧随AND或则OR的时候,就去除AND或者OR。 除了WHERE以外, 其实还有一个比较经典的实现,那就是SET。
   
   6  set
            <update id="updateUser" parameterType="com.dy.entity.User">
     update user set
     <if test="name != null">
     name = #{name},
     </if>
     <if test="password != null">
     password = #{password},
     </if>
     <if test="age != null">
     age = #{age}
     </if>
     <where>
     <if test="id != null">
     id = #{id}
     </if>
     and deleteFlag = 0;
     </where>
   </update>
               问题又来了: “如果我只有name不为null, 那么这SQL不就成了 update set name = #{name}, where ........ ?
                你那name后面那逗号会导致出错啊!”
         正解:
       <update id="updateUser" parameterType="com.dy.entity.User">
      update user set
      <set>
      <if test="name != null">name = #{name},</if>
      <if test="password != null">password = #{password},</if>
      <if test="age != null">age = #{age},</if>
      </set>
      <where>
      <if test="id != null">
      id = #{id}
      </if>
      and deleteFlag = 0;
      </where>
    </update>
    用trim
                <trim prefix="SET" suffixOverrides=",">
    ...
    </trim>
    WHERE是使用的 prefixOverrides(前缀), SET是使用的 suffixOverrides (后缀), 看明白了吧!   
   7. sql片段  Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,
                <!-- 传递pojo综合查询用户信息 -->
    <select id="findUserList" parameterType="user" resultType="user">
      select * from user
     <where>
     <if test="id!=null and id!=''">
        and id=#{id}
     </if>
     <if test="username!=null and username!=''">
        and username like '%${username}%'
     </if>
     </where>
    </select>
            
   将where条件抽取出来:
    <sql id="query_user_where">
     <if test="id!=null and id!=''">
      and id=#{id}
     </if>
     <if test="username!=null and username!=''">
      and username like '%${username}%'
     </if>
    </sql>
         使用include引用:
       <select id="findUserList" parameterType="user" resultType="user">
     select * from user
     <where>
     <include refid="query_user_where"/>
     </where>
    </select>
        注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:
         <include refid="namespace.sql片段”/>

以上就是mybatis的一些高级的理念和比较实际的用法,敬请等待后续非诚勿扰《mybatis》之终觉定。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马