XML版本:

实体类:

@Data
@ToString
@NoArgsConstructor
public class Dept {
private Integer id;
private String name;
private List<Dept> children = new ArrayList<Dept>();
private Dept parent; public Dept(Integer id) {
this.id = id;
} public Dept(String name) {
this.name = name;
} public Dept(String name, Integer parentId) {
this.name = name;
this.parent = new Dept(parentId);
} public String toLazyString() {
return "Dept:{id: " + this.id + " ; name: " + this.name + "}";
}
}

Mapper接口:

public interface DeptMapper {
public Dept selectById(Integer id);
public int insertDept(Dept dept);
public int updateDept(Dept dept);
public int deleteDept(Dept dept);
public List<Dept> selectByParentId(Integer parentId);
}

Mapper映射文件:

<?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.sunwii.mybatis.mapper.DeptMapper">
<resultMap type="Dept" id="DeptMap_basic">
<id property="id" column="did" />
<result property="name" column="name" />
</resultMap>
<resultMap type="Dept" id="DeptMap" extends="DeptMap_basic">
<!-- 多对一关联:使用select引用方式 。association配置先于collection-->
<association property="parent" column="parent_id" javaType="Dept" select="selectById"></association> <!-- 一对多关联:使用select引用方式 -->
<collection property="children" column="did" ofType="Dept" select="selectByParentId" fetchType="lazy">
</collection> </resultMap> <select id="selectById" parameterType="Integer"
resultMap="DeptMap">
select id as did, name,parent_id from t_dept d where d.id=#{id}
</select>
<select id="selectByParentId" parameterType="Integer"
resultMap="DeptMap">
select id as did, name,parent_id from t_dept d where d.parent_id=#{parentId}
</select> <insert id="insertDept" parameterType="Dept" keyColumn="id"
keyProperty="id" useGeneratedKeys="true">
insert into t_dept(name,parent_id)
values(#{name},
<if test="parent==null">
0
</if>
<if test="parent!=null">
#{parent.id}
</if>
)
</insert> <update id="updateDept" parameterType="Dept">
update t_dept set
name=#{name},parent_id=
<if test="parent==null">
0
</if>
<if test="parent!=null">
#{parent.id}
</if>
where id=#{id}
</update> <delete id="deleteDept" parameterType="Dept">
delete from t_dept
where
id=#{id}
</delete>
</mapper>

Service实现类:

@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper; @Override
public Dept getDept(Integer id) {
return deptMapper.selectById(id);
} @Override
public List<Dept> getDeptByParentId(Integer parentId) {
return deptMapper.selectByParentId(parentId);
} @Override
@Transactional
public void insertDept(Dept dept) {
deptMapper.insertDept(dept);
} @Override
@Transactional
public void updateDept(Dept dept) {
deptMapper.updateDept(dept);
} @Override
@Transactional
public void deleteDept(Dept dept) {
List<Dept> children = this.getDeptByParentId(dept.getId());
if(children!=null && children.size()>0) {
for(Dept d : children) {
//删除所有下级
deleteDept(d);
}
}
deptMapper.deleteDept(dept); //测试事务回滚
//new Integer(0/0);
} }

测试类:

public class TestSelf2Self {
private ApplicationContext context = SpringUtil.getContext();
private DeptService deptService = (DeptService) context.getBean(DeptService.class); /**
* -添加部门
*/
@Test
public void testInsert() {
deptService.insertDept(new Dept("dept-6"));
} /**
* -添加部门
*/
@Test
public void testInsert2() {
deptService.insertDept(new Dept("dept-7", 2)); } /**
* -查询指定部门
*/
@Test
public void testSelect() {
int id = 1;
Dept dept = deptService.getDept(id);
String trees = dept.getName() + "(" + (dept.getParent() == null ? 0 : dept.getParent().getId()) + "-"
+ dept.getId() + ")";
List<Dept> children = dept.getChildren();
trees += "\n" + treeLevel(children, "\t");
System.out.println(trees); /*
//结果:
部门-1(0-1)
部门-2(1-2)
部门-3(1-3)
部门-4(3-4)
部门-5(4-5) */
} // 子树
private String treeLevel(List<Dept> children, String levelChar) {
String trees = "";
for (Dept dept : children) {
trees += levelChar + dept.getName() + "(" + (dept.getParent() == null ? 0 : dept.getParent().getId()) + "-"
+ dept.getId() + ")\n";
List<Dept> subChildren = dept.getChildren();
if (subChildren != null && subChildren.size() > 0) {
levelChar = "\t" + levelChar;
trees = trees + treeLevel(subChildren, levelChar);
}
}
return trees;
} /**
* 查询所有下级部门(由于已经配置了一对多的关联,并且有延迟加载方案,其实没有必要再进行下级部门查询,直接用getChildren()就可以的啦,会自动进行查询)
*/
@Test
public void testSelectByParent() {
int parentId = 1;
//List<Dept> children = deptService.getDeptByParentId(parentId); Dept dept = deptService.getDept(parentId); //实际中,要查询下级的当前部门是已经存在的,只是由于延迟加载,没有加载子级
List<Dept> children = dept.getChildren(); //触发加载,执行SQL String trees = treeLevel(children, "\t");
System.out.println(trees); /*
//结果:
部门-2(1-2)
部门-3(1-3)
部门-4(3-4)
部门-5(4-5)
*/
} /**
* 查询所有上级部门(由于已经配置了一对多的关联(可能设置有延迟加载),其实没有必要再进行上级部门的查询,直接用getParent()就可以的啦,会自动进行查询)
*/
@Test
public void testSelectParents() {
int id = 4;
Dept dept = deptService.getDept(id);
List<Dept> parents = new ArrayList<Dept>();
parents.add(dept);
while (dept.getParent() != null && dept.getParent().getId() > 0) {
parents.add(dept.getParent());
dept = dept.getParent();
} String trees = "";
String LevelChar = "\t";
for (int i = parents.size() - 1; i >= 0; i--) {
trees += LevelChar + parents.get(i).getName() + "(" + parents.get(i).getId() + ")" + "\n";
LevelChar += "\t";
} System.out.println(trees); //结果:
/*
部门-1(1)
部门-3(3)
部门-4(4)
*/
} /**
* 更新部门
*/
@Test
public void testUpdate() {
int id = 6;
Dept dept = deptService.getDept(id);
dept.setName("dept-six");
dept.setParent(new Dept(3));
deptService.updateDept(dept);
} /**
* 删除部门(级联删除所有下级部门)
*/
@Test
public void testDelete() {
int id = 3;
deptService.deleteDept(new Dept(3));
}
}

注解版:

注解版本只是将Mapper映射文件去掉,将映射注解到Mapper接口中(并使用了动态sql提供器),其它东西不变。

Mapper接口(注解版):

public interface DeptMapper {
@Select("select id as did, name, parent_id from t_dept d where d.id=#{id}")
@Results(id="DeptMap", value= {
@Result(property = "id", column = "did"),
@Result(property = "name", column = "name"),
@Result(property = "parent", column = "parent_id", one=@One(
select = "selectById",
fetchType = FetchType.LAZY
)),
@Result(property = "children", column = "did", many=@Many(
select = "selectByParentId",
fetchType = FetchType.LAZY
))
})
public Dept selectById(Integer id); @InsertProvider(type = DeptProvider.class, method = "insert")
@Options(keyColumn = "id", keyProperty = "id", useGeneratedKeys = true)
public int insertDept(Dept dept); @UpdateProvider(type = DeptProvider.class, method = "update")
public int updateDept(Dept dept); @Delete("delete from t_dept where id=#{id}")
public int deleteDept(Dept dept); @Select("select id as did, name, parent_id from t_dept d where d.parent_id=#{parentId}")
@ResultMap("DeptMap")
public List<Dept> selectByParentId(Integer parentId);
}

动态SQL提供器:

public class DeptProvider {
public String insert(Dept dept) {
return new SQL() {
{
INSERT_INTO("t_dept");
VALUES("name", "#{name}");
if (dept.getParent() != null) {
VALUES("parent_id", "#{parent.id}");
} else {
VALUES("parent_id", "0");
}
}
}.toString();
} public String update(Dept dept) {
return new SQL() {
{
UPDATE("t_dept");
SET("name=#{name}");
if (dept.getParent() != null) {
SET("parent_id=#{parent.id}");
} else {
SET("parent_id=0");
}
WHERE("id=#{id}");
}
}.toString();
}
}

Mybatis中使用association及collection进行自关联示例(含XML版与注解版)的更多相关文章

  1. Mybatis中使用association及collection进行一对多双向关联示例(含XML版与注解版)

    XML版本: 实体类: package com.sunwii.mybatis.bean; import java.util.ArrayList; import java.util.List; impo ...

  2. Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版)

    Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版) XML版本: 实体类: @Data @NoArgsConstructor public class Course ...

  3. Mybatis中使用association进行关联的几种方式

    这里以一对一单向关联为例.对使用或不使用association的配置进行举例.  实体类: @Data @ToString @NoArgsConstructor public class IdCard ...

  4. Mybatis中的association用法

    这篇文章我们将来学习一些 association 用法 表结构 DROP TABLE IF EXISTS `student`; CREATE TABLE `student` (  `id` int(1 ...

  5. MyBatis对象关联关系---- association与collection

    Mybatis处理“一对多”的关系时,需要用到associasion元素.处理”多对一“用collection元素来实现(这两个元素在之前mapper文件中提到过). 本例子中,假设一名User可以有 ...

  6. mybatis中一对多查询collection关联不执行

    今天遇到的原因是因为下面红底id没有,导致关联查询没有条件(id字段没传),所以一直没有执行. <?xml version="1.0" encoding="UTF- ...

  7. MyBatis中出现Mapped Statements collection does not contain value

    引用csdn上一大神的解决方法: 经过排查,解决上述异常的过程如下: 1.确定xml文件中<mapper namespace=""/>中的namespace是否路径正确 ...

  8. Mybatis中的N+1问题与延迟加载

    0.什么是N+1问题? 在查询中一下子取出所有属性,就会使数据库多执行几条毫无意义的SQL .实际中不需要把所有信息都加载进来,因为有些信息并不常用,加载它们会多执行几条毫无用处的 SQL,导致数据库 ...

  9. MyBatis学习总结(三)——多表关联查询与动态SQL

    在上一章中我们学习了<MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射>,这一章主要是介绍一对一关联查询.一对多关联查询与动态SQL等内容. 一.多表关联查询 表与 ...

随机推荐

  1. spring boot整合websocket之使用自带tomcat启动项目报错记录

    项目中用到websocket,就将原来写好的websocket工具类直接拿来使用,发现前端建立连接的时候报404,经查找发现是因为原来用的是配置的外部tomcat启动,这次是spring boot自带 ...

  2. C++ 函数模板print

    简述 在知乎看到文章leetcode 的奇怪 println vector 工具,于是手痒自己也写了一个print函数. 因为工作中没有需要写这种代码的情况,所以好久没有写这种代码了,还是挺怀念以前学 ...

  3. iOS逆向(五)-ipa包重签名

    为什么要重签名? 1.在没有源代码的情况下,你已经对某个应用进行了资源修改(比如修改了启动图或图标等).修改完成以后,如果想要让APP可以正常使用,该APP一定要重新签名然后压缩成IPA文件. 2.如 ...

  4. cookie 设置报错 setcookie() expects parameter 3 to be integer, float given in...

    使用 setcookie 函数设置 cookie 报错,报错信息为: setcookie() expects parameter to be integer, float given in... 错误 ...

  5. Docker 安装 ActiveMQ

    搜索 ActiveMQ 镜像 docker search activemq 获取 ActiveMQ 镜像 docker pull webcenter/activemq 查看本地镜像 docker im ...

  6. Java学习-057-Jsoup爬虫获取中国所有的三级行政区划数据(二),并生成数据库 SQL 脚本插入语句

    多不废话,直接上马,小主您稳着... package com.fanfengping.zeus.uitl; import com.alibaba.fastjson.JSONObject; import ...

  7. invalid argument (errno: 22)

    socket通信示例中,当accept客户端时,经常报这个错误. 并且是第一次没有问题,第二次或后面几次都会出现如下问题, 错误码为22, 错误描述为invalid argument. 问题解决如下: ...

  8. GPL & LGPL

    Reference https://www.cnblogs.com/findumars/p/3556883.html GPL 我 们很熟悉的Linux就是采用了GPL.GPL协议和BSD, Apach ...

  9. kubernetes 1.9 安装部署

    参考地址:https://github.com/gjmzj/kubeasz 引言 提供快速部署高可用k8s集群的工具,基于二进制方式部署和利用ansible-playbook实现自动化,既提供一键安装 ...

  10. PAT-2019年冬季考试-甲级 7-3 Summit (25分) (邻接矩阵存储,直接暴力)

    7-3 Summit (25分)   A summit (峰会) is a meeting of heads of state or government. Arranging the rest ar ...