MyBatis多表查询

可以使用专门定义一个PO类作为输出类型,并在SQL中查询所有字段信息。

本文主要介绍使用resultMap,定义专门的 resultMap

一对一查询 association用法

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

字段名字段描述数据类型
id用户主键int
name用户名varchar(20)
sex性别varchar(10)
birthday出生日期date
address地址varchar(60)

账户表: account

字段名字段描述数据类型
id编号int <pk>
uid用户编号int<fk>
money金额double

通过面向对象的(has a)关系可以得知,可以在 Account 类中加入一个 User 类的对象来代表这个账户是哪个用户的。

  • 定义Account类
public class Account implements Serializable{
	private Integer id;
	private Integer uid;
	private Double money;
	//加入User对象
	private User user;
	/*此处省略getter setter方法*/
}
  • 定义User类
public class User implements Serializable{
	private Integer id;
	private String name;
	private String sex;
	private Date birthday;
	private String address;
	/*此处省略getter setter方法*/
}
  • 定义AccountDao接口,查询所有账户方法
public interface AccountDao{
	List<Account> findAll();
}

定义AccountDao.xml文件 方式一:

<mapper namespace="top.wayneliu.dao.IAccountDao">
	<!-- 建立对应关系 --> 
	<resultMap type="account" id="accountMap">
		<id column="aid" property="id"/>
		<result column="uid" property="uid"/> 
		<result column="money" property="money"/> 
		<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>

定义AccountDao.xml 方式二:

<mapper namespace="top.wayneliu.dao.IAccountDao">
	<!-- 建立user对象对应关系 --> 
	<resultMap type="user" id="userMap">
		<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"/>
	</resultMap>
	<!--建立account对象对应关系-->
	<resultMap type="account" id="accountMap">
		<id column="aid" property="id"/>
		<result column="uid" property="uid"/> 
		<result column="money" property="money"/> 
		<!--通过assosiation引入user对象的resultMap-->
		<association property="user" resultMap=“userMap”/>
	</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>

- 嵌套select 查询方式定义

这种方式是使用一条单独的select语句来加载关联的实体(本例中就是Account实体),然后在association元素中引用此select语句(注:此方法会产生N+1问题,尽量不要用嵌套的select语句)

<mapper namespace="top.wayneliu.dao.IAccountDao">
	<!-- 建立user对象对应关系 --> 
	<resultMap type="user" id="userMap">
		<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"/>
	</resultMap>
	<!--建立account对象对应关系-->
	<resultMap type="account" id="accountMap">
		<id column="id" property="id"/>
		<result column="uid" property="uid"/> 
		<result column="money" property="money"/> 
		<!--通过assosiation引入user对象的resultMap-->
		<association property="user" column="uid" select="findUserByid"/>
	</resultMap>
	<select id="findAll" resultMap="accountMap"> 
		select * from account
	</select> 
	<select id="findUserByid" parameterType="int" resultMap="userMap">
		select * from user where id = #{id}
	</select>
</mapper>

使用select嵌套方式控制台输出:

2020-03-04 15:43:27,345 1332   [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]
2020-03-04 15:43:27,387 1374   [           main] DEBUG ayneliu.dao.AccountDao.findAll  - ==>  Preparing: select * from account 
2020-03-04 15:43:27,461 1448   [           main] DEBUG ayneliu.dao.AccountDao.findAll  - ==> Parameters: 
2020-03-04 15:43:27,519 1506   [           main] DEBUG iu.dao.AccountDao.findUserByid  - ====>  Preparing: select * from user where id = ? 
2020-03-04 15:43:27,520 1507   [           main] DEBUG iu.dao.AccountDao.findUserByid  - ====> Parameters: 41(Integer)
2020-03-04 15:43:27,564 1551   [           main] DEBUG iu.dao.AccountDao.findUserByid  - <====      Total: 1
2020-03-04 15:43:27,565 1552   [           main] DEBUG iu.dao.AccountDao.findUserByid  - ====>  Preparing: select * from user where id = ? 
2020-03-04 15:43:27,565 1552   [           main] DEBUG iu.dao.AccountDao.findUserByid  - ====> Parameters: 45(Integer)
2020-03-04 15:43:27,610 1597   [           main] DEBUG iu.dao.AccountDao.findUserByid  - <====      Total: 1
2020-03-04 15:43:27,612 1599   [           main] DEBUG ayneliu.dao.AccountDao.findAll  - <==      Total: 3
Account{id=1, uid=41, money=1000.0, user=User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}}
Account{id=2, uid=45, money=1000.0, user=User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}}
Account{id=3, uid=41, money=2000.0, user=User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}}
2020-03-04 15:43:27,613 1600   [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]
2020-03-04 15:43:27,656 1643   [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]
2020-03-04 15:43:27,656 1643   [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 511473681 to pool.

使用select嵌套的方式可以看出,MyBtis首先查询了账户表,之后多次查询用户表。

一对多查询 collection用法

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

  • 在User类中加入List<Account>属性
public class User implements Serializable{
	private Integer id;
	private String name;
	private String sex;
	private Date birthday;
	private String address;
	private List<Account> accounts
	/*此处省略getter setter方法*/
}
  • 定义UserDao接口和查询所有用户及账户方法
public interface UserDao {
	public List<User> findAll();
}
  • 定义持久层Dao映射文件配置
<mapper namespace="top.wayneliu.dao.UserDao">
    <resultMap  type="account" id="accountMap">
        <id column="aid" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
    </resultMap>
    <resultMap type="user" id="userMap">
        <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"/>
        <collection property="accounts" resultMap="accountMap"/>
    </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>

控制台输出:

2020-03-04 16:19:49,571 1634   [           main] DEBUG p.wayneliu.dao.UserDao.findAll  - ==>  Preparing: select u.*,a.id as aid ,a.uid,a.money from user u left outer join account a on u.id =a.uid 
2020-03-04 16:19:49,662 1725   [           main] DEBUG p.wayneliu.dao.UserDao.findAll  - ==> Parameters: 
2020-03-04 16:19:49,738 1801   [           main] DEBUG p.wayneliu.dao.UserDao.findAll  - <==      Total: 7
User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京', accounts=[Account{id=1, uid=41, money=1000.0, user=null}, Account{id=3, uid=41, money=2000.0, user=null}]}
User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙', accounts=[Account{id=2, uid=45, money=1000.0, user=null}]}
User{id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙', accounts=[]}
User{id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙', accounts=[]}
User{id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京', accounts=[]}
User{id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正', accounts=[]}

涉及关键词:

association
collection

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值