美文网首页
Mybatis-4.关联查询

Mybatis-4.关联查询

作者: Blacol | 来源:发表于2022-04-28 16:01 被阅读0次

一对一查询

需求:一个用户只能有一个身份证信息,查询所有用户的身份证信息和用户信息以及查询指定用户的身份证信息和用户信息。

  1. 创建表Idcard并录入数据
    create table idCard
    (
      id       int auto_increment
          primary key,
      idNumber varchar(18) null,
      address  text        null,
      birth    date        null,
      constraint idCard_int_uindex
          unique (id)
    );
    INSERT INTO mybatisLesson.idCard (id, idNumber, address, birth) VALUES (1, '111555198811091111', 'A省B市C街道D小区E栋F室', '1988-11-09');
    INSERT INTO mybatisLesson.idCard (id, idNumber, address, birth) VALUES (2, '111555199101091112', 'A省B市C街道D小区E栋F室', '1991-01-09');
    INSERT INTO mybatisLesson.idCard (id, idNumber, address, birth) VALUES (3, '111555200005131113', 'A省B市C街道D小区E栋F室', '2000-05-13');
    
    
  2. 创建表user并生成数据
    create table user
    (
        id     int auto_increment
            primary key,
        name   varchar(15)   null,
        age    int default 1 null,
        idCard int           null,
        constraint user_id_uindex
          unique (id),
      constraint user_idCard_id_fk
        foreign key (idCard) references idCard (id)
            on update cascade on delete cascade
    );
    INSERT INTO mybatisLesson.user (id, name, age, idCard) VALUES (1, '张三', 34, 1);
    INSERT INTO mybatisLesson.user (id, name, age, idCard) VALUES (2, '李四', 31, 2);
    INSERT INTO mybatisLesson.user (id, name, age, idCard) VALUES (3, '王五', 22, 3);
    
  3. 创建实体类IdCard
    public class IdCard {
      private long id;
      private String idNumber;
      private String address;
      private java.sql.Date birth;
      //Getter&Setter&ToString
    }
    
  4. 创建实体类User
    public class User {
      private long id;
      private String name;
      private long age;
      private IdCard idCard;
      //Getter&Setter&ToString
    }
    
  5. 创建UserMapper
    @Mapper
    public interface UserMapper {
        List<User> selectAllUsers();
        List<User> selectUsersByIdards(List<IdCard> idCards);
    }
    
  6. 创建UserMapper.xml
    <mapper namespace="com.blacol.mapper.UserMapper">
    <resultMap id="userInfo" type="user">
        <id property="id" column="userId"></id>
        <result property="name" column="name"></result>
        <result property="age" column="age"></result>
        <association property="idCard" javaType="idCard">
            <id property="id" column="idcardId"></id>
            <result property="idNumber" column="idNumber"></result>
            <result property="address" column="address"></result>
            <result property="birth" column="birth"></result>
        </association>
    </resultMap>
    <select id="selectAllUsers" resultMap="userInfo">
        select user.id userId, name, age, idCard, idinfo.id idcardId, idNumber, address, birth
        from mybatisLesson.user,mybatisLesson.idCard idinfo
        where user.idCard=idinfo.id
    </select>
    <select id="selectUsersByIdards" resultMap="userInfo">
        select user.id userId, name, age, idCard, idinfo.id idcardId, idNumber, address, birth
        from mybatisLesson.user,mybatisLesson.idCard idinfo
        <where>
            idCard=idinfo.id and idinfo.id in
            <foreach collection="idCards" item="idc" open="(" separator="," close=")">
                #{idc}
            </foreach>
        </where>
    </select>
    </mapper>
    
  7. 创建Mybaits配置文件MyBatis-cfg.xml
     <configuration>
    <typeAliases>
        <package name="com.blacol.entity"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatisLesson"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.blacol.mapper"/>
    </mappers>
    </configuration>
    
  8. 创建测试类
    public class OneToOneTest {
        public OneToOneTest() throws IOException {
        }
    
        private SqlSession getSqlSession() throws IOException {
            SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
            InputStream is = Resources.getResourceAsStream("MyBatis-cfg.xml");
            SqlSessionFactory fac = builder.build(is);
            return fac.openSession(true);
        }
        private UserMapper userMapper=getSqlSession().getMapper(UserMapper.class);
        @Test
        public void test1(){
            System.out.println("获取所有用户");
            List<User> users = userMapper.selectAllUsers();
            System.out.println(users);
            System.out.println("获取Idcard-id为1,3的用户");
            List<Integer> ids=new ArrayList<>();
            ids.add(1);ids.add(3);
            List<User> users1 = userMapper.selectUsersByIdards(ids);
            System.out.println(users1);
        }
    }
    
  9. 让xml文件参与打包(略,可以看第2.1章)
  10. 运行测试类

总结:
mapper映射文件中有一个<resultMap>标签。当返回值的类中还有其他类或者其他类的数组/集合那么就需要使用resultMap。以上面的例子为例,User类中还有一个IdCard类的List,所以要使用resultMap标签来对属性和数据表列做映射。
要使用select需要将select的resultType属性改为resultMap并输入resultMap的id作为值。(不使用resultMap属性会报错)
resultMap有下列子标签:

子标签名 用途 属性
id 主键列需要使用id column:对应的数据表列
property:对应的属性
result 非主键列需要使用这个 column和property
association 另一个类的属性要通过它来确立映射关系 property:哪个属性是另一个类
javaType:另一个类是什么类(支持简写)
collection 另一个类的数组或者集合 property:哪个属性是另一个类的数组或集合
ofType:这个数组或集合是什么类型的

以上面的例子为例:

 <resultMap id="userInfo" type="user">
    <id property="id" column="userId"></id>
    <result property="name" column="name"></result>
     <result property="age" column="age"></result>
      <association property="idCard" javaType="idCard">
          <id property="id" column="idcardId"></id>
          <result property="idNumber" column="idNumber"></result>
          <result property="address" column="address"></result>
          <result property="birth" column="birth"></result>
      </association>
 </resultMap>

resultMap的属性id是该resultMap的唯一标识(名字),type是数据类型。我们做的是User类的映射,所以type是user(也可以是com.blacol.entity.User)。
因为user表中id列是主键,它对应的是User对象中的id属性,所以property的值是id,而column并不是id,因为在查找user和idcard表时都有id列,为了避免歧义,给user.id列起了一个别名叫userId(这个是列名歧义问题,在本章后面会详细介绍该问题),所以column的值是userId而不是id。
其他属性如name和age都不是主键所以用result标签,property是name和age,column是name和age。
因为User类有一个IdCard类的对象叫idCard,所以对于idCard属性要使用association标签。association标签的property=idCad,javaType=idCard(也可以是com.blacol.entity.IdCard)。
现在关注点来到IdCard类里,因为在idcard数据表中id列是主键,所以使用id标签,property为id。又因为在user表中也有一个Id列所以起了一个别名叫idcardId,column=“idcardId”,其他的属性如idNumber,address,birth都和数据表中的列一一对应,所以直接用result即可。

使用上面的resultMap后Mybatis就可以准确的返回结果。

一对多查询

需求:一个用户可以参加多个活动,要求显示某个用户的信息以及该用户参加的活动有哪些。
继续使用一对一查询时的代码。

  1. 复制User类并起名为User2
  2. 删除User2中的idCard属性并添加activities属性以及相应的getter/setter/toString
    public User2{
      ...
      //  private IdCard idCard;
      private List<Activity> activities;
      //Getter、Setter、ToString
    }
    
  3. 创建activity表并插入数据
    create table activity
    (
    id   int auto_increment
        primary key,
    name varchar(10) null,
    constraint activity_id_uindex
        unique (id)
    );
    INSERT INTO mybatisLesson.activity (id, name) VALUES (1, '养老院义工');
    INSERT INTO mybatisLesson.activity (id, name) VALUES (2, '孤儿院义工');
    INSERT INTO mybatisLesson.activity (id, name) VALUES (3, '支教活动');
    INSERT INTO mybatisLesson.activity (id, name) VALUES (4, '一起做饭');
    
  4. 创建actjoin表并插入数据
    create table actjoin
    (
    user     int null,
    activity int null,
    constraint actjoin_activity_id_fk
        foreign key (activity) references activity (id)
            on update cascade on delete cascade,
    constraint actjoin_user_id_fk
        foreign key (user) references user (id)
            on update cascade on delete cascade
    );
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (1, 1);
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (1, 4);
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (1, 2);
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (2, 1);
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (2, 3);
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (3, 2);
    INSERT INTO mybatisLesson.actjoin (user, activity) VALUES (3, 3);
    
  5. 创建Activity、User2Mapper和User2Mapper.xml
    Activity:
    public class Activity {
      private long id;
      private String name;//Getter,Setter,ToString
    }
    
    User2Mapper
    @Mapper
    public interface User2Mapper {
      User2 selectUserJoinedActivityByUserId(int id);
    }
    
    User2Mapper.xml
    <mapper namespace="com.blacol.mapper.User2Mapper">
    <resultMap id="userWithActivity" type="user2">
        <id column="userId" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="activities" ofType="activity">
            <id column="id" property="id"></id>
            <result column="actName" property="name"></result>
        </collection>
    </resultMap>
    <select id="selectUserJoinedActivityByUserId" resultMap="userWithActivity">
        select user.id userId,user.name,activity.id,activity.name actName
        from mybatisLesson.user,mybatisLesson.activity,mybatisLesson.actjoin
        where actjoin.activity=activity.id and actjoin.user=user.id and
            user.id=#{id}
    </select>
    </mapper>
    
  6. 创建测试类-OneToMore
    public class OneToMoreTest {
    public OneToMoreTest() throws IOException {
    }
    
    private SqlSession getSqlSession() throws IOException {
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        InputStream is = Resources.getResourceAsStream("MyBatis-cfg.xml");
        SqlSessionFactory fac = builder.build(is);
        return fac.openSession(true);
    }
    private User2Mapper user2Mapper=getSqlSession().getMapper(User2Mapper.class);
    @Test
    public void test1(){
      int num=3;
      User2 users = user2Mapper.selectUserJoinedActivityByUserId(num);
      System.out.println("获取"+num+"号用户参加的活动");      
      System.out.println("姓名:"+users.getName()+"\n参加的活动:");
      users.getActivities().forEach(e-> System.out.println(e.getName()));
      }
    }
    
  7. 运行测试类
    从运行结果可以得知Mybatis自动将查询到的数据装填进数组中。

多对多查询

需求:一个用户可以参加多个活动,一个活动可以由多个用户参与。要求显示某个用户的信息、该用户参加的活动以及参加这些活动的还有哪些用户。
在一对多查询案例的基础上进行修改

  1. 修改Activity类,添加属性List<User2> users以及相应的getter,setter和tostring

    public Activity{
      ...
      private List<User2> users;
      //Getter,Setter,toString
    }
    
  2. 创建ActivityMapper和ActivityMapper.xml

    @Mapper
    public interface ActivityMapper {
        List<User2> selectUsersByActivity(@Param("active") int active
        ,@Param("user") User2 user);
    }
    
    <mapper namespace="com.blacol.mapper.ActivityMapper">
    <select id="selectUsersByActivity" resultType="user2">
        select user.id ,user.name
        from mybatisLesson.activity,mybatisLesson.actjoin,mybatisLesson.user
        where user.id=actjoin.user and activity.id=actjoin.activity
        and user.id!=#{user.id} and activity.id =#{active}
    </select>
    </mapper>
    
  3. 创建测试类MoreToMore

    public class MoreToMoreTest {
        public MoreToMoreTest() throws IOException {
        }
    
        private SqlSession getSqlSession() throws IOException {
            SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
            InputStream is = Resources.getResourceAsStream("MyBatis-cfg.xml");
            SqlSessionFactory fac = builder.build(is);
            return fac.openSession(true);
        }
        private User2Mapper user2Mapper=getSqlSession().getMapper(User2Mapper.class);
        private ActivityMapper activityMapper=getSqlSession().getMapper(ActivityMapper.class);
        @Test
        public void test1(){
            int num=1;
            User2 users = user2Mapper.selectUserJoinedActivityByUserId(num);
            System.out.println("获取"+num+"号用户参加的活动");
            System.out.println("姓名:"+users.getName()+"\n参加的活动:");
            List<Activity> activities = users.getActivities();
            for (Activity ac:activities){
                System.out.println("参加"+ac.getName()+"的还有:");
                List<User2> users1 = activityMapper.selectUsersByActivity((int) ac.getId(), users);
                users1.forEach(u-> System.out.println(u.getName()+" "));
            }
        }
    }
    
  4. 运行测试类。

相关文章

  • Mybatis-4.关联查询

    一对一查询 需求:一个用户只能有一个身份证信息,查询所有用户的身份证信息和用户信息以及查询指定用户的身份证信息和用...

  • python面试题01

    1、什么是多表关联查询,有几种多表关联的查询方式,分别是什么? 多表关联查询概念: 多表关联查询分类:1.1内连接...

  • 关联关系查询(第一讲)

    关联查询 当查询内容涉及到具有关联关系的多个表时,就需要使用关联查询。根据表与表之间的关联关系的不同,关联查询分为...

  • 关于关联查询的处理

    mybatis关联查询配置有2种:关联嵌套结果,关联嵌套查询关联的查询过程中如果关联的表可能查到很多数据,应该考虑...

  • MySQL的多表关联查询

    一、多表关联查询 多表关联查询是使用一条SQL语句,将关联的多张表的数据查询出来。 1.1 交叉查询 交叉查询就是...

  • 数据库笔记-SQL子查询

    子查询:关联查询和非关联查询 子查询是「查询」中的「查询」,就是「嵌套查询」。 以 NBA 的SQL数据库文件为例...

  • 关联查询、子查询与分页查询

    关联查询 关联关系分为一对一,一对多,多对多关系关联查询就是从多张表中查询数据,当我们使用n张表使用关联查询,至少...

  • 2018-07-12 Mybatis的一对一关联查询

    //一对一关联查询,以订单为中心 关联用户查询

  • Oracle学习(二)

    --======================================多表关联查询--查询员工编号,员工...

  • SQL必知必会(子查询)

    一、什么是关联子查询,什么是非关联子查询 子查询虽然是一种嵌套查询的形式,不过我们依然可以依据子查询是否执行多次,...

网友评论

      本文标题:Mybatis-4.关联查询

      本文链接:https://www.haomeiwen.com/subject/gytdyrtx.html