Mybatis常见面试题总结
梳理面试过程中Mybatis相关的常见问题。为保证知识点覆盖,参考了《Mybatis从入门到精通》、《深入浅出Mybatis技术原理与实战》、《Mybatis技术内幕》等书籍。
Mybatis 简介
Mybatis 是一款优秀的持久层框架(ORM框架),它支持自定义SQL、存储过程以及高级映射。Mybatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。Mybatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
Mybatis优缺点
在介绍Mybatis优缺点前,先简单介绍下传统JDBC开发存在以下问题:
(1) 频繁地创建数据库连接对象、释放,容易造成系统资源浪费,影响系统性能。可以使用连接池解决这个问题。但是使用jdbc需要自己实现并管理连接池。
(2) sql语句定义、参数设置、结果集处理存在硬编码。实际项目中sql语句变化的可能性较大,一旦发生变化,需要修改java代码,系统需要重新编译,重新发布。(不能很好的适应变化)
(3) 使用preparedStatement向占位符传参数存在硬编码,因为sql语句的where条件不固定(如条件查询),可能多也可能少,修改sql还要修改代码,系统不易维护。
(4) 结果集处理存在重复代码,处理麻烦。如果可以映射成Java对象会比较方便。
Mybatis针对传统JDBC开发存在的问题,进行优化,实现以下功能(优点):
(1) 实现数据库连接配置及管理,无需编写数据库连接、释放等代码。(减少编码)
(2) 将Sql语句配置xml文件中,实现SQL语句与java代码分离,便于统一管理。提供XML标签,支持编写动态SQL语句。
(3) 支持自动将java对象映射至sql语句、自动将sql执行结果映射至java对象。(打通sql与java对象的交互)
但Mybatis也存在以下问题:
(1) SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2) SQL语句依赖于特定数据库,无法做到数据库无关,导致数据库移植性差。
Mybatis 是一个足够灵活的ORM框架。对性能的要求很高,或者需求变化较多的项目,Mybatis是比较不错的选择。
Mybatis和hibernate对比
Hibernate和Mybatis都是对jdbc的封装,都是ORM框架,在选择时,要根据业务场景合理选择。Hibernate和Mybatis主要有以下不同:
(1) 映射关系
Mybatis 是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单。
Hibernate 是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂。
Mybatis 需要编写原生SQL,可以严格控制sql执行性能,灵活度高,但无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
Hibernate 无需编写原生SQL,可以做到数据库无关性,但是其多表关联关系配置复杂。
(2) SQL优化和移植性
Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 Mybatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。
Mybatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。
(3) 开发难易程度和学习成本
Hibernate 是重量级框架,学习使用门槛相对较高,适合于需求相对稳定、对性能要求不高、关联查询场景较少的场景,如:办公自动化系统。
Mybatis 是轻量级框架,学习使用门槛相对较低,适合于需求变化频繁、对性能要求较高、关联查询场景较多的场景,如:互联网电子商务系统。
为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
简单介绍下一条SQL在Mybatis中是如何执行的
这里重点介绍下基于xml编写SQL的场景。
(1) 读取 MyBatis 配置文件。如名为mybatis-config.xml的文件为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
(2) 加载映射文件。映射文件即 xxxMapper.xml文件。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
(3) 构造会话工厂。通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。SqlSessionFactory用来创建SqlSession。
(4) 创建会话实例。会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
(5) 执行Executor(执行器)。MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6) 访问MappedStatement对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
(7) 输入参数映射。输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。
(8) 输出结果映射。输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于JDBC对结果集的解析过程。
能简单介绍下Mybatis映射器吗?
映射器是Mybatis最强大的工具,也是我们使用Mybatis时使用最多的工具。
在映射器中可以定义的元素有:select、insert、update、delete、resultMap、parameterMap、sql、include、selectKey,此外,还有动态sql的元素trim、where、set、foreach、if、choose、when、otherwise、bind等。
Mybatis如何实现主键回填
在插入记录时,会遇到主键回填的问题。针对这个场景,可以使用keyProperty属性来指定主键字段,并通过useGeneratedKeys来启用数据库内置生成策略,或通过selectKey来自定义生成策略。
Mybatis为什么引入延迟加载?它的实现原理是什么?
使用级联(多表查询或嵌套查询)后,即使不需要关联的信息,在执行select语句时也会被执行,这会造成SQL执行过多导致性能下降,这就是N+1问题。为了解决N+1问题,Mybatis引入延迟加载功能。延迟加载功能默认开启,无需手动开启。如果需要禁止,
延迟记载功能的意义在于,一开始并不取出级联数据,只有当使用级联数据时,才发送SQL去取回数据。
在Mybatis的配置中有两个全局的参数lazyLoadingEnabled和aggressiveLazyLoading。lazyLoadingEnabled用于表示是否启用延迟加载功能(默认是即时加载)。aggressiveLazyLoading表示积极应对延迟加载(层级加载),默认是true。在设置延迟加载时,要主动将该参数设置为false。(也即是说,延迟加载默认是关闭的,需要主动开启)
上述方案是全局延迟加载方案,有时需要实现局部延迟加载。可以在association和collection元素上添加属性fetchType。其中eager表示主动加载,lazy表示延迟加载。局部延迟加载的优先级高于全局延迟加载。
延迟加载的实现原理是动态代理。在默认情况下,Mybatis在3.3及以后的版本,采用JAVASSIST实现动态代理,在低版本,采用CGLIB。举例来说,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。
Mybatis动态sql了解吗?其执行原理可以介绍下吗?有哪些动态sql?
在实际的应用中,常常需要动态的组装SQL。Mybatis提供对SQL语句动态的组装能力,只需用几个基本元素,就可实现大量代码才能实现的功能,这体现了Mybatis的灵活性、高度可配置性和可维护性。
Mybatis也支持在注解中配置SQL,但由于注解中配置功能受限,对于复杂的SQL而言,可读性较差。推荐在Mapper.xml中动态组装SQL。
Mybatis的动态SQL主要分内如下几类:
(1) if元素。判断语句,单条件分支判断。
(2) choose(when、when、otherwise)元素。多条件分支判断,类比Java语言中的switch、case、default。
(3) trim、where、set等元素。辅助元素,用于处理一些SQL拼装问题。
(4) foreach元素。循环语句。在in语句等列举条件中常用。
动态SQL的原理是使用OGNL(Object-Graph Navigation Language)从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
多数据库支持
Mybatis是一种半自动映射的框架,需要配置Java对象与sql语句执行结果的对应关系,无法做到数据库无关性。Mybatis提供了多数据库支持的能力。Mybatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseld 属性的。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseld 属性的所有语句。如果同时找到带有 databaseId 和不带 databaseId 的相 同语句,则后者会被舍弃。
接下来以select元素为例,介绍如何实现多数据库支持。
<select id="selectXxx" databaseId="mysql">select id, code, name from Xxx where name like concat (#{name},'%')
</select>
<select id="selectXxx" databaseId="oracle">select id, code, name from Xxx where name like #{userName}||'%'
</select>
需要说明的是,databaseId通过是通过DatabaseMetaData#getDatabaseProductName()返回的字符串进行设置。
注意,尽管Mybatis支持使用if标签配合上下文中的 databaseOd 参数实现多数据库支持,但是因为这种写法在同一个SQL里面包含了不同类型的数据库,不利于后面的维护,不建议使用这种写法。反例如下:
<select id="selectXxx" databaseId=”mysql”>select id, code, name from Xxx <where><if test="name != null and name != ''"><if test="databaseId == 'mysql'">and name like concat (#{name},'%')</if><if test="databaseId == 'oracle'">and name like #{userName}||'%'</if></if></where>
</select>
Mybatis的一级缓存和二级缓存了解吗?该如何使用?
使用缓存可以使应用更快地获取数据,避免频繁的数据库交互,尤其是在查询越多、缓存命中率越高的情况下,使用缓存的作用就越明显。Mybatis作为持久化框架,提供了非常强大的查询缓存特性,可以非常方便地配置和定制使用。
Mybatis提供两级缓存。一般提到Mybatis缓存的时候,都是指二级缓存。一级缓存(也叫本地缓存〉默认会启用,并且不能控制,因此很少会提到。
一级缓存默认开启。 一级缓存存在于SqlSession的生命周期中,在同一个SqlSession中查询时,Mybatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中。如果同一个SqlSession中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当Map缓存对象中己经存在该键值时,则会返回缓存中的对象。
如果在执行方式的时候不想使用一级缓存,可以对该方法做如下修改。
二级缓存默认不开启。Mybatis的二级缓存存在于SqlSessionFactory的生命周期中,对应作用域为Mapper(Namespace)。虽然目前还没接触过同时存在多个SqlSessionFactory的情况,但可以知道,当存在多个SqlSessioηFactory时,它们的缓存都是绑定在各自对象上的,缓存数据在一般情况下是不相通的。只有在使用如Redis这样的缓存数据库时,才可以共享缓存。
将Mybatis二级缓存应用于生产环境,还需考虑二级缓存可能带来的脏读问题及避免策略。
Mybatis的二级缓存是和命名空间绑定的,所以通常情况下每一个Mapper映射文件都拥有自己的二级缓存,不同Mapper的二级缓存互不影响。在关联多表查询时肯定会将该查询放到某个命名空间下的映射文件中,这样一个多表的查询就会缓存在该命名空间的二级缓存中。涉及这些表的增、删、改操作通常不在一个映射文件中,它们的命名空间不同,因此当有数据变化时,多表查询的缓存未必会被清空,这种情况下就会产生脏数据。(二级缓存面向命名空间,不同的Mapper的二级缓存相互隔离。对于多表联合查询,涉及的表的增、删、改操作不在一个映射文件中,当数据变化时,多表查询的缓存未必会被清空,会产生脏数据)
对于多表联合查询存在的脏数据问题,可以使用参照缓存解决。当某几个表可以作为一个业务整体时,通常是让几个会关联的ER表同时使用同一个二级缓存,这样就能解决脏数据问题。
什么是Mybatis的接口绑定?有哪些实现方式?
接口绑定,就是在Mybatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式:
(1) 注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;
(2) 通过xml里面写SQL来绑定,在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定,当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
推荐使用xml方式,SQL本身就是变化点,同一个接口可能面向不同的数据库有不同的实现。
#{}和${}的区别是什么?
/#{} 是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值,可以有效的防止SQL注入,提高系统安全性。
Mybatis在处理${}时,就是把${}替换成变量的值,存在SQL注入的风险。
Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
Mybatis多表查询了解吗?
实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询两种方式。
联合查询是几个表联合查询,只查询一次,通过在resultMap里面配置association节点配置一对一的类就可以完成。
嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
实现一对多有几种方式?怎么操作的?
有联合查询和嵌套查询。
联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成。
嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。
参考
https://zhuanlan.zhihu.com/p/347935099 Mybatis面试题
《Mybatis从入门到精通》 刘增辉 著
《深入浅出Mybatis技术原理与实战》 杨开振著
《Mybatis技术内幕》 徐郡明 著
相关文章:

Mybatis常见面试题总结
梳理面试过程中Mybatis相关的常见问题。为保证知识点覆盖,参考了《Mybatis从入门到精通》、《深入浅出Mybatis技术原理与实战》、《Mybatis技术内幕》等书籍。 Mybatis 简介 Mybatis 是一款优秀的持久层框架(ORM框架),它支持自定义SQL、存储过程以及高…...

数字IC设计之时序分析基础概念汇总
1 时钟Clock 理想的时钟模型是一个占空比为50%且周期固定的方波。时钟是FPGA中同步电路逻辑运行的一个基准。理想的时钟信号如下图: 2 时钟抖动Clock Jitter 理想的时钟信号是完美的方波,但是实际的方波是存在一些时钟抖动的。那么什么是时钟抖动呢?时钟抖动&#…...

1.centos7安装docker
本文目录: 1.docker 安装1.安装步骤2.安装是否成功校验3.docker加速配置4.hello world来袭,验证安装是否ok 2.卸载docker3.卸载较旧版本docker 使用docker必备的三个官方网站: docker官网:https://www.docker.com docker官方仓库&…...

基于elasticsearch-8.8.2 kibana-8.8.2 搭建一个文搜图系统demo
数据来源是由 图片url,图片descript,图片keywords 外加一个id 基于此首先创建 索引, keywords是一组由单词或词组 组成的一组数据,所以以数组形式压入数据: descript 是由两条语句组合成的数据(针对图片的两种不同描述) # 这里创建的keywords 数组元素类型为text,即可以模糊匹…...
第26节-PhotoShop基础课程-形状工具组-画板
文章目录 前言1.基础图形1.正方形(shift/alt/两者加起来)2.描边3.合并形状 将多个图放在一个图层4.对齐只能在不同图层5.修改6.重叠,相交 2.多边形1.边数2.星形 3.直线工具1.正常2.箭头 4.自定义形状 前言 类似画图板,矢量图形。…...

第一次课,通过进程信息和服务信息识别当前计算机运行程序(预习版)
题目: 检测的目标进程: ydebugg ; “ImmunityDebugger.exe” _500], rax Exe ; “ollydbg.exe” _4F8], rax hackerE ; “ProcessHacker.exe” _4F0], rax Exe ; “tcpview.exe” _4E8], rax sExe ; “autoruns.exe” _4E0], rax scExe ; “autorunsc.ex…...

ChatGPT 或其它 AI,能用在文书创作上吗?
新的申请季已经正式开始,一些热门项目的ED截止日期也不再遥远,因此很多准留学生们都已经开始了关于文书的创作。 而随着科技的不断发展,以ChatGPT为首的一众AI工具也作为一种辅助手段愈发融入了我们的生活。 那么不免就会有一些同学在准备申…...
Java中锁的分类
Java中锁的分类 这篇文章介绍各种锁的分类。介绍的内容如下: 公平锁/非公平锁可重入锁独享锁/共享锁互斥锁/读写锁乐观锁/悲观锁分段锁偏向锁/轻量级锁/重量级锁自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性&am…...

centos安装flink,通过windows访问webui
1. 安装flink 1.1. flink的下载 通过flink官网下载flink安装包 https://flink.apache.org/ 下载安装包 1.2 flink在centos上的安装 将下载好的flink-1.17.1-bin-scala_2.12.tgz安装包放到centos目录下 解压文件: [rootlocalhost ~]# tar -zxvf flink-1.17.…...

如何让两台手机相互远程控制?
你的两台手机是什么系统的?如果你的两台手机都是安卓系统,而且都是安卓7.0及以上版本的系统,那么恭喜你,这两台手机可以相互远程控制! 你可以利用两个软件实现将两台手机相互远程控制的想法。为了避免混淆,…...

预编译为什么能防止SQL注入?一看你就明白了。预编译原理详解
「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 预编译防止SQL注入 1、SQL执行过程2、预编译原理3、…...

【7z密码】7z压缩包密码忘记了,怎么办?i
7z压缩包设置了密码,解压的时候就需要输入正确对密码才能顺利解压出文件,正常当我们解压文件或者删除密码的时候,虽然方法多,但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么,忘记了7z压缩包的密码…...

部署云MYSQL(在线版)
在Methodot - 您的一站式云原生在线开发协作平台网站上可以部署免费的MYSQL,在应用商店里能看到可以搭建多种数据库:(前提是要注册登录,免费版只能是2人共享) 登陆好后,点击工作台,选择应用商店…...

Gin 框架 解决 跨域问题
Gin 框架解决跨域问题 一点废话 在学习 Axios 的时候发现 up 使用了一个网址来提供 json 数据。因为不想加什么公众号搞啥百度网盘的,然后又刚好会一点点 go,就想着自己用 gin 框架返回一个 json 到前端页面然后从这个页面获取 json 。 这是我的go代码…...
【Datawhale课程笔记-简单学点大模型】大模型的能力
大模型的能力 参考GITHUB:https://github.com/datawhalechina/so-large-lm/blob/main/第二章:大模型的能力.md 深入探讨GPT-3——这个具有代表性的大型语言模型的能力。我们的研究主要基于GPT-3论文中的基准测试,这些测试包括: …...

git使用说明
目录 前言1.安装1.1. windows1.1.1.git客户端1.1.2.配置git客户端1.1.3.安装TortoiseGit图形客户端1.1.4 关于文件换行问题 1.2.ubuntu1.2.1.ubuntu终端Git中文乱码1.2.2 git log中文乱码解决 2.建立版本库2.1.下载网上开源版本库2.1.1.复制下载地址2.1.2.使用命令行…...

【PowerQuery】PowerBI Pro账户的自动刷新
在数据和模型通过发布或者上传方式上传到PowerBI Pro中,如何来进行数据刷新呢?数据源依然在本地,而数据模型已经发布到PowerBI Pro云端服务中。如果数据源更新,我们的模型如何进行自动刷新呢? PowerBI Pro如果需要基于本地数据源更新进行模型更新需要部署相应的数据网关服…...

红黑树(思维导图详解版)
目录 资源已上传 实现代码 测试代码 资源已上传 部分图片 实现代码 注意判断是否为红黑树的代码实现,实现代码中红黑树的删除 #pragma once #include<iostream> using namespace std;enum Color_Type {Red,Black };template<class K,class V> str…...

javafx学习记录
1.布局 2.选择重写或实现方法(select methods to override/implements) ctrl o 3.javafx有init方法,start方法,stop方法 4.定义一个按钮,使用系统默认浏览器访问网站 5.使窗口的关闭栏,缩小扩屏栏,代码是倒数第二行 6.设置模态窗口,默认关闭模态的 下…...

友善Nona Pi开发板ubuntu22.04系统用Python3.8.17的pip安装PyQt5.15.2时报错“Q_PID”这个宏未定义的一种解决办法
安装命令: pip install PyQt55.15.2 --config-settings --confirm-license --verbose -i https://mirrors.aliyun.com/pypi/simple/ 遇到出错: 如图: 分析具体错误内容: These bindings will be built: Qt, QtCore, QtNetwo…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 框架,SqlSugar 就是其中备受…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...