3.持久层框架设计实现及MyBatis 源码解析 - 基于注解的 Mybatis 应用

一、MyBatis 的常用注解

  1. @Insert:实现数据插入
  2. @Update:实现数据更新
  3. @Delete:实现删除数据
  4. @Select:查询数据
  5. @Result:实现结果集封装
  6. @Results:可以与 @Result 一起使用
  7. @One:实现一对一结果集封装
  8. @Many:实现一对多结果集封装

二、MyBatis 的增删改查

完成对 User 的增删改查操作

1.编写 SqlMapConfig.xml配置文件
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--指定JDBC配置信息-->
    <properties resource="jdbc.properties"></properties>
    <settings>
        <!-- 打印sql日志 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
    <!-- default 指定默认环境的名称 -->
    <environments default="dev">
        <!-- id指定当前环境名称 -->
        <environment id="dev">
            <!-- 事务管理类型,交由 JDBC 管理事务 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 指定当前数据源类型是连接池 -->
            <dataSource type="POOLED">
                <!-- 数据源配置的基本参数 -->
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.mfc.dao.UserDao"></mapper>
    </mappers>
</configuration>
2.编写 User 实体类
public class User {
    private Integer id;
    private String username;
    // set、get、toString 方法省略。。。
}
3.编写 UserDao 接口
public interface UserDao {
    @Select("select * from user")
    public List<User> findAllUser();
    @Select("select * from user where id=#{id}")
    public User findUserById(Integer id);
    @Insert("insert into user values(#{id},#{username})")
    public void addUser(User user);
    @Delete("delete from user where id=#{id}")
    public void deleteUser(Integer id);
    @Update("update user set t.username=#{username} where id=#{id}")
    public void updateUser(User user);
}
4.编写测试类

这里只测试查询方法:

    @org.junit.Test
    public void test() throws Exception{
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(inputStream);
        SqlSession sqlSession = factory.openSession();
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> users = userDao.findAllUser();
        for (User user : users) {
            System.out.println(user);
        }
        sqlSession.close();

    }

三、MyBatis 的注解复杂映射

1.复杂映射简介
  1. 在此之前我们已经实现了使用 XML 配置复杂关系映射,可参考2.持久层框架设计实现及MyBatis 源码解析 - 基于 XML 的 Mybatis 应用
  2. 复杂关系映射使用的注解:
    在这里插入图片描述
2.一对一查询
  1. 一对一查询模型

    1. 用户表和订单表的关系为:一个用户有多个订单,一个订单只从属于一个用户
    2. 一对一查询的需求:查询一个订单,与此同时查询出该订单的所属用户
      在这里插入图片描述
  2. 一对一查询语句

    1. 查看 orders 表数据
      在这里插入图片描述

    2. 查看 user 表数据
      在这里插入图片描述

    3. 编写一对一查询语句并执行:

      select * from orders o;
      select * from user u where u.id = 查询出的订单中的 uid;
      

      在这里插入图片描述

  3. MyBatis 实现一对一

    1. 编写 Orders 实体类

      public class Orders {
          private Integer id;
          private String ordertime;
          private Double total;
          private User user;
          // set、get、toString 方法省略。。。
      }
      
    2. 编写 User 实体类

      public class User {
         private Integer id;
         private String username;
         // set、get、toString 方法省略。。。
      }
      
    3. 创建 OrdersDao 接口

      public interface OrdersDao {
          @Results({
                  // 指定 Orders实体类 和 orders 表的映射
                  @Result(property = "id",column = "id"),
                  // 指定 Orders实体类 和 orders 表的映射
                  @Result(property = "ordertime",column = "ordertime"),
                  // 指定 Orders实体类 和 orders 表的映射
                  @Result(property = "total",column = "total"),
                  // 配置 订单和用户 一对一的关系。property配置的是Orders中的属性名,column配置的是orders表中的字段名
                  // javaType配置的是orders中uid字段关联的对象class
                  // one配置的是查询orders中uid字段关联的对象的方法
                  @Result(property = "user",column = "uid",javaType = User.class,
                          one = @One(select = "com.mfc.dao.UserDao.findUserById"))
          })
          @Select("select * from orders")
          public List<Orders> findOrders();
      }
      
    4. 创建 UserDao 接口

      public interface UserDao {
          @Select("select * from user where id=#{id}")
          public List<User> findUserById(Integer id);
      }
      
    5. 编写测试类

          @org.junit.Test
          public void test() throws Exception{
              InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              SqlSessionFactory factory = builder.build(inputStream);
              SqlSession sqlSession = factory.openSession();
              OrdersDao ordersDao = sqlSession.getMapper(OrdersDao.class);
              List<Orders> orders = ordersDao.findOrders();
              for (Orders order : orders) {
                  System.out.println(order);
              }
              sqlSession.close();
          }
      
    6. 测试结果
      在这里插入图片描述

3.一对多查询
  1. 一对多查询模型

    1. 用户表和订单表的关系为:一个用户有多个订单,一个订单只从属一个用户
    2. 一对多查询需求:查询一个用户,以此同时查询出该用户具有的订单
      在这里插入图片描述
  2. 一对多查询语句

    1. 查看 orders 表数据
      在这里插入图片描述

    2. 查看 user 表数据
      在这里插入图片描述

    3. 编写一对多查询语句并执行:

      select * from user u;
      select * from orders o where o.uid = 查询出来的用户 id;
      

      在这里插入图片描述

  3. MyBatis 实现一对多

    1. 编写 Orders 实体类
      public class Orders {
          private Integer id;
          private String ordertime;
          private Double total;
          private Integer uid;
          // set、get、toString 方法省略。。。
      }
      
    2. 编写 User 实体类
      public class User {
          private Integer id;
          private String username;
          private List<Orders> orders = new ArrayList<>();
          // set、get、toString方法省略。。。
      }
      
    3. 编写 UserDao 接口
      public interface UserDao {
          @Results({
                  // 指定 User实体类 和 user 表的映射
                  @Result(property = "id",column = "id"),
                  // 指定 User实体类 和 user 表的映射
                  @Result(property = "username",column = "username"),
                  // 配置 用户和订单 一对多的关系。property配置的是User实体类中的属性名,column配置的是user表中的字段名
                  // javaType配置的是多的一方的集合对象
                  // many配置的是查询user中id字段关联的Orders对象的方法
                  @Result(property = "orders",column = "id",javaType = List.class,
                          many = @Many(select = "com.mfc.dao.OrdersDao.findOrdersById"))
          })
          @Select("select * from user")
          public List<User> findUsers();
      }
      
    4. 编写 OrdersDao
      public interface OrdersDao {
          @Select("select * from orders where uid=#{uid}")
          public List<Orders> findOrdersById(Integer uid);
      }
      
    5. 测试类
          @org.junit.Test
          public void test() throws Exception{
              InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              SqlSessionFactory factory = builder.build(inputStream);
              SqlSession sqlSession = factory.openSession();
              UserDao userDao = sqlSession.getMapper(UserDao.class);
              List<User> users = userDao.findUsers();
              for (User user : users) {
                  System.out.println(user);
              }
              sqlSession.close();
          }
      
    6. 测试结果
      在这里插入图片描述
4.多对多查询
  1. 多对多查询模型

    • ⽤户表和⻆⾊表的关系为,⼀个⽤户有多个⻆⾊,⼀个⻆⾊被多个⽤户使⽤
    • 多对多查询的需求:查询⽤户同时查询出该⽤户的所有⻆⾊
      在这里插入图片描述
  2. 多对多查询语句

    • 查看 user 表数据
      在这里插入图片描述

    • 查看中间表 user_role 数据
      在这里插入图片描述

    • 查看 role 表数据
      在这里插入图片描述

    • 编写多对多查询语句并执行

      select * from user;
      select * from role r,user_role ur where r.id=ur.role_id and ur.user_id=⽤户的id
      

      在这里插入图片描述

  3. MyBatis 实现多对多

    • 编写 User 实体类
      public class User {
          private Integer id;
          private String username;
          private List<Role> roles = new ArrayList<>();
          // set、get、toString方法省略。。。
      }
      
    • 编写 Role 实体类
      public class Role {
          private Integer id;
          private String rolename;
          // set、get、toString方法省略。。。
      }
      
    • 编写 UserDao 接口
      public interface UserDao {
          @Results({
                  // 指定 User实体类 和 user 表的映射
                  @Result(property = "id",column = "id"),
                  // 指定 User实体类 和 user 表的映射
                  @Result(property = "username",column = "username"),
                  // 配置 用户和订单 一对多的关系。property配置的是User实体类中的属性名,column配置的是user表中的字段名
                  // javaType配置的是多的一方的集合对象
                  // many配置的是查询user中id字段关联的Orders对象的方法
                  @Result(property = "roles",column = "id",javaType = List.class,
                          many = @Many(select = "com.mfc.dao.RoleDao.findRoleByUid"))
          })
          @Select("select * from user")
          public List<User> findUsers();
      }
      
    • 编写 RoleDao 接口
      public interface RoleDao {
          @Select("select * from role r,user_role ur where r.id=ur.rid and ur.uid=#{uid}")
          public List<Role> findRoleByUid(Integer uid);
      }
      
    • 测试类
          @org.junit.Test
          public void test() throws Exception{
              InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
              SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
              SqlSessionFactory factory = builder.build(inputStream);
              SqlSession sqlSession = factory.openSession();
              UserDao userDao = sqlSession.getMapper(UserDao.class);
              List<User> users = userDao.findUsers();
              for (User user : users) {
                  System.out.println(user.getUsername());
                  List<Role> roles = user.getRoles();
                  for (Role role : roles) {
                      System.out.println(role);
                  }
                  System.out.println("====================");
              }
              sqlSession.close();
          }
      
    • 测试结果
      在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值