目录

MyBatis 持久化框架概述

Mybatis 标签汇总

SqlSessionFactory & SqlSession

搭建 Spring boot + Mybatis 环境

MyBatis 语法使用快速入门

resultType 设置查询结果类型

parameterType 设置参数类型

#{} VS ${} 取值对比

[CDATA[XXX]]> 转义小于符号

foreach 循环容器元素

concat 字符串拼接

choose (when, otherwise) 流程控制

if 条件判断

where 条件语句

if + set 修改语句

trim 代替 where、set 标签

sql 片段标签定义 sql 片段

MyBatis 集成 Spring boot 自动配置原理

@Param 定义 XxxMapper 方法多个参数


本文环境:Spring boot 2.3.5 + Java jdk 8 + Mysql + Log4j2 . + MyBatis 3.5.7

1、用户访问 Controller 控制层 -> Servires 业务层-> XxxMapper 接口-> XxxMapper.xml 映射。

2、所以使用 MyBatis 的重点就是 XxxMapper 接口 与 XxxMapper.xml 映射,本文采用 xml 的方式,不采用在注解上写 Sql 的方式。

MyBatis 持久化框架概述

1、MyBatis 是世界上流行最广泛的 SQL 映射框架之一。

官网:https://blog.mybatis.org/

MyBatis中文官网:https://github.com/mybatis/mybatis-3

配置:https://mybatis.org/mybatis-3/configuration.html#settings

集成:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/

github:https://github.com/mybatis/mybatis-3

2、Hibernate 的优点是将整个开发设计过程全部面向对象开发,全ORM,不用写任何SQL语句。

3、MyBatis 维持原有的编程方式,前部分按面向对象思考和设计,持久层时使用sql语句,面向过程,半 ORM。

4、Hibernate 的弱点是底层仍然使用sql,需要将hql语句转为sql,导致Sql无法优化,且Hibernate需要通过反射,性能较低。

5、MyBatis 只是基于jdbc的轻量级封装,还是使用sql,性能比较高。

6、所以业内认为:中小型项目使用 Hibernate,开发速度快;大型项目使用MyBatis,项目性能高。

7、 SqlSessionFactory 是线程安全的,SqlSession是线程不安全的,不能做类的公共变量。

8、学习 MyBatis 主要是学习它的标签语法,它们很类似以前的 JSTL 标签,所以本文重点就是介绍它的语法使用。

Mybatis 标签汇总

常用标签 描述
<select> 用于 select 查询 sql 语句
<insert> 用于 insert 插入 sql 语句
<update> 用于 update 更新 sql 语句
<delete> 用于 delete 删除 sql 语句
<foreach> 用于遍历容器元素,如 List、Set、Array 等,通常用于为 in 函数设置参数.
<![CDATA[xxx]]>

小于符号转义,如 <![CDATA[and sal <= #{end}]]>

<mapper namespace="xxx"> mapper 是整个 xml 文件的根标签,namespace 表示此配置文件的命名空间,严格上来说,没有强制要求,只需要唯一即可,不过官方推荐命名空间设置为 XxxMapper 的全路径.
<if test=true|false>

如果判断结果为 true,则将其中的内容拼接到 sql 中,否则不拼接。
<if test="name!=null and name !=''">xxx</if>
<if test="age <= 18 or age == 30">xxx</if>

<where>

当 where 标签中有返回值时,where 标签会自动插入一个 'where' 字符串 sql .
当 where 标签返回的内容是以 AND 或 OR 开头时,会自动剔除掉开头的 'and' 和 'or',不区分大小写。

<set> 当其中有内容时,自动添加 set 关键字,如果内容结尾有多余的逗号,也会自动删除。
<trim> trim 是一个格式化的标记,可以完成 set、where 标记的功能,有如下属性:
prefix:为内容添加前缀,如 "set"
suffix:为内容添加前缀,如 "where id=#{id}"
suffixOverrides:去掉内容结尾的指定字符串(多个时用"|"隔开),如逗号 ","
prefixOverrides:去掉内容开头的指定字符串(多个时用"|"隔开),如逗号 "and|or"

SqlSessionFactory & SqlSession

MyBatis 核心API 描述
SqlSessionFactoryBuilder

a、这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 实例的最佳范围是方法范围(也就是本地方法变量)。

b、可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但是最好还是不要让其一直存在以保证所有的 XML 解析资源开放给更重要的事情。

SqlSessionFactory

a、一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次。

b、因此 SqlSessionFactory 的最佳范围是应用范围,有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

openSession():会默认开启一个事务,但事务不会自动提交,需要手动提交和回滚。
openSession(boolean autoCommit):参数为是否自动提交,如果设置为true。
SqlSession

a、每个线程都应该有它自己的 SqlSession 实例,SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的范围是请求或方法范围。

b、绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例域也不行。也绝不能将 SqlSession 实例的引用放在任何类型的管理范围中,比如 Serlvet 架构中的 HttpSession。换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。

9、如下所示为纯 MyBatis 底层用法,如果是 myBatis + Sring Boot 集成,则无法在编写这种底层代码了。

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession= sqlSessionFactory.openSession();
try {BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);// do worksqlSession.commit();
} catch(Exception e){sqlSession.rollback();
} finally {session.close();
}

搭建 Spring boot + Mybatis 环境

1、新建 Spring boot 应用,pom.xml 文件引入相关依赖,比如 log4j2 日志、mysql 驱动、myBatis:https://gitee.com/wangmx1993/hb/blob/master/pom.xml

2、Mysql 数据库中准备好数据库、表、以及测试数据:创建 emp 与 dept 脚本.sql

3、类路径下提供 log4j2 日志配置文件:src/main/resources/log4j2.xml · 汪少棠/hb - Gitee.com

为了能清晰的看到 myBatis 执行的 sql,可以设置 myBatis 的日志输出基本为 debug:

<logger name="org.mybatis" level="debug"></logger>

4、application.yml 全局配置文件配置数据源与 myBatis:src/main/resources/application.yml · 汪少棠/hb - Gitee.com

5、提供 myBatis 核心配置文件: mybatis-config

6、jdbc 默认使用的 Hikari 数据源,可以写一个测试类 DataBaseTests 运行一下,看看数据库是否连接正常,此时需要先将 application.yml  中 myBatis 的配置暂时注释掉。

7、为了更好的封装接口返回的参数,提供返回数据实体和枚举:ResultData.java、ResultCode.java。

8、提供全局统一异常处理类:AppExceptionController.java

9、本文的 XxxMapper 映射接口在线源码目录:https://gitee.com/wangmx1993/hb/blob/master/src/main/java/com/wmx/hb/mapper

10、本文的 XxxMapper.xml 映射在线源码目录:/src/main/resources/myBatis/mapper

MyBatis 语法使用快速入门

resultType 设置查询结果类型

1.    resultType 是 <select> 标签中的属性,表示查询结果的类型。

2.    resultType 的值可以是基础类型,如 int、String;也可以是 POJO 对象,如 User,POJO 对象时要写全路径。

<!--查询表中的数据总条数-->
<select id="countForTable" resultType="long">select count(1) from dept
</select><!--返回值类型指定为 List 中的元素类型-->
<select id="findDeptEmp" resultType="java.util.Map">SELECT t1.*,t2.* from dept t1,emp t2 WHERE t1.deptno = #{deptno} and t1.deptno = t2.deptno;
</select><!-- select 表示查询标签,id 属性值是 DeptMapper 接口中的方法名称,resultType 指定返回值的类型-->
<!--可以不指定 parameterType 属性,此时会自动根据接口方法的参数类型进行映射-->
<select id="findDeptById" resultType="com.wmx.hb.pojo.Dept">select dept.deptno,dept.dname,dept.loc from dept where deptno = #{deptno}
</select>

parameterType 设置参数类型

1、parameterType 是 CRUD 标签中的属性,表示参数类型、参数映射,可以省略不写,此时会自动根据接口方法的参数进行映射。

2、parameterType 同样可以是基本数据类型如:int、flout等;也可以是POJO对象;甚至是List、Set、Array、Map等。

3、因为 Map 最灵活,所以项目中一般用 Map 最多,#{key} 取值的 key 就是 Map 中的 key。使用示例看下一节。

#{} VS ${} 取值对比

1、两者都是用于获取传入的参数值。

#{}表示一个占位符号,通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java类型和 jdbc 类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。 ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

2、#{}:会自动根据参数类型做封装,例如对字符串、日期类型,两边自动加单引号,而对数值类型直接使用。

3、${}:将传入的参数直接拼接到 SQL 中,例如拼接 order by xxx ,这是比较特殊的地方,也是 #{} 唯一无法做到的地方。

4、#{} 的好处是可以防止 SQL注入,因为非法用户传入的非法SQL只能是字符串类型,这样两头加上单引号后,SQL语法就错了,不会执行成功的()。

5、${} 取的值如果为 null,还容易报错,所以除非不得已,否则推荐一律使用 #{}。

//分页查询接口
@GetMapping("/dept/findByLimit")
public ResultData<List<Dept>> findByLimit(Integer page, Integer rows) {page = page == null || page <= 0 ? 1 : page;rows = rows == null || rows <= 0 ? 2 : rows;Map<String, Object> paramMap = new HashMap<>();paramMap.put("start", (page - 1) * rows);paramMap.put("end", (page - 1) * rows + rows);paramMap.put("orderColumn","dname");List<Dept> deptList = deptMapper.findByLimit(paramMap);return new ResultData<>(ResultCode.SUCCESS, deptList, null, page, rows);
}//deptMapper 映射接口方法
List<Dept> findByLimit(Map<String, Object> paramMap);<!--DeptMapper.xml 标签-->
<!-- 可以不指定 parameterType 属性,此时会自动根据接口方法的参数类型进行映射-->
<!-- order by 的值必须使用 ${} 取值}-->
<select id="findByLimit" resultType="com.wmx.hb.pojo.Dept" parameterType="map">select dept.deptno,dept.dname,dept.loc from dept order by ${orderColumn} limit #{start},#{end}
</select>
//比如想根据某列的值进行查询,其中 ${column} 会被直接替换,如  id,name,age...,而 #{value} 会使用 ? 预处理
//用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 SQL 注入攻击,
//因此,要么不允许用户输入这些字段(column),要么自行转义并检验这些参数。
@Select("select * from user where ${column} = #{value}")
List<User> findByColumn(String column, String value);

[CDATA[XXX]]> 转义小于符号

1、小于符号'<' 在 xml 文件中表示标签的开始,所以 sql 中的小于符号必须进行转义。

//查询薪资在[start,end]之间的员工,start 为空时,不设下限,end 为空时,不设上限.
@GetMapping("/emp/getEmpBySal")
public ResultData<Emp> getEmpBySal(Double start, Double end) {Map<String, Double> paramMap = new HashMap<>();paramMap.put("start", start);paramMap.put("end", end);List<Emp> empList = empMapper.getEmpBySal(paramMap);return new ResultData(ResultCode.SUCCESS, empList);
}//EmpMapper 接口方法
List<Emp> getEmpBySal(Map<String, Double> paramMap);<!--EmpMapper.xml 映射:小于符号'<'必须进行转义-->
<select id="getEmpBySal" resultType="com.wmx.hb.pojo.Emp" parameterType="map">select * from emp t<where><if test="start!=null">sal >= #{start}</if><if test="end != null"><![CDATA[and sal <= #{end}]]></if></where>
</select>

foreach 循环容器元素

1、foreach 元素的属性主要有:item,index,collection,open,separator,close
    item:集合中元素迭代时的别名
    index:集合中元素迭代时的索引
    open:常用语where语句中,表示以什么开始,比如以'('开始
    separator:表示在每次进行迭代时的分隔符,比如','
    close:常用语where语句中,表示以什么结束,比如以')'结尾
    collection:集合名称,通常是集合或者数组的参数名称,必传,其他的选项可选

2、collection 属性是必须指定的,在不同情况下,其值是不一样的,主要有以下3种情况:
    如果传入的是单参数且参数类型是一个List的时候,collection属性值为list.
    如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array.
    如果传入的参数是多参数,则需要把它们封装成一个Map,当然单参数也可以封装成map.
    
3、不管是多参数还是单参数的 list,array,set类型,collection  都可以封装为map进行传递。
    如果传递的是一个List,则mybatis会封装为一个list为key,list值为object的map,
    如果是array,则封装成一个array为key,array的值为object的map,
    如果自己封装呢,则colloection里放的是自己封装的map里的key值

4、注意 foreach 的集合或者数组如果为空,则抛异常。

//mapper 接口中提供方法:根据主键集合查询部门数据
List<Dept> findByDeptnos(List<Integer> deptnos);!--根据主键 id集合查询,deptnos 就是接口方法参数的名称,如果 foreach 的集合或者数组为空,则直接异常-->
<select id="findByDeptnos" resultType="com.wmx.hb.pojo.Dept">select * from dept<where><if test="deptnos !=null and deptnos.size > 0">deptno in<foreach collection="deptnos" item="deptno" index="index" open="(" separator="," close=")">#{deptno}</foreach></if></where>
</select>

concat 字符串拼接

1、concat 元素类似数据库的 concat 函数,用于拼接字符串.

//mapper 接口中提供方法:根据关键字模糊查询,默认查询所有
List<Dept> findByKeyword(String keyword);<!-- 对应 xml 中标签:根据关键字模糊查询,不为空时才拼 like 条件,否则默认查询所有.-->
<select id="findByKeyword" resultType="com.wmx.hb.pojo.Dept" parameterType="string">select * from dept<where><if test="keyword!=null">dname like concat('%',concat(#{keyword},'%')) or loc like concat('%',concat(#{keyword},'%'))</if></where>
</select>

choose (when, otherwise) 流程控制

1、choose 标签是按顺序判断其内部 when 标签中的 test 条件是否成立,如果有一个成立,则 choose 结束,其他的 when 以及 otherwise 都不会再走。

2、当 choose 中所有 when 的条件都不满足时,则执行 otherwise 中的 sql。

//mapper 接口中提供方法:按顺序将实体类 Emp 第一个不为空的属性作为 where 查询条件,默认查所有
List<Emp> getEmp(Emp emp);<!--对应 xml 中标签:choose-when-otherwise,其中一个 when 条件成立,则其他的都不会再走,所有 when 都不成立时,走 otherwise-->
<!-- select 表示查询标签,id 属性值是 XxxMapper 接口中的方法名称,resultType 指定返回值的类型-->
<!--可以不指定 parameterType 属性,此时会自动根据接口方法的参数类型进行映射-->
<select id="getEmp" resultType="com.wmx.hb.pojo.Emp" parameterType="com.wmx.hb.pojo.Emp">select * from emp<where><choose><when test="empno !=null">empno=#{empno}</when><when test="ename !=null and ename !=''">ename like concat('%',concat(#{ename},'%'))</when><when test="job !=null and job !=''">job like concat('%',concat(#{job},'%'))</when><when test="hiredate !=null">hiredate=#{hiredate}</when><otherwise></otherwise></choose></where>
</select>

if 条件判断

1、myBatis 中很多标签,如果参数为空,或者为 null,则容易出现异常,比如 foreach 的集合或者数组为空,则直接异常。

2、此时可以使用 if 动态 sql 语句先进行判断,如果值为 null 或等于空字符串,或者集合的 size<=0,则不进行操作。

where 条件语句

1、当 where 标签中有返回值时,where 标签会自动插入一个 'where' 字符串 sql .

2、当 where 标签返回的内容是以 AND 或 OR 开头,则会自动剔除掉 'and' 和 'or',不区分大小写。

//mapper 接口中提供方法:查询指定部门的信息,将实体对象中不为空的属性都作为 where 条件,默认查所有
List<Dept> findByDept(Dept dept);<!--对应 xml 中标签:拼接 where 条件前进行是否为空判断-->
<!--where 标签会自动删除内容开头的 and 或者 or 字符串   -->
<select id="findByDept" resultType="com.wmx.hb.pojo.Dept">SELECT t1.deptno,t1.dname,t1.loc from dept t1<where><if test="deptno!=null">deptno = #{deptno}</if><if test="dname!=null and dname !=''">and dname like concat('%',concat(#{dname},'%'))</if><if test="loc!=null and loc!=''">and loc like concat('%',concat(#{loc},'%'))</if></where>
</select>

if + set 修改语句

1、当在 update 语句中使用 if 标签时,如果后面的 if 没有执行,则结尾会产生多余的逗号,从而导致错误。

2、使用 set 标签可以动态的追加 SET 关键字,以及剔除追加到条件末尾的任何多余的逗号。

//mapper 接口中提供方法:根据主键id修改部门信息,只修改不为null,且不为空的属性
Integer updateDeptByNotNull(Dept dept);<!--对应 xml 中标签:set标签会自动去除内容结尾多余的逗号-->
<update id="updateDeptByNotNull" parameterType="com.wmx.hb.pojo.Dept">update dept t<set><if test="dname!=null and dname !=''">dname=#{dname},</if><if test="loc!=null and loc!=''">loc=#{loc}</if></set>where deptno=#{deptno}
</update>

trim 代替 where、set 标签

1、trim 是更灵活的去处多余关键字的标签,可以代替 where 和 set 标签。

prefix:表示为内容添加前缀,比如 where
    suffix:表示为内容添加后缀
    prefixOverrides:表示前缀覆盖,去除内容开头多余的前缀,如 'and'、'or'
    suffixOverrides:表示后缀覆盖,去除内容结尾多余的后缀,如 ','

2、trim标签代替 where标签,prefix 表示添加前缀 where,prefixOverrides 表示前缀覆盖,去除内容开头多余的 and 或者 or。

    <!--trim标签代替 where标签,prefix 表示添加前缀 where,prefixOverrides 表示前缀覆盖,去除前缀多余的 and 或者 or--><select id="loadByDept" resultType="com.wmx.hb.pojo.Dept">SELECT t1.deptno,t1.dname,t1.loc from dept t1<trim prefix="where" prefixOverrides="and|or"><if test="deptno!=null">deptno = #{deptno}</if><if test="dname!=null and dname !=''">and dname like concat('%',concat(#{dname},'%'))</if><if test="loc!=null and loc!=''">and loc like concat('%',concat(#{loc},'%'))</if></trim></select>

3、trim 标签代替 set 标签,prefix 表示添加前缀 set,suffixOverrides 表示后缀覆盖,去除内容结尾多余的逗号

    <!--trim标签代替 set 标签,prefix 表示添加前缀 set,suffixOverrides 表示后缀覆盖,去除内容结尾多余的逗号--><update id="modifyDeptByNotNull" parameterType="com.wmx.hb.pojo.Dept">update dept t<trim prefix="set" suffixOverrides=","><if test="dname!=null and dname !=''">dname=#{dname},</if><if test="loc!=null and loc!=''">loc=#{loc}</if></trim>where deptno=#{deptno}</update>

sql 片段标签定义 sql 片段

1、sql 片段标签 <sql> 可定义能复用的 sql 语句片段,在执行 sql 语句标签中直接引用即可。

2、<sql> 的属性 id="xxx" 值表示该 sql 语句片段的唯一标识.

3、引用 sql 片段:通过 <include refid="xxx" /> 标签引用,refid="" 中的值指向需要引用的<sql>中的id属性。

<!--定义 dept 表的列信息,查询标签可以直接引用,不用再每次都重复写一遍-->
<sql id="dept_columns">dept.deptno,dept.dname,dept.loc
</sql><!-- 查询所有,虽然返回值是一个 List<Dept>,但是 resultType 只需要指定列表元素的类型即可.-->
<!--include 引用定义好的 sql 片段-->
<select id="findAllDepts" resultType="com.wmx.hb.pojo.Dept">select <include refid="dept_columns"/> from dept;
</select>

MyBatis 集成 Spring boot 自动配置原理

Spring Boot 2.x 集成 MyBatis ,MyBatis 自动配置原理与自定义配置

@Param 定义 XxxMapper 方法多个参数

1、XxxMapper 接口方法中如果需要使用到多个参数,通常是封装成 POJO 对象,或者使用 Map 封装,而 Map 看起来不太直观,此时可以使用 myBatis 的 @Param 注解进行定义。

//控制层方法
@PostMapping("/findByDept")
public List<Dept> findByDept(@RequestBody(required = false) Dept dept, Integer pageNum, Integer pageSize) {pageNum = pageNum == null || pageNum <= 0L ? 1 : pageNum;pageSize = pageSize == null || pageSize <= 0L ? 2 : pageSize;List<Dept> deptList = deptMapper.findByDept(dept, pageNum, pageSize);return deptList;
}/**DeptMapper 接口方法* 1、查询指定部门的信息,将实体对象中不为空的属性都作为 where 条件,默认查所有。* 2、使用 org.apache.ibatis.annotations.Param 注解可以为 XxxMapper 接口方法指定多个参数。* 3、多个参数会被封装成一个 map,map 的 key 是使用 @Param 注解指定的值,value 是参数值。* 4、如果是级联对象,则 XxxMapper.xml 映射文件中也是级联取值,如 dept.deptno、dept.dname,前提是 dept 不能为 null,否则异常.* * @param dept* @param pageNum  :查询的页码,从1开始* @param pageSize :每页显示的条数* @return*/
List<Dept> findByDept(@Param("dept") Dept dept, @Param("pageNum") int pageNum, @Param("pageSize") int pageSize);<!--dept是对象,所以需要级联取值,必须不等于 null,才能级联取值-->
<!--拼接 where 条件前进行参数是否为空判断。返回值类型指定为 List 中的元素类型-->
<!--where 标签会自动删除内容开头的 and 或者 or 字符串   -->
<select id="findByDept" resultType="com.wmx.hb.pojo.Dept">SELECT t1.deptno,t1.dname,t1.loc from dept t1<where><if test="dept !=null and dept.deptno!=null">deptno = #{dept.deptno}</if><if test="dept !=null and dept.dname!=null and dept.dname !=''">and dname like concat('%',concat(#{dept.dname},'%'))</if><if test="dept !=null and dept.loc!=null and dept.loc!=''">and loc like concat('%',concat(#{dept.loc},'%'))</if></where>
</select>

MyBatis 持久化框架快速使用入门(Xml配置版)相关推荐

  1. 第 3-2 课:SpringBoot如何优雅地使⽤ MyBatis XML 配置版

    MyBatis 是现如今最流⾏的 ORM 框架之⼀,我们先来了解⼀下什么是 ORM 框架. ORM 框架 对象关系映射(Object Relational Mapping,ORM)模式是⼀种为了解决⾯ ...

  2. 【SpringMVC 笔记】SpringMVC 原理 + 入门项目(xml 配置版 vs 注解版)

    SpringMVC 入门项目 什么是 SpringMVC? 中心控制器 SpringMVC 执行原理 执行流程 xml 配置版 1.创建一个 Web 项目 2.pom.xml 中导入 SpringMV ...

  3. Spring Boot入门系列(六)Spring Boot如何使用Mybatis XML 配置版【附详细步骤】

    前面介绍了Spring Boot 中的整合Thymeleaf前端html框架,同时也介绍了Thymeleaf 的用法.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/z ...

  4. Ktor: Kotlin Web后端框架 快速开始入门

    Ktor: Kotlin Web后端框架 Web backend framework for Kotlin 快速开始入门 Ktor 简介 Ktor 是一个用于在 Kotlin 中快速创建 web 应用 ...

  5. Mybatis莫名报错或Mapper.xml配置后爆红或显示The error may exist in com/jdsydwr/dao/UserMapper.java找不到Mapper接口的修改方法

    报错内容 org.apache.ibatis.exceptions.PersistenceException:  ### Error building SqlSession. ### The erro ...

  6. 银行管理系统(使用SQL Server)-Python快速编程入门(第2版)-人民邮电出版社-阶段案例

    阶段案例-银行管理系统 题目描述 银行管理系统是一个集开户.查询.取款.存款.转账.锁定.解锁.退出等一系列业务于一体的管理系统,随着计算机技术在金融行业的广泛应用,银行企业采用管理系统替代了传统手工 ...

  7. Python快速编程入门 第2版 实训案例及课后编程题

    目录 本文档仅供参考,更新了 第2章 第3章 第4章 第5章 第6章 第7章 本文档仅供参考,更新了6.7章 第2章 2.4.1打印购物小票 蚂蚁森林是支付宝客户端发起"碳账户"的 ...

  8. 【python快速编程入门 第2版】第一章 python概述 习题

    一.填空题 1.Python是面向___对象的高级语言. 2.Python 可以在多种平台运行,这体现了Python语言_可移植性的特性. 3.Python模块的本质是.py文件. 4.使用impor ...

  9. spring整合mybatis的xml配置

    之前在SSM之Mybatis概览_数字公民某杨的博客-CSDN博客有这个示意图: mybatis框架有两类xml配置,一个是全局的xml,另一类是单个接口的xml. 当spring整合mybatis, ...

  10. java day53【 Mybatis框架概述 、 Mybatis 框架快速入门、自定义 Mybatis 框架 】

    第1章 框架概述 1.1 什么是框架 1.1.1 什么是框架 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种 定义认为,框架是可被应用开发者定 ...

最新文章

  1. 爬虫训练之--获取错误并将其保存进本地文件
  2. 分隔单词和标点符号示例
  3. SAP实施方法论之探讨-现状调研与需求分析
  4. 【GNN】2022年最新3篇GNN领域综述!
  5. EfficientNet论文阅读笔记
  6. allegro下快捷键设置[转贴]
  7. 点击率预估与冷启动(二)
  8. 开博啦——半路出家做运维以来的一些杂感
  9. 【渝粤教育】国家开放大学2018年春季 8636-22T实用心理学 参考试题
  10. 计算机的分类按cpu芯片可以分为,按CPU芯片可分为单片机、单板机、多芯片机和多板机...
  11. 解决办法:nvidia-settings:ERROR: Unable to load info from any available system
  12. 联想笔记本电脑安装完Ubuntu16.04出现搜索不到wifi的问题
  13. java工程师的职业规划_Java工程师如何进行职业规划?
  14. pathinfo 伪静态 详细解析PATH_INFO 和 ORIG_PATH_INFO技术分享
  15. win10驱动开发16——派遣函数(直接方式读操作)
  16. C语言蜗牛爬墙(个人练习)
  17. keil中出现警告:last line of file ends without a newline解决方法
  18. RAFT共识算法学习
  19. django中models的filter过滤方法
  20. EC11旋转编码器电路和程序

热门文章

  1. javascript 闭包和原型
  2. python代码怎么练_自己练习的Python代码(1)
  3. 拓端tecdat|关联规则APRIORI挖掘豆瓣读书评论爬虫采集数据与可视化
  4. 拓端tecdat|用于NLP的Python:使用Keras进行深度学习文本生成
  5. java未完成的标记,eclipse中的任务标记(TODO、FIXME、XXX)
  6. (5)Matplotlib_grid
  7. python导入上级目录的模块
  8. SQL语言概况(4.1)
  9. 为什么深度学习有效?(why deep learning works)
  10. cloudquery.php态势感知,CloudQuery v1.3.4 版本更新