mybatis3.0 添加了association和collection标签专门用于对多个相关实体类数据进行级联查询,但仍不支持多个相关实体类数据的级联保存和级联删除操作。因此在进行实体类一对多和多对多映射表设计时,需要专门建立一个关联对象类对相关实体类的关联关系进行描述。
设计数据库表,假设现在有角色,人员,部门三级关系,其中角色对人员是多对多,人员对部门是多对一,设计中间表和表内字段实现根据部门查询所属员工,根据员工查询所属角色.
我们首先在创建一个 java 工程,工程名称为:01-mybatis-der,笔者使用的是jdk1.8下面是笔者使用的jar:
创建5张表,它们分别是部门表 department,员工表employee,角色表 role, 部门员工映射表 department_employee和员工角色映射表employee_role,一个部门可以有多个员工,一个员工可以有多个角色,一个角色也可以有多个员工。项目工程结构如下:
使用Navicat for MySQL创建表
department表
employee表
department_employee表
role表
employee_role表
每一张表的主键都是自增的
一个表对应一个实体类
部门实体类
public class Department implements Serializable {
private Integer did; //部门id
private String dname; //部门名称
private List<Employee> employees; //部门的员工
//无参构造构造,有参构造,setter,getter,toString方法这里就省略了
员工实体类
public class Employee implements Serializable {
private Integer eid; //员工id
private String ename; //员工名字
private int eage; //员工年龄
private List<Role> roles; //员工扮演的角色
//无参构造构造,有参构造,setter,getter,toString方法这里就省略了
部门员工映射实体类
public class DepartmentEmployee implements Serializable {
private Integer deId; //部门组映射id
private Integer departmentId; //部门id
private Integer employeeId; //员工id
//无参构造构造,有参构造,setter,getter,toString方法这里就省略了
角色实体类
public class Role implements Serializable {
private Integer rid; //角色id
private String rname; //角色名字
private List<Employee> employees; //这个角色的全部员工
//无参构造构造,有参构造,setter,getter,toString方法这里就省略了
员工角色映射实体类
public class EmployeeRole implements Serializable {
private Integer erId; //员工角色映射id
private Integer employeeId; // 员工id
private Integer roleId; // 角色id
//无参构造构造,有参构造,setter,getter,toString方法这里就省略了
mybatis的配置文件有主配置文件和映射配置文件,我们先写主配置文件,我把放在src目录下,文件名为mybatis.xml,其详细情况如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 指出jdbc属性文件所在位置 -->
<properties resource="jdbc.properties"/>
<!-- 注册类型别名 -->
<typeAliases>
<package name="com.haichuang.beans"/>
</typeAliases>
<!-- 注册数据源 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 注册映射文件 -->
<mappers>
<mapper resource="com/haichuang/daos/employee-mapper.xml"/>
<mapper resource="com/haichuang/daos/role-mapper.xml"/>
<mapper resource="com/haichuang/daos/department-mapper.xml"/>
<mapper resource="com/haichuang/daos/employee-role-mapper.xml"/>
<mapper resource="com/haichuang/daos/department-employee-mapper.xml"/>
</mappers>
</configuration>
mybatis通过mapper动态代理直接调用接口方法,这里我们需要创建一个接口
Employee实体类对应的接口
package com.haichuang.daos;
import com.haichuang.beans.Employee;
public interface IEmployeeDao {
public Employee selectEmployeeById(int eid);
}
Role实体类对应的接口
package com.haichuang.daos;
import com.haichuang.beans.Role;
public interface IRoleDao {
public Role selectRoleById(int rid);
}
EmployeeRole实体类对应的接口
package com.haichuang.daos;
import java.util.List;
import java.util.Set;
import com.haichuang.beans.Employee;
import com.haichuang.beans.Role;
public interface IEmployeeRoleDao {
public List<Role> selectRoleByEmployeeId(int eid);
public List<Employee> selectEmployeeByRoleId(int rid);
}
IEmployeeDao .java 对应的配置文件 src/com/haichuang/daos/employee-mapper.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="com.haichuang.daos.IEmployeeDao">
<!-- 员工的mapper -->
<!-- collection标签子标签select通过Role对应的映射文件来获取员工信息 -->
<resultMap type="Employee" id="employeetMapper">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="eage" property="eage"/>
<collection property="roles"
ofType="Role"
select="com.haichuang.daos.IEmployeeRoleDao.selectRoleByEmployeeId"
column="eid"/>
</resultMap>
<!-- 通过id查询员工 -->
<select id="selectEmployeeById" resultMap="employeetMapper">
select eid,ename,eage from employee where eid = #{eid}
</select>
</mapper>
IRoleDao .java 对应的配置文件 src/com/haichuang/daos/role-mapper.xml 的内容如下:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.haichuang.daos.IRoleDao">
<!-- 角色的mapper -->
<!-- collection标签子标签select通过Employee对应的映射文件来获取角色信息 -->
<resultMap type="role" id="roleMapper">
<id column="rid" property="rid"/>
<result column="rname" property="rname"/>
<collection property="employees"
ofType="Employee"
select="com.haichuang.daos.IEmployeeRoleDao.selectEmployeeByRoleId"
column="rid"/>
</resultMap>
<!-- 通过id来查询角色信息 -->
<select id="selectRoleById" resultMap="roleMapper">
select rid,rname from role where rid = #{xxx}
</select>
</mapper>
IEmployeeRoleDao .java 对应的配置文件 src/com/haichuang/daos/employee-role-mapper.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="com.haichuang.daos.IEmployeeRoleDao">
<resultMap type="Role" id="roleMapper">
<id column="rid" property="rid"/>
<result column="rname" property="rname"/>
</resultMap>
<!-- 通过传来的员工id查询员工角色中间表进而确定员工对象的角色信息 -->
<select id="selectRoleByEmployeeId" resultMap="roleMapper">
select rid,rname
from role
inner join employee_role on employeeId = #{xxx}
where rid = roleId
</select>
<resultMap type="Employee" id="employeeMapper">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
</resultMap>
<!-- 通过传来的角色id查询员工角色中间表进而确定员工对象的信息 -->
<select id="selectEmployeeByRoleId" resultMap="employeeMapper">
select eid,ename
from employee
inner join employee_role on roleId = #{xxx}
where eid = employeeId
</select>
</mapper>
到这里我们员工对角色的多对多关系查询就完成了
Department实体类对应的接口
package com.haichuang.daos;
import com.haichuang.beans.Department;
public interface IDepartmentDao {
public Department selectDepartmentById(int did);
}
DepartmentEmployee实体类对应的接口
package com.haichuang.daos;
import java.util.List;
import java.util.Set;
import com.haichuang.beans.Employee;
public interface IDepartmentEmployeeDao {
public List<Employee> selectEmployeeByDepartmentId(int did);
}
IDepartmentDao .java 对应的配置文件 src/com/haichuang/daos/department-mapper.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="com.haichuang.daos.IDepartmentDao">
<!-- 部门的mapper -->
<!-- collection标签子标签select通过DepartmentEmployee对应的映射文件来获取员工信息 -->
<resultMap type="Department" id="departmentMapper">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
<collection property="employees"
ofType="Employee"
select="com.haichuang.daos.IDepartmentEmployeeDao.selectEmployeeByDepartmentId"
column="did"/>
</resultMap>
<!-- 通过id查询部门 -->
<select id="selectDepartmentById" resultMap="departmentMapper">
select did,dname from department where did = #{xxx}
</select>
</mapper>
DepartmentEmployee.java 对应的配置文件 src/com/haichuang/daos/department-employee-mapper.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="com.haichuang.daos.IDepartmentEmployeeDao">
<!-- 从部门员工表中查询出员工的id,然后用这个id通过employee的mapper配置文件查询员工信息 -->
<select id="selectEmployeeByDepartmentId" resultMap="com.haichuang.daos.IEmployeeDao.employeetMapper">
select eid,ename,eage
from employee
inner join department_employee on departmentId = #{xxx}
where eid = employeeId
</select>
</mapper>
这个不是这个例子的重点,笔者就不再解析了
package com.haichuang.utils;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MybatisUtils
{
public static SqlSession getSqlSession() {
try {
//1.加载主配置文件
InputStream in = Resources.getResourceAsStream("mybatis.xml");
if(sqlSessionFactory == null) {
//2.创建SqlSessionFactory对象
sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
}
//3.创建SqlSession对象并返回
return sqlSessionFactory.openSession();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private static SqlSessionFactory sqlSessionFactory;
}
到这里,整个工作准备得已经差不多了,我们创建一个主类来测试上面程序,在 src 的com.haichuang.test创建一个 MyTest.java,代码如下:
package com.haichuang.test;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.haichuang.beans.Department;
import com.haichuang.beans.Employee;
import com.haichuang.beans.Role;
import com.haichuang.daos.IDepartmentDao;
import com.haichuang.daos.IEmployeeDao;
import com.haichuang.daos.IRoleDao;
import com.haichuang.utils.MybatisUtils;
public class MyTest {
@Before
public void before(){
sqlSession=MybatisUtils.getSqlSession();
//edao = sqlSession.getMapper(IEmployeeDao.class);
//rdao = sqlSession.getMapper(IRoleDao.class);
ddao = sqlSession.getMapper(IDepartmentDao.class);
}
@After
public void after() {
if(sqlSession != null) {
sqlSession.close();
}
}
@Test
public void test01() {
Employee employee = null;
employee = edao.selectEmployeeById(1);
System.out.println(employee);
}
@Test
public void test02() {
Role role = null;
role = rdao.selectRoleById(2);
System.out.println(role);
}
@Test
public void test03() {
Department department = null;
department = ddao.selectDepartmentById(1);
System.out.println(department);
}
private IEmployeeDao edao;
private IRoleDao rdao;
private IDepartmentDao ddao;
private SqlSession sqlSession;
}