Mybatis学习第五弹。

Mybatis-5-多表查询2

1. 多对多

1. 开发步骤

  1. 建表
  2. 创建Maven工程
  3. 添加坐标文件
  4. 编写SqlMapConfig文件
  5. 创建实体类
  6. 创建实体类对应的Dao
  7. 创建Dao对应的配置文件
  8. 编写测试类

1. 建表

  1. 模拟用户角色
  2. 分析:一个用户有多个角色(一个人有学生、儿子、朋友等角色),一个角色可以赋予给多个用户(学生可以是很多人等)
  1. 创建三张表:Role表、User表、用户角色管理表

my-5-table

2. 创建Maven工程(略)

3. 添加坐标文件

给pom文件添加:mysql,mybatis,dom4j,log4j,junit等坐标。

4. 编写SqlMapConfig文件

在resources文件夹下创建SqlMapConfig.xml,添加约束,编写MySQL的配置。

5. 创建实体类

根据创建的表,创建对应实体类User、Role

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 用户表
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 存放多一个用户多个角色
private List<Role> roles;
}
// 角色表
public class Role {
private Integer id;
private String roleName;
private String roleDesc;
private List<User> users;
}

6. 创建实体类对应的Dao

根据需求编写抽象方法

1
2
3
4
public interface RoleDao {
// 查询所有角色
List<Role> findAll();
}
1
2
3
4
public interface UserDao {
// 查询所有用户
List<User> findAll();
}

7. 创建Dao对应配置文件

resources下创建top/tobing/dao(与包名对应)目录,在目录下创建dao对应配置文件

1
2
3
4
5
6
<mapper namespace="top.tobing.dao.UserDao">
<!--数据库表名与对应实体类一致-->
<select id="findAll" resultType="top.tobing.domain.User">
SELECT * from user;
</select>
</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
<mapper namespace="top.tobing.dao.RoleDao">
<!--建立数据库【表列名】以及对应的【实体类字段】关系-->
<resultMap id="roleMap" type="top.tobing.domain.Role">
<id column="id" property="id"/>
<result column="role_name" property="roleName"/>
<result column="role_desc" property="roleDesc"/>
</resultMap>
<!--数据库表名与对应实体类不一致-->
<select id="findAll" resultMap="roleMap">
SELECT * from role ;
</select>
</mapper>

  • 注意:由于Role表与数据库的表名称不一致,因此需要通过建立resutlMap关联数据库表列名和实体类字段名称。

resultMap对应关系

8. 编写测试类测试

test目录下,创建top.tobing.test包,创建对应Dao的测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 通用初始化
public class RoleDaoTest {
private InputStream in;
private SqlSession session;
private RoleDao roleDao;

/**
* 初始化方法
*/
@Before // 在方法执行前执行
public void init(){
try{
//1.读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建工厂类
SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
//3.生产SqlSession对象
session = factory.openSession();
//4.获取代理对象
roleDao = session.getMapper(RoleDao.class);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 释放资源
*/
@After // 在方法执行之后执行
public void destroy() throws IOException {
session.commit(); // 此处记得提交事务
session.close();
in.close();
}
1
2
3
4
5
6
7
8
// RoleDao
@Test
public void findAll(){
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println(role);
}
}
1
2
3
4
# 查询结果
Role{id=1, roleName='院长', roleDesc='管理整个学院'}
Role{id=2, roleName='总裁', roleDesc='管理整个公司'}
Role{id=3, roleName='校长', roleDesc='管理整个学院'}

9. 案例实现多对多查询

  1. 开发步骤

    1. 业务需求
    2. 根据业务需求分析出SQL语句
    3. 编写Dao、Dao配置文件
    4. 测试方法
    5. 检验结果
  2. 需求一

    需求:实现查询所有角色,包含其对应的用户信息

    1. 编写SQL
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SELECT 
    r.*,
    u.id uid, -- 给id起别名,防止查询得到的表的结果冲突
    u.username,
    u.birthday,
    u.sex,
    u.address
    FROM
    role r
    INNER JOIN
    user_role ur
    ON (ur.rid = r.id)
    INNER JOIN
    USER u
    ON (ur.uid = u.id ) -- 条件

    1. 编写Dao接口
    1
    2
    3
    4
    public interface RoleDao {
    List<Role> findAll();
    }

    1. 编写Dao对应配置文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <mapper namespace="top.tobing.dao.RoleDao">
    <!--建立数据库【表列名】以及对应的【实体类字段】关系-->
    <resultMap id="roleMap" type="top.tobing.domain.Role">
    <id column="id" property="id"/>
    <result column="role_name" property="roleName"/>
    <result column="role_desc" property="roleDesc"/>
    <collection property="users" ofType="top.tobing.domain.User">
    <id column="uid" property="id"/>
    <result column="username" property="username"/>
    <result column="birthday" property="birthday"/>
    <result column="sex" property="sex"/>
    <result column="address" property="address"/>
    </collection>
    </resultMap>
    <!--数据库表名与对应实体类一致-->
    <select id="findAll" resultMap="roleMap">
    SELECT
    r.id,
    r.`role_desc`,
    r.`role_name`,
    u.id uid, -- 给id起别名,防止查询得到的表的结果冲突
    u.username,
    u.birthday,
    u.sex,
    u.address
    FROM
    role r
    INNER JOIN
    user_role ur
    ON (ur.rid = r.id)
    INNER JOIN
    USER u
    ON (ur.uid = u.id )
    </select>
    </mapper>

    1. 测试
    1
    2
    3
    4
    5
    6
    7
    8
    public void findAll(){
    List<Role> roles = roleDao.findAll();
    for (Role role : roles) {
    System.out.println("-------------------------");
    System.out.println(role);
    }
    }

    1. 检测结果
    1
    2
    3
    4
    5
    -------------------------
    Role{id=1, roleName='院长', roleDesc='管理整个学院', users=[User{id=41, username='Tobing', birthday=null, sex='男', address='四川', roles=null}, User{id=45, username='张无忌', birthday=null, sex='男', address='广东', roles=null}]}
    -------------------------
    Role{id=2, roleName='总裁', roleDesc='管理整个公司', users=[User{id=41, username='Tobing', birthday=null, sex='男', address='四川', roles=null}]}

  3. 需求二

    查询所有的用户,包含其角色

    1. SQL语句

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      SELECT 
      u.*,
      r.`id`,
      r.`role_desc`,
      r.`role_name`
      FROM
      USER u
      INNER JOIN
      user_role ur
      ON (ur.uid = u.`id`)
      INNER JOIN
      role r
      ON (r.`id` = ur.`rid`)

    2. Dao接口

      1
      2
      3
      4
      5
      6
      7
      8
      public interface UserDao {
      /**
      * 查询所有用户
      * @return
      */
      List<User> findAll();
      }

    3. Dao接口配置文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      <mapper namespace="top.tobing.dao.UserDao">
      <resultMap id="userMap" type="top.tobing.domain.User">
      <id column="id" property="id"/>
      <result column="username" property="username"/>
      <result column="birthday" property="birthday"/>
      <result column="sex" property="sex"/>
      <result column="address" property="address"/>
      <collection property="roles" ofType="top.tobing.domain.Role">
      <id column="id" property="id"/>
      <result column="role_desc" property="roleDesc"/>
      <result column="role_name" property="roleName"/>
      </collection>
      </resultMap>
      <!--数据库表名与对应实体类一致-->
      <select id="findAll" resultMap="userMap">

      SELECT
      u.*,
      r.`id`,
      r.`role_desc`,
      r.`role_name`
      FROM
      USER u
      INNER JOIN
      user_role ur
      ON (ur.uid = u.`id`)
      INNER JOIN
      role r
      ON (r.`id` = ur.`rid`)
      </select>
      </mapper>


    4. 测试

    5. 检验

      1
      2
      3
      4
      5
      -------------
      User{id=41, username='Tobing', birthday=null, sex='男', address='四川', roles=[Role{id=41, roleName='院长', roleDesc='管理整个学院', users=null}]}
      -------------
      User{id=45, username='张无忌', birthday=null, sex='男', address='广东', roles=[Role{id=45, roleName='院长', roleDesc='管理整个学院', users=null}]}

总结

  1. 多表查询的难点在于把需求转换为SQL语句
  2. 把SQL写出来,根据查询得到的数据,可以轻易写出Dao.xml配置文件。

评论