Mybatis_day3_Mybatis的多表查询

Mybatis 多表查询

  • 本次案例主要以最为简单的用户和账户的模型来分析 Mybatis 多表关系。用户为 User 表,账户为Account表。一个用户(User)可以有多个账户(Account)。具体关系如下:

在这里插入图片描述


一对一查询(多对一)

  • 需求
    • 查询所有账户信息,关联查询下单用户信息。
  • 注意:
    • 因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。
方式一
  1. 定义账户信息的实体类
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;

public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public Integer getUid() {
	return uid;
}
public void setUid(Integer uid) {
	this.uid = uid;
}
public Double getMoney() {
	return money;
}
public void setMoney(Double money) {
	this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", uid=" + uid + ", money=" + money + "]";
	}
}

  1. 定义 AccountUser 类
public class AccountUser extends Account implements Serializable {
private String username;
private String address;

public String getUsername() {
	return username;
}
public void setUsername(String username) {
	this.username = username;
}
public String getAddress() {
	return address;
}
public void setAddress(String address) {
	this.address = address;
}
@Override
public String toString() {
return super.toString() + " AccountUser [username=" + username + ", 
address=" + address + "]";
	}
}

  1. 编写 Sql 语句
实现查询账户信息时,也要查询账户所对应的用户信息。
SELECT  
	account.*, 
	user.username, 
	user.address
FROM 
	account,
 	user
WHERE account.uid = user.id

  1. 定义账户的持久层 Dao 接口
public interface IAccountDao {
/**
* 查询所有账户,同时获取账户的所属用户名称以及它的地址信息
* @return
*/
List<AccountUser> findAll();
}

  1. 定义 AccountDao.xml 文件中的查询配置信息
<mapper namespace="cn.myp666.dao.IAccountDao">
<!-- 配置查询所有操作-->
<select id="findAll" resultType="accountuser">
	select a.*,u.username,u.address from account a,user u where a.uid =u.id;
</select>
</mapper>
  • 注意: 因为上面查询的结果中包含了账户信息同时还包含了用户信息,所以我们的返回值类型 returnType的值设置为 AccountUser 类型,这样就可以接收账户信息和用户信息了。

  1. 创建 AccountTest 测试类
@Test
public void testFindAll() {
//6.执行操作
	List<AccountUser> accountusers = accountDao.findAll();
	
	for(AccountUser au : accountusers) {
		System.out.println(au);
	}

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


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

    在 Account 类中加入 User 类的对象作为 Account 类的一个属性。
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//添加User对象
private User user;

public User getUser() {
	return user;
}
public void setUser(User user) {
	this.user = user;
}


public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public Integer getUid() {
	return uid;
}
public void setUid(Integer uid) {
	this.uid = uid;
}
public Double getMoney() {
	return money;
}
public void setMoney(Double money) {
	this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", uid=" + uid + ", money=" + money + "]";
	}
}

  1. 修改 AccountDao 接口中的方法

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

  1. 重新定义 AccountDao.xml 文件
<mapper namespace="cn.myp666.dao.IAccountDao">
	<!-- 建立对应关系 -->
	<resultMap type="account" id="accountMap">
		<id column="aid" property="id"/>
		<result column="uid" property="uid"/>
		<result column="money" property="money"/>
		<!-- 它是用于指定从表方的引用实体属性的 -->
		 <!--多对一的关系, property: 指的是属性的值, javaType:指的是属性的类型 -->
		<association property="user" javaType="user">
			<id column="id" property="id"/>
			<result column="username" property="username"/>
			<result column="sex" property="sex"/>
			<result column="birthday" property="birthday"/>
			<result column="address" property="address"/>
		</association>
	</resultMap>
	
<select id="findAll" resultMap="accountMap">
	select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
</select>
</mapper>

  1. 在 AccountTest 类中加入测试方法
@Test
public void testFindAll() {
	List<Account> accounts = accountDao.findAll();
	for(Account au : accounts) {
		System.out.println(au);
		System.out.println(au.getUser());
	}
}



一对多查询

  • 需求:

    • 查询所有用户信息及用户关联的账户信息。
  • 分析:

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

  1. 编写 SQL 语句
SELECT
	u.*, 
	acc.id as aid,
	acc.uid,
 	acc.money
FROM
	user u
LEFT JOIN account acc ON u.id = acc.uid

  1. User 类加入 List< Account >
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accounts;

public List<Account> getAccounts() {
	return accounts;
}
public void setAccounts(List<Account> accounts) {
	this.accounts = accounts;
}
public Integer getId() {
	return id;
}
public void setId(Integer id) {
	this.id = id;
}
public String getUsername() {
	return username;
}
public void setUsername(String username) {
	this.username = username;
}
public Date getBirthday() {
	return birthday;
}
public void setBirthday(Date birthday) {
	this.birthday = birthday;
}
public String getSex() {
	return sex;
}
public void setSex(String sex) {
	this.sex = sex;
}
public String getAddress() {
	return address;
}
public void setAddress(String address) {
	this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", birthday=" + birthday
+ ", sex=" + sex + ", address="
+ address + "]";
	}
}

  1. 用户持久层 Dao 接口中加入查询方法
List<User> findAll();

  1. 用户持久层 Dao 映射文件配置
<mapper namespace="cn.myp666.dao.IUserDao">
	<resultMap type="user" id="userMap">
		<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"/>
		<!-- 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" resultMap="userMap">
	select u.*,a.id as aid ,a.uid,a.money from user u left outer join account 
a on u.id =a.uid
</select>
</mapper>
  • collection
    部分定义了用户关联的账户信息。表示关联查询结果集
  • property=“accounts”:
    关联查询的结果集存储在 User 对象的上哪个属性里。
  • ofType=“account”:
    指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。

  1. 测试方法
@Test
public void testFindAll() {
//6.执行操作
	List<User> users = userDao.findAll();
	for(User user : users) {
		System.out.println("-------每个用户的内容---------");
		System.out.println(user);
		System.out.println(user.getAccounts());
	}
}
发布了94 篇原创文章 · 获赞 0 · 访问量 2097

猜你喜欢

转载自blog.csdn.net/qq_16836791/article/details/104779111
今日推荐