mybatis中mysql递归查询多级_多级菜单查询实践-Mybatis和JPA

在9月份面试时,面试官在一张草稿纸上出了一道省市县联动的题目,并提示我可以使用递归或循环,将数据查询出来封装到对象中。当时我用了循环的方式将其封装,虽说勉强实现,但是代码冗余度高,逻辑性特别差。

碰巧最近项目中业务需要,也是将多级菜单封装到根菜单返回给前端,发现还是会把自己弄得头晕,因此打算认真写一下,当做笔记,也对之前Hibernate,Mybatis框架的复习。下面将会使用Mybatis 和 JPA 分别实现菜单封装业务逻辑,初步规划只要将数据以JSON格式写回前端即是测试通过。

Demo1 「使用Mybatis实现多层菜单数据查询」

数据库表一览

menuid

menuname

parentid

0

系统菜单

100

二级菜单A

0

101

三级菜单A

100

102

三级菜单A

100

200

二级菜单B

0

201

三级菜单B

200

202

三级菜单B

200

根据数据库表编写菜单实体类

public class Menu {

private String menuid; //主键ID

private String name; //菜单名称

private String parentid; //上一级菜单

private List

//get and set method...

}

针对Mybatis , 编写对应Mapper接口

public interface MenuMapper {

public Menu getRootMenu(); //返回根菜单

public List

}

编写Mapper.xml , 这里是编码重点 , 此时 ,需要注意的点是,我们将要封装的数据是一个根菜单Menu对象,难点在于给子菜单menus赋值,因为数据库和实体类中的menus并没有任何关系,所以这里需要使用ResultMap形式将数据封装。

SELECT * FROM menu WHERE parentid ='' or parentid is NULL

SELECT * from menu where parentid = #{value}

注:

​ 这里重点就是ResultMap的配置,普通字段,使用id和property即可实现实体类和数据库表字段映射。比较特殊的是menus这个字段,需要配置一对多关系,由于多的一方数据类型仍是Menu,因此ofType就是Menu类型,另外需要添加配置项 select , 将findMenuByParentId返回的值指向menus字段。

以下就是测试结果,重点关注 menuid , 第二级菜单都 100 , 200 ,300 ....第三级菜单都是 101,102,201,202,203....以此类推

{

"menuid": "0",

"name": "系统菜单",

"parentid": "",

"menus": [

{

"menuid": "100",

"name": "二级菜单1",

"parentid": "0",

"menus": [

{

"menuid": "101",

"name": "三级菜单1",

"parentid": "100",

"menus": [ ]

},

{

"menuid": "102",

"name": "三级菜单3",

"parentid": "100",

"menus": [ ]

}

]

},

{

"menuid": "200",

"name": "二级菜单2",

"parentid": "0",

"menus": [

{

"menuid": "201",

"name": "三级菜单2",

"parentid": "200",

"menus": [ ]

}

]

}

]

}

Demo2 「使用Hibernate或JPA实现多层菜单数据查询」

这个demo有两个主要看点:

1.上文中的Menu使用JPA再次实现。

2.JPA的一些解释。

第一步,jar包环境 。注,这里使用的是Springboot整合的方式,引入JPA的相关类库。

org.springframework.boot

spring-boot-starter-data-jpa

mysql

mysql-connector-java

runtime

实体类(使用注解形式)

@Entity

public class Menu {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private String menuid; //菜单主键,GenerationType.IDENTITY即是主键生成模式,自增长。

private String menuname; //名

@OneToMany(cascade=CascadeType.ALL)

@JoinColumn(name = "parentid") //根据父级菜单ID,实现自关联(内部其实也就是一对多)

private List

//get and set method..

}

说明:

JPA使用注解形式进行开发,可以简便一些。省去写配置文件的麻烦,但也与java代码耦合。具体使用传统Hibernate配置文件形式开发还是使用简洁的JPA库开发还是要根据实际项目作出对应选择。

具体JPA注解的使用,这里不做重点解释。

开始DAO层开发

public interface MenuDao extends JpaRepository

}

是的,DAO层就这一句代码就可以了,JPA内部帮我们封装了很多简单的增删改查方法,省去我们很多重复代码的编写。

调用

@Service

@Transactional

public class MenuServiceImpl implements MenuService {

@Autowired

private MenuDao menuDao;

@Override

public Menu getRootMenu() {

return menuDao.findOne("0"); //将最上层菜单返回即可内联查询出所有子菜单

}

}

总结

​ 主要为了记录一个比较特殊,也是比较绕一种数据读取。其特点是对象之间内部关联,或者说有父子关系,当然实现方式也是多种多样,应结合具体项目,具体技术应用场景来规划技术选型。比如使用递归,循环等等,都可以实现类似业务。该demo可以给前端返回一个跟节点对象,而不是一组数据(json数组)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值