9-Mybatis 多表查询之一对多

本次案例主要以最为简单的用户和账户的模型来分析 Mybatis 多表关系。用户为 User 表,账户为 Account
表。一个用户( User )可以有多个账户( Account )。具体关系如下:
 
9-Mybatis 多表查询之一对多_第1张图片

一、一对一查询(多对一)

1.需求

查询所有账户信息,关联查询下单用户信息。
 
注意:
因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如
果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。

2.方式一 (定义专门的 po 类作为输出类型

a.定义账户信息的实体类

@Data
public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
}

b.编写 Sql 语句

实现查询账户信息时,也要查询账户所对应的用户信息。
SELECT
account.*,
user.username,
user.address
FROM
account,
`user`
WHERE account.uid = user.id;

MySQL 中测试的查询结果如下:

c.定义 AccountUser

为了能够封装上面 SQL 语句的查询结果,定义 AccountUser 类中要包含账户信息同时还要包含用户信
息,所以我们要在定义 AccountUser 类时可以继承 Account 类。
 
@Data
public class AccountUser extends Account implements Serializable {
    private String username;
    private String address;
}

d.定义账户的持久层 Dao 接口

public interface IAccountDao {
    /**
     * 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
     * @return
     */
    List findAll();
}

e.定义 IAccountDao.xml 文件中的查询配置信息




    
    
注意:因为上面查询的结果中包含了账户信息同时还包含了用户信息,所以我们的返回值类型 returnType
的值设置为 AccountUser 类型,这样就可以接收账户信息和用户信息了。

f.创建 AccountTest 测试类

/**
 * @ClassName: AccountTest
 * @Author: linxin
 * @Date: 2021/6/13 19:12
 * @Company: http://www.oesoft.cn
 * @Description: 一对多账户的操作
 */
public class AccountTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IAccountDao accountDao;

    @Before//在测试方法执行之前执行
    public void init() throws Exception {
        //1.读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.创建 SqlSession 工厂对象
        factory = builder.build(in);
        //4.创建 SqlSession 对象
        session = factory.openSession();
        //5.创建 Dao 的代理对象
        accountDao = session.getMapper(IAccountDao.class);
    }

    @After//在测试方法执行完成之后执行
    public void destroy() throws Exception {
        session.commit();
        //7.释放资源
        session.close();
        in.close();
    }

    @Test
    public void testFindAll() {
        //6.执行操作
        List accountusers = accountDao.findAll();
        for (AccountUser au : accountusers) {
            System.out.println(au);
        }
    }
}

g.小结

定义专门的 po 类作为输出类型,其中定义了 sql 查询结果集所有的字段。此方法较为简单,企业中使用普
遍。

3.方式二(定义专门的 resultMap 用于映射一对一查询结果

使用 resultMap ,定义专门的 resultMap 用于映射一对一查询结果。
通过面向对象的 (has a) 关系可以得知,我们可以在 Account 类中加入一个 User 类的对象来代表这个账户
是哪个用户的。
 

a.修改 Account

Account 类中加入 User 类的对象作为 Account 类的一个属性。

private User user;

b.修改 AccountDao 接口中的方法

/**
* 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
* @return
*/
List findAll();
注意:第二种方式,将返回值改 为了 Account 类型。
因为 Account 类中包含了一个 User 类的对象,它可以封装账户所对应的用户信息。

c.重新定义 IAccountDao.xml 文件




    
    
        
        
        
        
        
            
            
            
            
            
        
    
    

d.在 AccountTest 类中修改测试方法

@Test
    public void testFindAll() {
        List accounts = accountDao.findAll();
        for(Account au : accounts) {
            System.out.println(au);
            System.out.println(au.getUser());
        } }

二、一对多查询

需求:
查询所有用户信息及用户关联的账户信息。
分析:
用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息
查询出来,我们想到了左外连接查询比较合适。

1.编写 SQL 语句

SELECT
u.*, acc.id id,
acc.uid,
 acc.money
FROM
`user` u
LEFT JOIN account acc ON u.id = acc.uid;

9-Mybatis 多表查询之一对多_第2张图片

2.User 类加入 List

private List accounts; 

3.用户持久层 Dao 接口中加入查询方法

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

4.用户持久层 Dao 映射文件配置


        
        
        
        
        
        
        
            
            
            
        
    
    
    
collection
部分定义了用户关联的账户信息。表示关联查询结果集
property = "accounts"
关联查询的结果集存储在 User 对象的上哪个属性。
ofType = "account"
指定关联查询的结果集中的对象类型即 List 中的对象类型。此处可以使用别名,也可以使用全限定名。

5.测试方法

 @Test
    public void testFindAllWithAccounts() {
        //6.执行操作
        List users = userDao.findAllWithAccounts();
        for(User user : users) {
            System.out.println("-------每个用户的内容---------");
            System.out.println(user);
            System.out.println(user.getAccounts());
        } }

 

你可能感兴趣的:(mybatis)