• Mybatis中的多表查询 多对一,一对多


    示例:用户和账户
      一个用户可以有多个账户
      一个账户只能属于一个用户(多个账户也可以属于同一个用户)
    步骤:
      1、建立两张表:用户表,账户表
        让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
      2、建立两个实体类:用户实体类和账户实体类
        让用户和账户的实体类能体现出来一对多的关系
      3、建立两个配置文件
        用户的配置文件
        账户的配置文件
      4、实现配置:
        当我们查询用户时,可以同时得到用户下所包含的账户信息
        当我们查询账户时,可以同时得到账户的所属用户信息

    定义账户信息的实体类Account 

    public class Account implements Serializable {
        private Integer id;
        private Integer uid;
        private Double money;
        
        /*get  set toString*/
    }

    User

    public class User implements Serializable {
    
        private Integer id;
        private String username;
        private String address;
        private String sex;
        private Date birthday;
      /*get  set toString*/
    }

    用户的持久层接口IuserDao:

    public interface IUserDao {
        List<User> findAll();
        User findUserById (Integer userId);
    }

    IAccountDao:

    public interface IAccountDao {
        /**
         * 查询所有账户
         * @return
         */
        List<Account> findAll();
    }

    映射配置文件IUserDao.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.mkl.dao.IUserDao">
    
        <!-- 查询所有 -->
        <select id="findAll" resultType="user">
            select * from user;
        </select>
    
        <!-- 根据id查询用户 -->
        <select id="findUserById" parameterType="int" resultType="user">
            select * from user where id = #{uid}
        </select>
    
    </mapper>

    IAccountDao.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.mkl.dao.IAccountDao">
        <!-- 查询所有账户信息-->
        <select id="findAll" resultType="Account">
            select * from account;
        </select>
    </mapper>

    主配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!-- 配置properties-->
        <properties resource="jdbcConfig.properties"></properties>
    
        <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
        <typeAliases>
            <package name="com.mkl.domain"></package>
        </typeAliases>
    
        <!--配置环境-->
        <environments default="mysql">
            <!-- 配置mysql的环境-->
            <environment id="mysql">
                <!-- 配置事务 -->
                <transactionManager type="JDBC"></transactionManager>
    
                <!--配置连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"></property>
                    <property name="url" value="${jdbc.url}"></property>
                    <property name="username" value="${jdbc.username}"></property>
                    <property name="password" value="${jdbc.password}"></property>
                </dataSource>
            </environment>
        </environments>
        <!-- 配置映射文件的位置 -->
        <mappers>
            <package name="com.mkl.dao"></package>
        </mappers>
    </configuration>

    一对一查询(多对一) 

    需求 :

    查询所有账户信息,关联查询对应用户信息。 

    注意: 

    因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询

    如果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。 

    方式一 :

    编写 Sql 语句 

    实现查询账户信息时,也要查询账户所对应的用户信息。 

    SELECT    account.*,   user.username,   user.address   

    FROM   account,   user   

    WHERE  account.uid = user.id ;

    查询结果

     定义 AccountUser 类 

    为了能够封装上面 SQL 语句的查询结果,定义 AccountCustomer 类中要包含账户信息同时还要包含用户信息

    所以我们要在定义 AccountUser 类时可以继承Account 类。 

    public class AccountUser extends Account implements Serializable {
        /*继承了Account中的信息*/
        private  String username;
        private  String address;
        
        /*get set super.toString+toString*/
    }

    账户的持久层接口 IAccountDao中添加方法

        /**
         * 查询所有账户 同时获取到当前账户的所属用户信息: 用户名称  地址
         * @return
         */
        List<AccountUser> findAllEnhance();

    在 IAccountDao.xml 文件中添加相应的的查询配置信息 

     <!--增强的查询所有账户信息, 包含账户信息, 用户名称 地址-->
     <select id="findAllEnhance" resultType="AccountUser">
         select account.*, user.username as username,user.address as address 
       from account,user
       where user.id=account.uid;
    </select>

    添加测试方法

       /**
         * 测试增强的查询所有账户信息, 包含账户信息, 用户名称 地址
         */
        @Test
        public void testFindAllAccountEnhance(){
            List<AccountUser> accountUsers=accountDao.findAllEnhance ();
            System.out.println (accountUsers);
        }

     方式二(常用):

    让用户和账户的实体类能体现出来一对多的关系

    使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。 

    一对一的关系映射 使用association标签

    在从表实体类Account中添加主表实体的对象引用

    从表实体应该包含一个主表实体的对象引用

            //从表实体应该包含一个主表实体的对象引用
            private User user;
    
            /*get set*/

    IAccountDao 接口中的方法 

       /**
         * 查询所有账户  同时获取账户的所属用户信息
         * @return
         */
        List<Account> findAll();

    修改IAccountDao.xml 文件 

    <!--定义封装account和user的resultMap-->
        <resultMap id="accountUserMap" type="account">
            <id column="aid" property="id"></id>
            <result column="uid" property="uid"></result>
            <result column="money" property="money"></result>
            <!--一对一的关系映射, 配置封装User的内容-->
            <association property="user" javaType="user">
                <id column="id" property="id"></id>
                <result column="username" property="username"></result>
                <result column="sex" property="sex"></result>
                <result column="birthday" property="birthday"></result>
                <result column="address" property="address"></result>
            </association>
        </resultMap>
    
        <!-- 查询所有账户信息-->  
        <select id="findAll" resultMap="accountUserMap">
            select user.*,account.id as aid, account.uid ,account.money
            from account,user
            where user.id=account.uid;
        </select>

    一对多查询 

    需求:

    查询所有用户信息及用户关联的账户信息。 

    分析: 

    用户信息和他的账户信息为一对多关系

    并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,我们想到了 左外连接查询 比较合适。 

    编写 SQL 语句 :

    SELECT user.*, account.id AS aid,account.uid,account.money
    FROM USER
    LEFT JOIN account
    ON user.id = account.uid ;

    User 类加入 List<Account> 

    一对多关系映射, 主表实体应该包含从表实体的集合引用

    private List<Account> accounts;
    
    /*get set*/

    持久层接口IUserDao中的查询方法 

    /** 
     * 查询所有用户,同时获取出每个用户下的所有账户信息  
    *
    @return */
    List<User> findAll();

    修改持久层接口的映射配置文件IUserDao.xml

      <resultMap id="userMap" type="user">
        <id column="id" property="id"></id>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>
        <!--封装该用户下的账户信息到List-->
        <!--collection是用于建立一对多中集合属性的对应关系, ofType用于指定集合元素的数据类型-->
        <collection property="accounts" ofType="account">
          <id column="aid" property="id"/>
          <result column="uid" property="uid"/>
          <result column="money" property="money"/>
        </collection>
      </resultMap>

    <!-- 查询所有 --> <!--<select id="findAll" resultType="user">--> <select id="findAll" resultMap="userMap"> SELECT user.*, account.id AS aid,account.uid,account.money FROM USER LEFT JOIN account ON user.id = account.uid ; </select>

    collection   用于建立一对多中集合属性的对应关系  表示关联查询结果集 

      property="accounts"  关联查询的结果集存储在 User 对象的上哪个属性。 

      ofType="account"   指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。  

  • 相关阅读:
    通过应用程序域AppDomain加载和卸载程序集(转自张逸)
    Asp.net 2.0 中获取控件输出的Html代码 (转)
    工作和学习
    查询数据库中的所有表
    观活动板房感怀
    温心之旅
    读书无用论是21世纪最大的阴谋
    我渴望女人,但我更渴望成功
    外面比家里亮
    近来,可好?
  • 原文地址:https://www.cnblogs.com/mkl7/p/10755218.html
Copyright © 2020-2023  润新知