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. 【转】Android 将自己的应用改为系统应用

    所谓系统程序就是system/app目录中的程序,普通应用转换成系统程序后有稳定.减少内存(DATA)空间占用.恢复出厂设置后不会消失.修改系统时间.调用隐藏方法.系统关机重启.静默安装升级卸载应用等 ...

  2. android -------- VideoCache 视频播放(缓存视频到本地)

    先前做了一个小视频的功能,里面有播放多个视频的功能,为了效率,我加了视频缓存功能: 一方面耗费用户的流量,另一方面直接从本地播放要更流畅 网上看资料,一个视频缓存库,使用起来很方便,还不错,就分享给大 ...

  3. Android Studio 教程

    Android Studio 超详细安装教程 http://dkylin.com/archives/2019/android-studio-installation.html Android Stud ...

  4. 全新思维导图 XMind ZEN v10.0.0 中文破解版

    http://www.carrotchou.blog/20331.html 官网 https://www.xmind.cn/ 注意事项 破解版本已经去除了全部的官方试用版的限制,让大家可以像正版用户一 ...

  5. VUE-012-图表 v-charts 学习(一)饼图展示状态

    软件质量平台中需要输出各种各样的图表数据,以 v-charts 中的饼图为例,记录图表使用实现过程. v-charts :https://github.com/ElemeFE/v-charts doc ...

  6. bootcss 之 .table-hover 类 鼠标悬停

    通过添加 .table-hover 类可以让 <tbody> 中的每一行对鼠标悬停状态作出响应. <table class="table table-hover" ...

  7. python - logging.basicConfig format参数无效

    有这么一段python代码 import threading import time import requests from decimal import Decimal, ROUND_DOWN i ...

  8. SVM – 线性分类器

    感知机 要理解svm,首先要先讲一下感知机(Perceptron),感知机是线性分类器,他的目标就是通过寻找超平面实现对样本的分类:对于二维世界,就是找到一条线,三维世界就是找到一个面,多维世界就是要 ...

  9. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器解决方案之Grunt的使用简介

    什么是Grunt? Grunt,简而言之,就是运行在Node.js上面的任务管理器(task runner),其可以在任何语言和项目中自动化指定的任务.我们可通过npm来安装Grunt和Grunt插件 ...

  10. 为什么var可以重复声明

    总结自:https://blog.csdn.net/DurianPudding/article/details/87953939 一言以蔽之:编辑器会在作用域判断这是重名声明时,忽略var直接赋值 首 ...