• MyBatis 之 一对一、一对多、多对多


    一、前言

    自己用mybatis做项目的时候,有时候会对MyBatis 的一对一,一对多,以及多对多的关系映射,学习的时候没有过深研究就草草了之了,因此会感到困惑,在此梳理下它的映射关系。

    二、一对一 和 一对多

    一对一和一对多比较简单,可以在一起讲。本次demo打算使用 用户表(User),地址表(Address),汽车表(Car)来表述。即:一个用户只有一个地址,两者的关系是一对一;一对多的话,即一个用户可以有多辆车,两者的关系是一对多。

    1.springboot项目搭建

    1.1、项目配置

    ​ 本节的重点不在于springboot的pom.xml 导入了哪些包,mybatis如何配置,仅仅简单说下:

    pom.xml 中添加 : mybatis-spring-boot-starter 1.3.2mysql-connector-java 两个。

    application.yml 配置:

    server:
      port: 8080
    
    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
        driver-class-name: com.mysql.cj.jdbc.Driver
    
    mybatis:
      mapper-locations: classpath:mapping/*Mapper.xml
      type-aliases-package: com.example.entity
    
    #showSql
    logging:
      level:
        com:
          example:
            mapper : debug
    
    
    1.2、项目结构

    本次demo会创建controller、service、service.imp、mapper、entity等包,以及在resources文件夹下创建mapping文件夹存放mybatis的xml文件。三个表,创建三个控制层,以及也在其他各层创建其对应的接口类和接口实现类等等,在此略过。看下项目结构:

    springboot-mybatis

    1.3 实体类代码(无get和set方法,记得自己添加)
    public class User {
    
        private Long id;
    
        private String nick_name ; // 用户昵称
    
        private Address address;    //地址信息,和用户是一对一的关系
    
        private List<Car> cars;     //用户拥有的车,和用户是一对多的关系
        //TODO:无参构造,有参构造,get和set方法
    }
    //----------------------------------------------
    public class Address implements Serializable {
    
        private Long id;               // ID
    
        private String province;    //省市
    
        private String city;        // 城市
        //TODO:无参构造,有参构造,get和set方法
    }
    //----------------------------------------------
    public class Car implements Serializable {
    
        private Long id;    // id
    
        private String color;   // 颜色
    
        private String name;    // 名称
    
        private User user ; // 用户
        //TODO:无参构造,有参构造,get和set方法
    }
    
    1.4、UserMapper.xml 演示一对一、一对多

    我们以用户为例,通过用户id ,获取用户的id,nick_name,地址的id、省市、城市;(一对一)以及用户所拥有的的车辆cars列表,

    列表里是Car实体类 的每条信息。如图:

    image-20210313225925119

    我们在UserController 编写 getOneAddress()方法,粘贴下控制层方法,直接到UserMapper.xml 中

    @Autowired
    private AddressService addressService ;
    
    @RequestMapping("getOneAddress")
    public Address getOneAddress(Long id){
    
        Address address = addressService.getOneAddress(id);
    
        return address ;
    }
    

    UserMapper.xml 代码 :

    <resultMap id="BaseMap" type="com.dzbiao.springbootmybatis.entity.User">
        <id property="id" column="id" />
        <result property="nick_name" column="nick_name" />
        <!--一对一-->
        <association property="address" javaType="com.dzbiao.springbootmybatis.entity.Address" >
            <id property="id" column="id" />
            <result property="city" column="city" />
            <result property="province" column="province" />
        </association>
        <!--一对多-->
        <!--JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是 映射到list集合属性中pojo的类型 -->
        <collection property="cars" ofType="com.dzbiao.springbootmybatis.entity.Car" javaType="java.util.ArrayList">
            <id property="id" column="c_id" />
            <result property="color" column="color" />
            <result property="name" column="name" />
        </collection>
    
    </resultMap>
    
    <select id="getOneUser" resultMap="BaseMap">
        select user.*,address.* ,car.id as c_id ,car.color,car.name,car.user_id
        from user,address,car
        where user.id = #{id} and user.address_id = address.id and user.id = car.user_id
    </select>
    

    上述代码解释一下 :

    首先我们id = "getOneUser"的select方法的结果映射时BaseMap,我们通过association标签和另一张表Address进行关联映射,property的值即是User表中 的 private Address address; 属性;

    mybatis-user-mapping

    javaType 用来指定对象类型,在这指代的是address前面的Address类型,包括下面collection标签中的javaType,都是实体类该属性属于什么类型。比如address前面是Address类型,cars前面是List数组类型,所以下面collection标签中JavaType的值为java.util.ArrayList

    mybatis-list-mapping

    ofType指定的是 映射到list集合属性中pojo的类型 。

    这里需要注意的是: select方法中的sql语句,查询的数据,表的id可能会相同,这样查询出的多条数据就无法映射到collection列表中,所以要在此改下查询结果集的属性,改成别名进行映射。

    mapping-mybatis

    三、多对多映射

    我们使用常见的文章(article)和分类(category)进行多对多讲解。一篇文章有多个分类,一个分类下拥有多篇文章。

    CREATE TABLE `article`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    INSERT INTO `article` VALUES (1, 'Java基础', '这是一个java的示例文章');
    INSERT INTO `article` VALUES (2, 'Python学习', 'Python学习示例');
    INSERT INTO `article` VALUES (3, 'Springboot学习', 'springboot学习案例');
    CREATE TABLE `category`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    INSERT INTO `category` VALUES (1, 'Java');
    INSERT INTO `category` VALUES (2, 'Python ');
    INSERT INTO `category` VALUES (3, 'HTML');
    INSERT INTO `category` VALUES (4, 'JavaScript');
    INSERT INTO `category` VALUES (5, 'Linux');
    INSERT INTO `category` VALUES (6, 'CSS');
    INSERT INTO `category` VALUES (7, 'Go');
    -- ----------------------------
    -- 中间表
    -- ----------------------------
    CREATE TABLE `article_category`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `article_id` int(11) NULL DEFAULT NULL,
      `category_id` int(11) NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of article_category
    -- ----------------------------
    INSERT INTO `article_category` VALUES (1, 1, 1);
    INSERT INTO `article_category` VALUES (2, 1, 3);
    INSERT INTO `article_category` VALUES (3, 1, 4);
    INSERT INTO `article_category` VALUES (4, 1, 6);
    INSERT INTO `article_category` VALUES (5, 2, 2);
    INSERT INTO `article_category` VALUES (6, 2, NULL);
    INSERT INTO `article_category` VALUES (7, 2, 4);
    INSERT INTO `article_category` VALUES (8, 2, 6);
    INSERT INTO `article_category` VALUES (9, 3, 1);
    

    实体类 Article 和Category:

    public class Article implements Serializable {
    
        private Integer id ; // 文章ID
    
        private String title ; // 文章标题
    
        private String content ; // 文章内容
    
        private List<Category> categories ; // 分类列表
        
    }
    
    public class Category implements Serializable {
    
        private Integer id ;// 分类ID
    
        private String name ; // 分类名称
    
        private List<Article>  articles ; // 文章列表
    }
    

    多对多映射,可以看成两个一对多。一个文章实体类有一个分类的列表,而分类的实体类则也有一个文章列表。

    直接看 ArticleMapper.xml 中的代码 :

    many-to-many

    同样道理,当我们想要获取一个分类下的文章列表时,和上面一样。

    many-to-many-

    这儿也使用了左连接进行关联映射查询。

    四、demo地址 :

    链接:https://pan.baidu.com/s/1YF4Ys0OXaPW1uoRbdrMq3A 提取码:p3ju

  • 相关阅读:
    Helpful SharePoint JavaScript functions
    JQuery操作SharePoint Web Services之查询列表数据
    强大的SPGridView
    如何在 MOSS 2007 启用 Session
    实现类似于sharepoint列表的分组统计功能
    MOSS自带SPDatePickerControl控件的使用
    Silverlight多线程技术Thread的应用
    Silverlight同步(Synchronous)调用WCF服务
    Moss2007 Customize the NewForm.aspx 自定义NewForm EditForm页面
    Multiple Attachment custom control in Sharepoint
  • 原文地址:https://www.cnblogs.com/duanxiaobiao/p/14531116.html
Copyright © 2020-2023  润新知