zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Docker安装
    Shell编程
    Java:字节流和字符流(输入流和输出流)
    spring中的组合模式
    MySQL:ALTER COLUMN、MODIFY COLUMN 和 CHANGE COLUMN
    springboot项目打包docker镜像maven插件
    OGNL表达式
    项目中redisTemplate设置的key,redis客户端上查询不到的问题
    spring-session-data-redis反序列化问题
    深入理解SPI机制
  • 原文地址:https://www.cnblogs.com/liqbk/p/13199987.html
Copyright © 2011-2022 走看看