表之间的关系有几种:
- 一对多
- 多对一
- 一对一
- 多对多
环境准备
- 数据库
CREATE TABLE `account` (
-> `ID` int(11) NOT NULL COMMENT '编号',
-> `UID` int(11) default NULL COMMENT '用户编号',
-> `MONEY` double default NULL COMMENT '金额',
-> PRIMARY KEY (`ID`),
-> KEY `FK_Reference_8` (`UID`),
-> CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.创建实体类Account
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 +
'}';
}
}
- 创建Dao接口
public interface IAccountDao {
List<Account> findAll();
List<AccountUser> findAccount();
}
- 创建接口配置文件
<?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.lwb.dao.IAccountDao">
<!--查询所有-->
<select id="findAll" resultType="com.lwb.domain.Account">
SELECT * FROM account
</select>
</mapper>
- 配置SqlMapConfig.xml文件中的Mapper
<mapper resource="com/lwb/dao/IAccountDao.xml"></mapper>
一对一查询
- 第一种方式:为了能够封装上面 SQL 语句的查询结果,定义 AccountCustomer 类中要包含账户信息同时还要包含用户信息,所以我们要在定义 AccountUser 类时可以继承 Account 类
- 创建AccountUser实体类继承Account类
public class AccountUser extends Account {
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() +
"username='" + username + '\'' +
", address='" + address + '\'' +
'}';
}
}
- 在接口IAccountDao创建方法
List<AccountUser> findAccount();
- 配置接口配置文件
<!--查询账户信息-->
<select id="findAccount" resultType="com.lwb.domain.AccountUser">
select account.*,user.username,user.address from user,account where user.id = account.uid;
</select>
- 测试
@Test
public void test8()throws Exception {
// 第五步:执行dao中的方法
List<AccountUser> accountUser = accountDao.findAccount();
for (AccountUser account: accountUser) {
System.out.println(account.toString());
}
}
- 第二种方式:使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。通过面向对象的(has a)关系可以得知,我们可以在 Account 类中加入一个 User 类的对象来代表这个账户是哪个用户的。
- 在Account实体类中加入User类
- 在IAcountDao接口里修改方法
- 在配置文件里面设置
<mapper namespace="com.lwb.dao.IAccountDao">
<resultMap id="AccountUser" type="com.lwb.domain.Account">
<!--建立对应关系-->
<id property="id" column="aid"></id>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!--指定从表中引用的实体类-->
<association property="user" javaType="com.lwb.domain.User">
<id property="id" column="id"></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" resultType="com.lwb.domain.Account">
SELECT * FROM account
</select>
<!--查询账户信息-->
<!--<select id="findAccount" resultType="com.lwb.domain.AccountUser">-->
<!--select account.*,user.username,user.address from user,account where user.id = account.uid;-->
<!--</select>-->
<select id="findAccount" resultMap="AccountUser">
select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
</select>
</mapper>
- 测试
@Test
public void test7()throws Exception {
// 第五步:执行dao中的方法
List<Account> accounts = accountDao.findAccount();
for (Account account: accounts) {
System.out.println(account.toString()+account.getUser());
}
}
一对多的查询
- 用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,我们想到了左外连接查询比较合适
- User 类 类入 加入
List<Account>
- 用户持久层 Dao 接口 中加入查询方法
- 用户持久层 Dao 映射文件
- collection:部分定义了用户关联的账户信息。表示关联查询结果集
- property=“accList” :关联查询的结果集存储在 User 对象的上哪个属性。
- ofType=“account” :指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
<resultMap id="UserAccount" type="com.lwb.domain.User">
<id property="id" column="id"></id>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<collection property="accounts" ofType="com.lwb.domain.Account">
<id property="id" column="aid"></id>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="UserAccount">
select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
a on u.id =a.uid
</select>
- 测试
多对多的查询
- 查询角色我们需要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。
- 数据库
CREATE TABLE `role` (
`ID` int(11) NOT NULL COMMENT '编号',
`ROLE_NAME` varchar(30) default NULL COMMENT '角色名称',
`ROLE_DESC` varchar(60) default NULL COMMENT '角色描述',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');
CREATE TABLE `user_role` (
`UID` int(11) NOT NULL COMMENT '用户编号',
`RID` int(11) NOT NULL COMMENT '角色编号',
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;
insert into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);
- 创建实体类Role,并且在user实体类中添加Role集合
public class Role implements Serializable{
private Integer id;
private String role_name;
private String role_desc;
private List<User> users;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_desc() {
return role_desc;
}
public void setRole_desc(String role_desc) {
this.role_desc = role_desc;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", role_name='" + role_name + '\'' +
", role_desc='" + role_desc + '\'' +
'}';
}
}
- 创建IRoleDao接口
public interface IRoleDao {
List<Role> findAll();
}
- 配置IRoleDao的配置文件和IUserDao的配置文件
- IRoleDao.xml
<mapper namespace="com.lwb.dao.IRoleDao">
<resultMap id="RoleUser" type="com.lwb.domain.Role">
<id property="id" column="rid"/>
<result property="role_name" column="role_name"/>
<result property="role_desc" column="role_desc"/>
<collection property="users" ofType="com.lwb.domain.User">
<id property="id" column="id"></id>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
</collection>
</resultMap>
<select id="findAll" resultMap="RoleUser">
SELECT u.*,r.id AS rid,r.role_name,r.role_desc FROM ROLE r LEFT JOIN USER_ROLE ur ON ( r.id = ur.rid) LEFT JOIN USER u ON (ur.uid = u.id)
</select>
</mapper>
- IUserDao.xml
<resultMap id="UserRole" type="com.lwb.domain.User">
<id property="id" column="id"></id>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<collection property="roles" ofType="com.lwb.domain.Role">
<id property="id" column="rid"/>
<result property="role_name" column="role_name"/>
<result property="role_desc" column="role_desc"/>
</collection>
</resultMap>
<!--查询所有用户以及他们的角色-->
<select id="findUserAndRole" resultMap="UserRole">
SELECT u.*,r.id AS rid,r.role_name,r.role_desc FROM User u LEFT JOIN USER_ROLE ur ON ( u.id = ur.uid) LEFT JOIN role r ON (ur.rid = r.id)
</select>
- 测试
- 根据角色获取角色和相应的用户信息
@Test
public void test9()throws Exception {
// 第五步:执行dao中的方法
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println("--每个角色---");
System.out.println(role);
System.out.println(role.getUsers());
}
}
- 每个用户对应的角色
@Test
public void test10()throws Exception {
// 第五步:执行dao中的方法
// List<User> users= dao.findByName("%王%");
List<User> users = dao.findUserAndRole();
for(User user:users) {
System.out.println("----每一个用户------");
System.out.println(user);
System.out.println(user.getRoles());
}
}