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. 【转】vim复制与粘贴

    用vim写代码时,经常遇到这样的场景,复制多行,然后粘贴. 这样做:1. 将光标移动到要复制的文本开始的地方,按v进入可视模式.2. 将光标移动到要复制的文本的结束的地方,按y复制.此时vim会自动将 ...

  2. 【Gamma阶段】第一次Scrum Meeting

    冰多多团队-Gamma阶段第一次Scrum会议 工作情况 团队成员 已完成任务 待完成任务 卓培锦 推广软件,发放调查问卷 修改可移动button以及button手感反馈优化,编辑器风格切换(夜间模式 ...

  3. template cannot be keyed. Place the key on real elements instead.

    template cannot be keyed. Place the key on real elements instead. 一.总结 一句话总结: 原因:vue不支持在 template 元素 ...

  4. 6条shell小技巧,让脚本显得不再业余【转】

    如何能让自己的shell显得不那么业余?下面6点实践一定有用. 画外音:本篇文章源自Google的一篇实践,抽取了部分1分钟能读完的内容,加入了一些分析. 一.以下面的语句开场 set -o noun ...

  5. 一条SQL语句执行得很慢的原因有哪些?| MySQL高性能优化规范建议

    一条SQL语句执行得很慢的原因有哪些 https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485185&idx=1&am ...

  6. IIS调优--增加并发处理能力

    一个ASP.NET项目在部署到生产环境时,当用户并发量达到200左右时,IIS出现了明显的请求排队现象,发送的请求都进入等待,无法及时响应,系统基本处于不可用状态.因经验不足,花了很多时间精力解决这个 ...

  7. cannot connect to daemon at tcp:5037: cannot connect to 127.0.0.1:5037: 由于目标计算机积极拒绝,无法连接。 (10061)

    原因是:5037端口被占用 解决方法:1.查找5037被谁占用   netstat -ano | findstr "3037" 2.查看对应的是哪个任务  tasklist | f ...

  8. android ------ 高版本的 Tablayout 下划线宽度

    前面呢,有写过TabLayout的博客,最近开发用到了高本版遇到一些问题,来总结一下 Android--------TabLayout实现新闻客户端顶部导航栏 Android中Tablayout设置下 ...

  9. 关于uboot中的属性"u-boot,dm-pre-reloc”的意义

    "u-boot,dm-pre-reloc”属性:当设置了这个属性时,则表示这个设备在重定向之前就需要使用. 当dm_init_and_scan的参数为true时,只会对带有“u-boot,d ...

  10. 虚拟机 /dev/mapper/centos-root 动态扩容

    [root@bogon ~]# df -h Filesystem Size Used Avail Use% Mounted on .2G .2G 51M % / devtmpfs 908M 908M ...