1、idea下载easycode
2、配置数据源
3、右击生成代码
4、除了debug.json,都选对号
5、在dao上面添加@Mapper,或者在启动类上面添加@MapperScan("com.winter.dao")
6、测试启动
问题
1、生成的代码dao层没有@Mapper,自己添加
2、xml文件多表级联有问题
问题2解决方案:(原文网址、Mybatis 有关级联删除和更新 - JavaShuo)
(原文网址、第八章:MyBatis级联查询 - 知乎 (zhihu.com))
多表级联中删除更新查询
RESTRICT、NO ACTION表示子级有数据改变是父级数据不更新方法
SET NULL 表示父级在更新或者删除时将子记录列的值设为nullim
ON DELETE CASCADE 表示父记录删除时子记录对应的列数据也删除数据
ON UPDATE CASCADE 表示父记录更新时子记录对应的列数据也更新
1:在建立表的时候就对外键定义成级联删除或者更新
CREATE TABLE `order` (
`id` int(4) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
CONSTRAINT `约束名(可随意,不可重复)` FOREIGN KEY (`外键名在本表中列名`) REFERENCES `外键表名` (`外键表列名`) ON DELETE CASCADE ON UPDATE CASCADE)
这样把父级删除后子级的数据也会删除
2:这种方法是最笨的方法,也就是一条一条把把父级做为外键的子记录的数据,写sql一条一条的删除,经过父级的id 去删除
例如: delete from order where "外键名在本表中列名" =user.id;
多表级联中处理重复联合子集
(1)我们先来看一下 <collection> 标签中的属性:
property:对象属性的名称
ofType:指定的是映射到集合属性中 pojo 的类型
column:所对应的外键字段名称
select:使用另一个查询封装的结果
(2)在Dept.java实体类中添加员工集合属性,用于存放员工列表信息:
(3)xml 代码:
<resultMap id="deptMap1" type="Dept">
<id column="dept_deptno" property="deptno"/>
<result column="dname" property="dname"/>
<result column="loc" property="loc"/>
<!-- column 属性对应来自一方(一对多的一)表主键的字段名 -->
<collection property="employeeList" ofType="Employee" column="dept_deptno">
<id column="emp_no" property="empNo"/>
<result column="e_name" property="eName"/>
</collection></resultMap>
<select id="findListByDeptno" resultMap="deptMap1">
SELECT
dept.deptno dept_deptno,
dname,
loc,
emp_no,
e_name,
job,
sal
FROM dept
JOIN emp ON dept.deptno = emp.dept_no
WHERE dept.deptno = #{deptno}
</select>
(4)java 代码:
List<Dept> findListByDeptno(Integer deptno);
(5)测试用例:
@Testpublic void test01() throws IOException {
DeptMapper deptMapper = session.getMapper(DeptMapper.class);
List<Dept> list = deptMapper.findListByDeptno(8);
list.forEach(item -> System.out.println(item));}
(6)测试结果:
从结果我们可以看出,已经把“技术研发部”下的员工全都查询出来了,那部门和员工信息是如何对应的呢?我们可以看到,在 <collection> 标签中有一个 property 属性,这个属性的值必须要和实体类中员工集合属性相对应才行,要不然是无法进行字段映射的,这一点要十分的注意。而 ofType 属性则是集合中所对应的那个 bean。
2、通过执行另外一个 SQL 映射语句来返回预期的复杂类型
(1)xml 代码:
<resultMap id="deptMap2" type="Dept">
<id column="dept_deptno" property="deptno"/>
<result column="dname" property="dname"/>
<result column="loc" property="loc"/>
<collection property="employeeList" ofType="Employee" select="empFindByDeptno" column="dept_deptno">
</collection></resultMap>
<!-- 根据部门编码查询部门中的职员信息 --><select id="empFindByDeptno" resultType="Employee">
select emp_no AS "empNo", e_name AS "eName", job
from emp
where dept_no = #{deptno}
</select>
<!-- 根据部门编号查询部门信息 --><select id="deptFindByDeptno" resultMap="deptMap2">
select deptno AS "dept_deptno", dname, loc
from dept
where deptno = #{deptno}
</select>
(2)这里不再给出接口和测试用例,和第一种完全一样,这种方法最重要的是 xml 代码,我们可以看到,定义了两个查询语句,deptFindByDeptno 这个方法是调用的 resultMap 结果集,而 empFindByDeptno 方法的作用则体现在了 <collection> 标签中 select 属性上,这个 <collection> 标签的意思是:根据 deptFindByDeptno 方法查询出的结果对象中的 dept_deptno 属性当做参数,传递给 empFindByDeptno 方法再次进行查询,实际上是执行了两次查询操作。
三、多对一
多个员工,隶属于一个部门,这就是多对一的关系,正好与一对多反过来,废话不多说,直接上代码。
(1)我们先来看一下 <association> 标签中的属性:
property:对象属性的名称
javaType:对象属性的类型
column:所对应的外键字段名称
select:使用另一个查询封装的结果
(2)在员工表中添加部门实体:
(3)xml 代码:
<resultMap id="empMap" type="Employee">
<id column="emp_no" property="empNo"/>
<result column="e_name" property="eName"/>
<result column="job" property="job"/>
<result column="sal" property="sal"/>
<association property="dept" javaType="Dept">
<result column="dept_deptno" property="deptno"/>
<result column="dname" property="dname"/>
<result column="loc" property="loc"/>
</association></resultMap>
<!-- 根据职员编号查询职员信息以及隶属部门信息 --><select id="empFindById" resultMap="empMap">
SELECT
dept.deptno dept_deptno,
dname,
loc,
emp_no,
e_name,
job,
sal
FROM dept
JOIN emp ON dept.deptno = emp.dept_no
WHERE emp.emp_no = #{empNo}
</select>
(4)java 代码:
List<Employee> empFindById(Integer empNo);
(5)测试用例:
@Testpublic void test03() throws IOException {
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
List<Employee> list = employeeMapper.empFindById(7369);
list.forEach(item -> System.out.println(item));}
(6)测试结果:
(7)从结果可以看出,我们已经把部门信息关联出来了,还是很好理解的,这里主要是依靠 <association> 标签,这个是一定要掌握的。
四、多对多
多对多的例子还是很常见的,这里我们使用用户和角色这个例子,一个用户可以属于多个角色,一个角色又可以分配多个用户,这就形成了一个多对多的关系,由于是多对多,就要使用到第三张表,这是一个关系表,用于记录两个表中的主键,下面我们先给出表结构,先来看一下这三张表是什么样子的。
(1)表结构:
用户表:
角色表:
用户角色关系表:
(2)实体类代码:
用户实体类(User.java):
public class User {
private int userId;
private String userName;
private List<Role> roleList; // 角色列表属性
// 此处省略setter、getter方法
}
角色实体类(Role.java):
public class Role {
private int roleId;
private String roleName;
private List<User> userList; // 用户列表
// 此处省略setter、getter方法
}
用户角色关系实体类(UserRole.java):
public class UserRole {
private User user;
private Role role;
// 此处省略setter、getter方法
}
(3)xml 代码:
<resultMap id="getUserMap" type="User">
<id column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
<collection property="roleList" ofType="Role">
<id column="role_id" property="roleId"/>
<result column="role_name" property="roleName"/>
</collection></resultMap>
<!-- 查询所有用户所拥有的角色信息 --><select id="getUsers" resultMap="getUserMap">
SELECT
u.*, r.*
FROM USER u
JOIN user_role ur ON ur.user_id = u.user_id
JOIN role r ON r.role_id = ur.role_id
</select>
(4)接口代码:
List<User> getUsers();
(5)单元测试:
@Testpublic void test04() throws IOException {
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> list = userMapper.getUsers();
list.forEach(item -> System.out.println(item));}
(6)测试结果:
(7)细细想来,其实多对多就是两个一对多组成的,一对多掌握了,多对多也就很容易上手了。
网友评论