Mybatis中使用association及collection進行自關聯示例(含XML版與注解版)


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();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM