前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >11. MyBatis注解

11. MyBatis注解

作者头像
Devops海洋的渔夫
发布2021-05-06 16:21:47
4700
发布2021-05-06 16:21:47
举报
文章被收录于专栏:Devops专栏Devops专栏

11. MyBatis注解

前言

前面的章节我们已经认识了如何使用 xml 来配置 MyBatis 的用法。随着这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了。

我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。不过,总体来说,注解开发方式一般只用在简单的SQL,其他复杂的方式一般还是写在 xml 文件中。

# 配置文件
0. 作用: 配置一些信息,给程序使用
 程序读取配置文件的数据过程: 解析
1. properties 文件 
  解析: Properties类
2. xml 文件
  解析: dom/sax/pull
3. 注解
  解析: 反射

1. MyBatis常用注解

* @Insert:实现新增,代替了<insert></insert>
 
* @Update:实现更新,代替了<update></update>

* @Delete:实现删除,代替了<delete></delete>

* @Select:实现查询,代替了<select></select>

* @Result:实现结果集封装,代替了<result></result>

* @Results:可以与@Result 一起使用,封装多个结果集,代替了<resultMap></resultMap>

* @One:实现一对一结果集封装,代替了<association></association>
 
* @Many:实现一对多结果集封装,代替了<collection></collection>

2. MyBatis单表操作【重点】

需求:基于user模块通过注解实现,增删改查

2.1 UserMapper接口

public interface UserMapper {

    // 查询所有
    @Select("select id as uid,username as uname,birthday as bir , sex as gender, address as addr from user")
    @Results({ // resultMap标签手动映射
            @Result(column = "uid",property = "id",id=true), // result标签映射封装
            @Result(column = "uname",property = "username"),
            @Result(column = "bir",property = "birthday"),
            @Result(column = "gender",property = "sex"),
            @Result(column = "addr",property = "address")
    })
    public List<User> findAll();

    // id查询
    @Select("select * from user where id = #{id}")
    public User findById(Integer id);


    // 新增
    @Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
    public void save(User user);


    // 修改(动态sql还是推荐使用xml)
    @Update("update user set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} where id = #{id}")
    public void update(User user);


    // 删除
    @Delete("delete from user where id = #{id}")
    public void delete(Integer id);
}

2.2 测试

2.2.1 测试查询所有 findAll()
@Test
public void test16(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 查询所有用户信息
    List<User> users = mapper.findAll();
    for (User user : users) {
        System.out.println(user);
    }

    MyBatisUtil.commitAndClose(sqlSession);
}

执行如下:

image-20210406081842726

2.2.2 测试 根据 id 查询用户信息 findById()
@Test
public void test17(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 根据id查询用户信息
    User user = mapper.findById(41);
    System.out.println(user);

    MyBatisUtil.commitAndClose(sqlSession);
}

执行如下:

image-20210406082307312

2.2.3 测试 新增用户 save()
@Test
public void test18(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 新增用户
    User user = new User();
    user.setUsername("李大四");
    user.setSex("男");

    mapper.save(user);

    MyBatisUtil.commitAndClose(sqlSession);
}

执行如下:

image-20210406082726038

2.2.4 测试 修改用户 update()
@Test
public void test19(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 修改用户
    User user = new User();
    user.setId(49); // 设置修改的用户ID
    user.setUsername("张大三");
    user.setSex("男");

    mapper.update(user);

    MyBatisUtil.commitAndClose(sqlSession);
}

执行如下:

image-20210406083006221

2.2.5 测试 删除用户 delete()
@Test
public void test20(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 根据id, 删除用户
    mapper.delete(46);

    MyBatisUtil.commitAndClose(sqlSession);
}

执行如下:

image-20210406083234369

3. MyBatis多表操作【了解】

“注解开发的方式写多表查询很少用,因为很麻烦,大概了解一下就好。 ”

注解多表操作是基于嵌套查询来实现

1589334124076

3.1 一对一查询

需求:查询一个订单,与此同时查询出该订单所属的用户

一对一查询语句

-- 使用一对一的嵌套查询进行
SELECT * FROM orders where id = #{订单的id};
SELECT * FROM `user` WHERE id = #{订单的uid};
3.1.1 UserMapper接口:根据 uid 查询用户信息
public interface UserMapper {

    // id查询
    @Select("select * from user where id = #{id}")
    public User findById(Integer id);
    
}
3.1.2 OrderMapper接口:使用注解的方式设置嵌套查询
public interface OrdersMapper {
 /**
     *     <!--
     *         设置查询结果集 resultMap, 结果映射为 Orders 类
     *     -->
     *     <resultMap id="myorder" type="Orders" autoMapping="true">
     *         <!--  设置 id 字段映射 Orders 类的属性 id -->
     *         <id property="id" column="id"/>
     *         <!--  设置普通字段 ordertime 映射 Orders 类的属性 ordertime   -->
     *         <result property="ordertime" column="ordertime"/>
     *         <!--
     *             # 嵌套查询重点:
     *                 0. 目的
     *                     select * from user where id = ?
     *                         映射到 orders.user属性中
     *                 1. 编写查询user表的语句:
     *                     UserMapper.findUserById -> UserMapper.xml
     *                 2. 嵌套到这里
     *                     association标签的两个属性
     *                         a. column : 条件 (执行查询方法的参数)
     *                          b. select : 调用第二句sql执行
     *                             接口的权限定名.方法名
     *                             UserMapper.findUserById(用户id)
     *         -->
     *         <association property="user" javaType="user" autoMapping="true"
     *                      column="uid"
     *                      select="com.lijw.dao.UserMapper.findUserById">
     *             <id property="id" column="uid"/>
     *             <result property="username" column="username"/>
     *         </association>
     *     </resultMap>
     *
     *     <select id="findOrderByIdWithUser" resultMap="myorder">
     *         select * from orders where id = #{id}
     *     </select>
     */
    @Select("select * from orders where id = #{id}")
    @Results({
            @Result(property = "id",column = "id",id=true), // id标签: 主键字段映射
            @Result(property = "ordertime",column = "ordertime"),
            @Result(property = "user",javaType = User.class, column = "uid",
                    one = @One(select = "com.lijw.dao.UserMapper.findById",fetchType = FetchType.EAGER)) // 设置立即加载
    })
    Orders findOrderByIdWithUser(Integer id);
    
}
3.1.3 测试
public class OrderMapperTest extends BaseMapperTest { // 继承父类,就可以直接使用 父类的方法和成员变量了

    // 一对一嵌套测注解试
    @Test
    public void test21(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);

        // 嵌套查询
        Orders order = mapper.findOrderByIdWithUser(1);
        System.out.println(order);

        MyBatisUtil.commitAndClose(sqlSession);
    }
}

执行如下:

image-20210407002433893

3.2 一对多查询

需求:查询一个用户,与此同时查询出该用户具有的订单

一对多查询语句

-- 使用嵌套查询演示
SELECT * FROM `user` where id = #{id};
SELECT * FROM orders where uid = #{用户id};
3.2.1 OrdersMapper接口: 根据 uid 查询 Order 方法
public interface OrdersMapper {
   
    @Select("select * from orders where uid = #{id}")
    public List<Orders> findByUid(Integer uid);
}
3.2.2 UserMapper接口:使用注解嵌套设置查询一个用户的多个订单
public interface UserMapper {

    // 一对多注解嵌套查询
    @Select("select * from user where id = #{id}")
    @Results({ // resultMap标签手动映射
            @Result(column = "id",property = "id",id=true), // result标签映射封装
            @Result(column = "username",property = "username"),
            @Result(column = "birthday",property = "birthday"),
            @Result(column = "sex",property = "sex"),
            @Result(column = "address",property = "address"),
            // 嵌套查询:SELECT * FROM orders where uid = #{用户id};
            // 传递 id 到 com.lijw.dao.OrdersMapper.findByUid 方法中,返回的结果设置到 user 对象的 list 属性
            @Result(
                    property = "list", javaType = List.class, column = "id",
                    many = @Many(select = "com.lijw.dao.OrdersMapper.findByUid")
            )
    })
    public User findByIdWithOrders(Integer id);
}
3.2.3 测试
    // 一对多嵌套查询测试
    @Test
    public void test22(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 查询id=41用户的信息,包含订单信息
        User user = mapper.findByIdWithOrders(41);
        System.out.println(user);

        List<Orders> ordersList = user.getList();
        System.out.println(ordersList);

        MyBatisUtil.commitAndClose(sqlSession);
    }

执行如下:

image-20210407005203830

4. 局部延迟加载

不管是一对多还是多对多 ,在注解配置中都有fetchType的属性

* fetchType = FetchType.LAZY 表示懒加载

* fetchType = FetchType.EAGER   表示立即加载

* fetchType = FetchType.DEFAULT 表示使用全局配置

5. 二级缓存

配置SqlMapConfig.xml文件开启二级缓存的支持

<settings>
    <!--
  因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。
  为true代表开启二级缓存;为false代表不开启二级缓存。
    -->
    <setting name="cacheEnabled" value="true"/>
</settings>

在Mapper接口中使用注解配置二级缓存

// 注解配置二级缓存
@CacheNamespace
public interface UserMapper {...}

相当于 xml 配置如下:

image-20210407005411170

6. 知识小结

1. 注解开发和xml配置相比,从开发效率来说,注解编写更简单,效率更高。

2. 从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。

* 经验:单表简单CRUD可以使用注解、多表及动态sql你就用xml
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 海洋的渔夫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 11. MyBatis注解
    • 前言
      • 1. MyBatis常用注解
        • 2. MyBatis单表操作【重点】
          • 2.1 UserMapper接口
          • 2.2 测试
        • 3. MyBatis多表操作【了解】
          • 3.1 一对一查询
          • 3.2 一对多查询
        • 4. 局部延迟加载
          • 5. 二级缓存
            • 6. 知识小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档