MyBatis2

MyBatis2(MyBatis 开发DAO的方法)

SqlSession使用范围

SqlSessionFactoryBuilder(当作工具类来使用)

  • 通过 SqlSessionFactoryBuilder().builder(InputStream is) 创建 SqlSessionFactory,
    在创建SqlSessionFactory的时候,只需要new 一次SqlSessionFactoryBuilder即可

SqlSessionFactory

  • 通过 SqlSessionFactory 创建 SqlSession, 通过单例模式管理sqlSessionFactory (一旦创建,不再销毁,一直使用)
    将来 Spring 和 Mybatis 整合后,使用单例模式管理 sqlSessionFactory

SqlSession

  • SqlSession 面向用户(开发者)的接口,但是是线程不安全的,最佳的应用场合是在方法体内,定义成局部变量

##DAO 开发

原始Dao 开发方法(需要写Dao 接口和Dao 实现类)

  • 向Dao 实现类中注入SqlSessionFactory, 通过sqlSessionFactory 创建SqlSession
dao 接口
public interface Dao {

//    通过用户id 查询用户
    User findUserById(int id) throws Exception;

//    通过用户名字模糊查询用户
    List<User> findUserByName(String name) throws Exception;

//    添加用户
    int addUser(User user) throws Exception;

//    通过id 删除用户
    int deleteUserById(User user) throws Exception;

//    通过id 更新用户
    int updateUserById(User user) throws Exception;

}
dao 实现类
public class DaoImpl implements Dao {

    private SqlSessionFactory sqlSessionFactory;

    public DaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User findUserById(int id) throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        User u = sqlSession.selectOne("com.mybatisStudy2.usermapper.findUserById", id);
        sqlSession.close();
        return u;
    }

    @Override
    public List<User> findUserByName(String name) throws Exception {

        name = ("%").concat(name).concat("%");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> users = sqlSession.selectList("com.mybatisStudy2.usermapper.findUserByName", name);
        sqlSession.close();
        return users;
    }

    @Override
    public int addUser(User user) throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        int num = sqlSession.insert("com.mybatisStudy2.usermapper.addUser", user);
        sqlSession.commit();
        sqlSession.close();
        return num;
    }

    @Override
    public int deleteUserById(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        int num = sqlSession.insert("com.mybatisStudy2.usermapper.deleteUserById", user);
        sqlSession.commit();
        sqlSession.close();
        return num;
    }

    @Override
    public int updateUserById(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        int num = sqlSession.insert("com.mybatisStudy2.usermapper.updateById", user);
        sqlSession.commit();
        sqlSession.close();
        return num;
    }
}

原始DAO 开发的问题
  1. 接口实现类存在大量的重复代码
  2. 在调用SqlSession 讲statement的ID 硬编码在Java 语句内
  3. sqlSession 方法传参错误在编译时不会报错,不利于开发

使用mapper 代理的方式(只需要mapper 接口(相当于Dao 接口))

  1. 编写Mapper 接口(相当于DAO 接口)
  2. 编写Mapper.xml 映射文件
  3. 规范
  • 在Mapper.xml 的namespace 要为mapper 接口的地址

TIM截图20190514123612.png

  • 编写接口的方法,方法名和Mapper.xml 的statement 的id 一致
  • Mapper 接口的输入参数要和Mapper.xml 内Statement 的 parameterType 指定的类型一致
  • Mapper 接口的返回值要和Mapper.xml 内Statement 的 resultType 指定的类型一致
public interface Dao {

//    通过用户id 查询用户
    User findUserById(int id) throws Exception;

//    通过用户名字模糊查询用户
    List<User> findUserByName(String name) throws Exception;

//    添加用户
    int addUser(User user) throws Exception;

//    通过id 删除用户
    int deleteUserById(User user) throws Exception;

//    通过id 更新用户
    int updateById(User user) throws Exception;

}

  • 加载Mapper
    <mapper resource="mapper/mapper.xml"/>
代理内部调用方式
@Test
    public void test() throws Exception {
        //读取配置文件
        InputStream is = Resources.getResourceAsStream("mybatisConfig.xml");
        //创建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //创建SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //实例化Dao
        Dao dao = sqlSession.getMapper(Dao.class);
        System.out.println(dao.findUserById(2).toString());
    }
注:DAO 层参数建议使用pojo 类来包含所有参数(许多Service 层使用)、Service 层不建议使用pojo 传参\

Mybatis 配置文件(Mybatis 全局配置文件)

properties(属性)

  • 讲数据库的配置单独配置到db.properties 中,在Mybatis内加载properties文件,避免硬编码
    方便对参数进行统一管理

  • db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/javaend
jdbc.username=root
jdbc.password=1006

  • 加载properties
    <properties resource="db.properties"></properties>

注:Mybatis 加载属性的顺序

  1. 首先读取properties 元素的值
  2. 再读取properties 元素内resource 或url 加载的属性,它会覆盖读取的同名属性
  3. 最后读取parameterType 传递的属性值

当properties 的属性名和mapper 内的属性名一样的时候(${jdbc.username})会出现如下错误
TIM截图20190514130813.png
在properties 定义属性要有一定的特殊性,如:xxxx.xxxx

settings 全局参数配置

  • mybatis 全局配置参数,全局参数将会影响mybatis 的运动行为
    settings 配置

typeAliases (别名)

  • 在输入类型的时候, 针对输入或输入的类型过长(全路径)不便于开发,可以使用别名
  • 默认的别名

TIM截图20190515192735.png

  • 自定义别名 (pojo)

单个别名的定义

<typeAliases>
<!--        针对单个别名
        type:类型的路径
         alias:别名 -->
    <typeAlias type="com.pojo.User" alias="user"/>
</typeAliases>

批量定义别名(常用)

 <typeAliases>
<!--        批量定义别名:
            指定包名,mybatis 自动将该包下面的pojo 设置别名(类名首字母小写(或大写))-->
        <package name="com.pojo"/>
    </typeAliases>
    

typeHandles 类型处理器

  • 在Mybatis 使用typeHandles 完成jdbc 类型和java 类型的相互转换

TIM截图20190515194453.png

mapper 映射器

  • 记载单个的映射文件
<mappers>
    <mapper resource="mapper/usermapper.xml"/>
    <mapper resource="mapper/mapper.xml"/>
</mappers>
  • 使用mapper 接口加载
  • 需要将mapper 接口的类名和mapper.xml 玩文件名需要一致(前提:使用mapper 代理的方式)
<mappers>
    <mapper class="com.dao.Dao"/>
</mappers>
<mappers>
    <package name="com.dao"/>
</mappers>

Mybatis 输入映射和输出映射

输入输出映射类型

  • 简单类
  • hashMap
  • Pojo 包装对象
输入映射
  • 使用包装类型
输出映射
  • resultType

查询出来的列名称和pojo属性一致,pojo内属性才能被赋值

  • resultMap

使用resultMap 完成一对一、多对多查询等

  • 定义resultMap
  • 使用resultMap 作为输出类型
<!--    通过用户id 查询用户-->  
<!--    resultMap:指定resultMap 的id,如果resultMap 在其他mapper.xml 下,则前面需要加上namespace -->
<select id="findUserById" parameterType="int" resultMap="resultMapTest" >
    SELECT id id_, username username_, password password_, name name_, addr addr_ FROM user WHERE id = #{id}
</select>
<resultMap id="resultMapTest" type="user">
    <id column="id_" property="id" />
    <result column="username_" property="username" />
    <result column="password_" property="password" />
    <result column="name_" property="name" />
    <result column="addr_" property="addr" />
</resultMap>
动态SQL
  • Mybatis 对SQL 语句进行灵活的操作
if

  • mapper.xml
<!-- 用于判断条件是否满足,userVO 是pojo User视图层对象,用于获取user对象 -->
<select id="findUserByUsingDTSql" parameterType="userVO" resultType="user">
    SELECT * from user
    <!--
        where 可以自动去掉第一个and
    -->
    <where>
        <if test="user != null">
            <if test="user.sex != null">
                AND sex = #{user.sex}
            </if>
            <if test="user.name != null">
                And name LIKE #{user.name}
            </if>
        </if>
    </where>
</select>

  • 组成判断的sql片段
  1. 定义sql 片段
<!-- 定义sql 片段,id 唯一标识sql 片段 
      在sql 片段内部不要包括where
      基于单表定义的sql 片段可复用性才高 -->
<sql id="if_test">
    <if test="user != null">
        <if test="user.sex != null">
            AND sex = #{user.sex}
        </if>
        <if test="user.name != null">
            And name LIKE #{user.name}
        </if>
    </if>
</sql>
  1. 使用sql 片段
<where>
    <!-- 如果sql 片段在其他xml 文件内,则需要在前面加上namespace -->
    <include refid="if_test"></include>
</where>
choose, wher, otherwise
<sql id="choose_test">
    <choose>
        <when test='user.sex == "男"'>
            AND sex = "女"
        </when>
        <otherwise>
            And 1 = 1
        </otherwise>
    </choose>
</sql>
trim, where, set
  • where : 在sql 语句后添加条件
<where>
    id = #{id}
</where>
  • set : 在update 语句后添加设置语句
<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

如实现 标签的作用

<where>
    <if test="user != null">
        <if test="user.sex != null">
            AND sex = #{user.sex}
        </if>
        <if test="user.name != null">
            And name LIKE #{user.name}
        </if>
    </if>
</where>

使用 实现

<trim prefix="WHERE" prefixOverrides="AND">
    <if test="user != null">
        <if test="user.sex != null">
             AND sex = #{user.sex}
        </if>
        <if test="user.name != null">
             AND name LIKE #{user.name}
        </if>
    </if>
</trim>
foreach
  • 多个值的输入查询, sql 语句如下

SELECT * FROM user WHERE id = 1 OR id = 3 OR id = 5;
SELECT * FROM user WHERE id IN(1, 3, 5);

  • 在mapper.xml 文件内配置如下
  • 注意:

collection:输入对象的集合属性
item:每次遍历生成的对象
open:开始遍历拼接的串
close:结束遍历拼接的串
separator:遍历生成的两个对象之间需要拼接的串

<sql id="foreach_test">
    <foreach collection="ids" item="id" open="AND(" close=")" separator="OR">
        id = #{id}
    </foreach>
</sql>

实现 SELECT * FROM user WHERE id IN(1, 3, 5);

<sql id="foreach_test">
    <foreach collection="ids" item="id" open="id IN(" close=")" separator=",">
        id = #{id}
    </foreach>
</sql>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值