Mybatis-4.關聯查詢

一對一查詢

需求:一個用戶只能有一個身份證信息,查詢所有用戶的身份證信息和用戶信息以及查詢指定用戶的身份證信息和用戶信息。

  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. 運行測試類。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容