Mybatis之多表查询(五)
一、公共测试环境
public class CommonTest {
private InputStream in;
private SqlSession sqlSession;
private IAccountDao accountDao;
@Before
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession(true);
//4.获取dao的代理对象
接口 = sqlSession.getMapper(接口.class);
}
@After
public void destroy()throws Exception{
//5.提交事务
// sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
}
二、创建表
user表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8
account表
CREATE TABLE `account` (
`id` int(11) NOT NULL COMMENT '账户id',
`uid` int(11) DEFAULT NULL COMMENT '用户id',
`money` double DEFAULT NULL COMMENT '金额',
PRIMARY KEY (`id`) USING BTREE,
KEY `FK_Reference_8` (`uid`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`uid`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
role表
CREATE TABLE `role` (
`ID` int(11) NOT NULL COMMENT '角色id',
`ROLE_NAME` varchar(30) DEFAULT NULL COMMENT '角色名称',
`ROLE_DESC` varchar(60) DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
user_role中间表
CREATE TABLE `user_role` (
`UID` int(11) NOT NULL COMMENT '用户id',
`RID` int(11) NOT NULL COMMENT '角色id',
PRIMARY KEY (`UID`,`RID`),
KEY `FK_Reference_10` (`RID`),
CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
三、一对一查询
一个账户对应某个用户,所以从查询账户关联查询用户为一对一查询。
如果从用户关联查询用户的账户信息则为一对多查询,一个用户有多个账户。
查询所有账户信息并关联查询账户下用户信息,为一对一查询。
方式一
定义专门的类作为输出类型便于封装查询结果集,该类包含账户信息同时包含用户信息。
1.创建Account账户实体
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//setter() getter()
}
2.创建输出类型AccountUser
public class AccountUser extends Account implements Serializable {
private String username;
private Date birthday;
private String sex;
private String address;
//setter() getter()
}
3.创建IAccountDao账户接口
public interface IAccountDao {
/**
* 查询所有账户,同时查询账户关联的用户信息
* @return
*/
List<AccountUser> findAll();
}
4.创建AccountDao.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="cn.ybzy.dao.IAccountDao">
<!-- 配置查询所有-->
<select id="findAll" resultType="accountuser">
SELECT account.*, user.username, user.address,user.birthday,user.sex FROM account, user WHERE account.uid = user.id
</select>
</mapper>
5. 执行测试
查询账户时,同时得到账户的所属用户信息
/**
* 测试查询所有
*/
@Test
public void testFindAll(){
List<AccountUser> accountusers = accountDao.findAll();
for(AccountUser au : accountusers) {
System.out.println(au);
}
}
方式二
使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。
1.修改Account账户实体类
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//从表实体包含主表实体的对象引用
private User user;
}
2.修改IAccountDao账户接口类
public interface IAccountDao {
/**
* 查询所有账户,同时查询账户关联的用户信息
* @return
*/
List<Account> findAll();
}
3.修改AccountDao.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="cn.ybzy.dao.IAccountDao">
<!-- 定义封装account和user的resultMap -->
<resultMap id="accountUserMap" type="account">
<id property="id" column="aid"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!-- 一对一的关系映射:配置封装user的内容-->
<association property="user" column="uid" javaType="user">
<id property="id" column="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</association>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="accountUserMap">
select u.*,a.id as aid,a.uid,a.money from account a , user u where u.id = a.uid;
</select>
</mapper>
4.执行测试
查询用户时,同时得到用户下所包含的账户信息
@Test
public void testFindAll(){
List<Account> accounts = accountDao.findAll();
for(Account account : accounts){
System.out.println(account);
System.out.println(account.getUser());
}
}
四、一对多查询
查询所有用户信息及用户关联的账户信息,一个用户有多个账户,为一对多查询。
1.创建User用户实体类
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//一对多关系映射:主表实体包含从表实体的集合引用
private List<Account> accounts;
}
2.创建IUserDao用户接口
public interface IUserDao {
/**
* 查询所有用户,同时查询用户关联账户信息
* @return
*/
List<User> findAll();
}
3.创建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="cn.ybzy.dao.IUserDao">
<!-- 定义User的resultMap-->
<resultMap id="userAccountMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 配置user对象中accounts集合的映射 -->
<!-- collection 是用于建立一对多中集合属性的对应关系,表示关联查询结果集
property 关联查询的结果集存储在 User 对象的上哪个属性。
ofType 用于指定集合元素的数据类型,指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。-->
<collection property="accounts" ofType="account">
<id column="aid" property="id"></id>
<result column="uid" property="uid"></result>
<result column="money" property="money"></result>
</collection>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="userAccountMap">
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>
4.执行测试
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
System.out.println(user.getAccounts());
}
}
五、多对多查询
1.创建User和Role实体类
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//多对多的关系映射:一个用户可以有多个角色
private List<User> roles;
}
public class Role implements Serializable {
private Integer roleId;
private String roleName;
private String roleDesc;
//多对多的关系映射:一个角色可以赋予多个用户
private List<User> users;
}
2.创建IUserDao与IRoleDao接口
public interface IUserDao {
/**
* 查询所有用户,同时获取到用户下所有账户的信息
* @return
*/
List<User> findAll();
}
public interface IRoleDao {
/**
* 查询所有角色
* @return
*/
List<Role> findAll();
}
3.创建IRoleDao.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="cn.ybzy.dao.IUserDao">
<!-- 定义User的resultMap-->
<resultMap id="userMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 配置角色集合的映射 -->
<collection property="roles" ofType="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
</collection>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="userMap">
select u.*,r.id as rid,r.role_name,r.role_desc from user u
left outer join user_role ur on u.id = ur.uid
left outer join role r on r.id = ur.rid
</select>
</mapper>
4.创建IRoleDao.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="cn.ybyz.dao.IRoleDao">
<!--定义role表的ResultMap-->
<resultMap id="roleMap" type="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="roleMap">
select u.*,r.id as rid,r.role_name,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id = ur.uid
</select>
</mapper>
5.查询所有用户及关联查询用户所属角色
/**
* 测试查询所有
*/
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
System.out.println(user.getRoles());
}
}
7.查询角色及关联查询角色所分配的用户
/**
* 测试查询所有
*/
@Test
public void testFindAll(){
List<Role> roles = roleDao.findAll();
for(Role role : roles){
System.out.println(role);
System.out.println(role.getUsers());
}
}