Mybatis關聯查詢(一對多,多對一)


mybatis關聯查詢(一對多和多對一)

1 創建DBUtils工具類

public class DBUtils {
    private static SqlSessionFactory factory = null;
    static {
        try {
            String mybatis_config = "mybatis-config.xml";
            InputStream in = Resources.getResourceAsStream(mybatis_config);
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 獲取SqlSession
    public static SqlSession getSqlSession() {
        return factory.openSession(true);
    }
    // 獲取mapper
    public static <T> T getMapper(Class<T> mapper) {
        return getSqlSession().getMapper(mapper);
    }
}

2 准備數據

用戶和賬戶兩個表

用戶表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用戶名',
  `age` int(11) DEFAULT NULL COMMENT '年齡',
  `address` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

賬戶表

DROP TABLE IF EXISTS `account`;
CREATE TABLE `account`  (
  `id` int(11) NOT NULL,
  `uid` int(11) DEFAULT NULL COMMENT '用戶id',
  `money` double(20, 0) DEFAULT NULL COMMENT '賬戶余額',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

插入用戶數據

INSERT INTO `user` VALUES (1, '張三', 18, '河北');
INSERT INTO `user` VALUES (2, '李四', 29, '北京');
INSERT INTO `user` VALUES (3, '王五', 30, '天津');
INSERT INTO `user` VALUES (4, '趙六', 28, '廣州');
INSERT INTO `user` VALUES (5, '楊七', 88, '上海');

插入賬戶數據

INSERT INTO `account` VALUES (1, 1, 1000);
INSERT INTO `account` VALUES (2, 1, 3000);
INSERT INTO `account` VALUES (3, 3, 5000);

3 mybatis一對多查詢

ResultMap格式:

<resultMap id="唯一的標識" type="映射的pojo對象">    
    <id column="表的主鍵字段(數據庫表中的字段)" jdbcType="字段類型" property="映射pojo對象的主鍵屬性(實體類中的屬性)" />    
    <result column="表字段名或者別名(定義別名后不是能原來的字段名)" jdbcType="字段類型" property="映射到pojo對象的一個屬性(實體類中的屬性)"/> 
     <!--多個標簽<result>...-->
    <!-- 一對多用collection標簽-->
    <collection property="pojo的集合屬性名(實體類中多的一方的集合)" ofType="集合中的pojo對象的類型">        
        <id column="主鍵字段" jdbcType="字段類型" property="集合中pojo對象的主鍵屬性" />        
        <result column="表字段名或者別名" jdbcType="字段類型" property="集合中的pojo對象的屬性" /> 
        <!--多個標簽<result>...-->
    </collection>
</resultMap>

案例

一個用戶可以有多個賬戶, 查詢所有的用戶,

用戶類

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String address;
    //一對多映射集合
    private List<Account> accounts;
}

賬戶類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    private  Integer id;
    private  Integer uid;
    private Double money;
}

實現UserMapper接口

public interface UserMapper {
    List<User> findAllUser();
}

方案一:聯表查詢(按照結果嵌套處理)

<mapper namespace="com.tedu.dao.UserMapper">
    <resultMap id="userAccountMap" type="user">
        <id column="uid" property="id"/>
        <result column="uname" property="name"/>
        <result column="uage" property="age"/>
        <result column="uaddress" property="address"/>
        <collection property="accounts" javaType="ArrayList" ofType="Account">
            <id column="aid" property="id"/>
            <result column="auid" property="uid"/>
            <result column="amoney" property="money"/>
        </collection>
    </resultMap>
    <select id="findAllUser" resultMap="userAccountMap">
        select
        u.id uid,
        u.name uname,
        u.age uage,
        u.address uaddress,
        a.id aid,
        a.uid auid,
        a.money amoney
        from user u
        left  join account a
        on u.id =a.uid;
    </select>

方案二: 按查詢嵌套處理

<select id="findAllUser" resultMap="userAccountMap">
    select * from user
</select>
<select id="findAccountById" resultType="Account">
    select  * from account where uid =#{id}
</select>
<resultMap id="userAccountMap" type="user">
    <!-- 數據庫的字段名和pojo對象中的屬性名一致,可以不用映射,但是要再次基於id執行嵌套查詢,則需將id表明.將查詢結果封裝-->
      <id property="id" column="id"/>
    <collection column="id" property="accounts" ofType="Account" javaType="ArrayList" select="findAccountById"/>
</resultMap>

方案一二測試如下

// 查詢所有的用戶
@Test
    public void test1() {
        UserMapper mapper = DBUtil.getMapper(UserMapper.class);
        List<User> allUser = mapper.findAllUser();
        for (User user : allUser) {
            System.out.println(user.getId()+","+user.getName()+","+user.getAddress()+","+user.getAge());
            System.out.println(user.getAccounts());

        }
    }

測試結果如下:

1,張三,河北,18
[Account(id=1, uid=1, money=1000.0, user=null), Account(id=2, uid=1, money=3000.0, user=null)]
2,李四,北京,29
[]
3,王五,天津,30
[Account(id=3, uid=3, money=5000.0, user=null)]
4,趙六,廣州,28
[]
5,楊七,上海,88
[]

4 mybatis多對一查詢

resultMap格式:

<resultMap id="唯一的標識" type="映射的pojo對象">    
    <id column="表的主鍵字段" jdbcType="字段類型" property="映射pojo對象的主鍵屬性" />    
    <result column="表字段名或者別名" jdbcType="字段類型" property="映射到pojo對象的一個屬性"/> 
     <!--多個標簽<result>...-->
    <association property="pojo的對象屬性名" javaType="引用配型">        
        <id column="主鍵字段" jdbcType="字段類型" property="集合中pojo對象的主鍵屬性" />        
        <result column="表字段名或者別名" jdbcType="字段類型" property="集合中的pojo對象的屬性" /> 
        <!--多個標簽<result>...-->
    </association>
</resultMap>

案例

用戶類

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String address;
}

賬戶類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    private  Integer id;
    private  Integer uid;
    private Double money;
    //多對一映射
    private User user;
}

AccountMapper類

//查詢每個賬戶所對應的用戶
public interface AccountMapper {
    List<Account> findAllAccount();
}

方案一:按照結果處理

<mapper namespace="com.tedu.dao.AccountMapper">
    <resultMap id="accountUserMap" type="Account">
        <id column="aid" property="id"/>
        <result column="auid" property="uid"/>
        <result column="amoney" property="money"/>
        <association property="user" javaType="User">
            <id column="uid" property="id"/>
            <result column="uname" property="name"/>
            <result column="uage" property="age"/>
            <result column="uaddress" property="address"/>
        </association>
    </resultMap>
    <select id="findAllAccount" resultMap="accountUserMap">
        select
        a.id aid,
        a.uid auid,
        a.money amoney,
        u.id uid,
        u.name uname,
        u.age uage,
        u.address uaddress
        from account a
        left join user u
        on a.uid =u.id;
    </select>

</mapper>

方案二:按查詢嵌套

<select id="findAllAccount" resultMap="AccountUserMap">
    select * from account
</select>
<select id="findUserById" resultType="User">
    select  * from user where id =#{uid}
</select>
<resultMap id="AccountUserMap" type="Account">
     <!-- 數據庫的字段名和pojo對象中的屬性名一致,可以不用映射,但是要再次基於uid執行嵌套查詢,則需將uid表明.將u查詢結果封裝-->
    <id property="uid" column="uid"/>
    <association property="user" javaType="User" select="findUserById" column="uid"/>
</resultMap>

方案一二測試如下

//查詢多(一)個賬戶對應一個用戶
@Test
    public void test2() {
        AccountMapper mapper = DBUtil.getMapper(AccountMapper.class);
        List<Account> allAccount = mapper.findAllAccount();
        for (Account account : allAccount) {
            System.out.println(account);
        }
    }

測試結果如下:

Account(id=1, uid=null, money=1000.0, user=User(id=1, name=張三, age=18, address=河北, accounts=null))
Account(id=2, uid=null, money=3000.0, user=User(id=1, name=張三, age=18, address=河北, accounts=null))
Account(id=3, uid=null, money=5000.0, user=User(id=3, name=王五, age=30, address=天津, accounts=null))

5 總結

一對多查詢時使用collection

多對一查詢時使用association


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM