36-Mybatis-qianfeng-笔记


文章目录

  • 36-Mybatis-qianfeng-笔记
  • 一、MyBatis简介
    • ①:框架概念
    • ②:常用框架
    • ③:MyBatis介绍
  • 二、MyBatis框架部署
    • ①:创建Maven项目
    • ②:在项目中添加MyBatis依赖
    • ③:创建MyBatis配置文件(模板文件)
  • 三、MyBatis框架的使用
    • ①:创建数据库
    • ②:安装lombok插件导入Lombok坐标
    • ③:创建实体类
    • ④:创建DAO接口,定义操作方法
    • ⑤:创建DAO接口的映射文件(Mapper)
  • 四、单元测试
    • ①:添加单元测试依赖
    • ②:创建单元测试类
    • ③:测试代码
  • 五、MyBatis的CRUD操作
    • ①:添加操作
    • ②:删除操作
    • ③:修改操作
    • ④:查询所有
      • 01.查询方法一
      • 02.查询方式二
    • ⑤:根据主键查询一条信息
    • ⑥:分页查询-多个参数
      • 01.方法一(arg0,arg1)
      • 02.方法二 (使用HashMap)
      • 03.方法三(使用@Param注解)
    • ⑦:查询总记录数(返回int)
    • ⑧:添加操作回填生成的主键
  • 六、MyBatis工具类
    • ①:手动提交事务
    • ②:自动提交事务
  • 八、MyBatis主配置文件
    • ①:properties标签
    • ②:settings标签
    • ③:typeAliases标签
    • ④:plugins标签
    • ⑤:environments标签
    • ⑥:mapper标签
  • 九、映射文件
    • ①:MyBatis Mapper初始化
    • ②:Mapper根标签
    • ③:insert标签
    • ④:delete标签
    • ⑤:update标签
    • ⑥:select标签
    • ⑦:resultMap标签
    • ⑧:cache标签
    • ⑨:sql片段和include
  • 十、分页插件
    • ①:添加分页插件的依赖
    • ②:配置插件
    • ③:分页实例
      • 01.不带条件分页
      • 02.带条件分页
  • 十一、关联映射
    • ①:实体关系
    • ②:创建项目,部署MyBatis框架
    • ③:一对一关联添加操作
      • 01.创建数据库
      • 02.创建实体类
      • 03.一对一添加操作 1
      • 04.一对一添加操作 2
    • ④:一对一关联查询操作
      • 01. 单表查询(查询User用户信息)
      • 02.两个表关联查询
        • 1. 关联查询方案1(连接查询)
        • 2.关联查询方案2(子查询)
    • ⑤:一对多关联查询
      • 01. 创建数据表
      • 02.创建实体类
      • 03.一对多关联查询
        • 1. 添加数据
        • 2.关联查询方式一(连接查询)
        • 3.关联查询方式二(子查询)
    • ⑥:多对一关联查询
      • 01.创建实体类
      • 02.关联查询方式一(连接查询)
      • 03. 关联查询方式二(子查询)
    • ⑦:多对多关联查询
      • 01.创建数据表
      • 02.关联查询方式一(连接查询)
      • 03.关联查询方式二(子查询)
  • 十二、动态SQL
    • ①:什么时动态SQL?
    • ②:动态SQL使用案例
      • 01.创建项目
      • 02.创建数据表
      • 03. 创建实体类
      • 03.添加数据
    • ③:动态SQL实现1(if)
    • ④:动态SQL实现2(where)
      • 01. 使用`<where>`标签
      • 02.使用`<trim>`标签
      • 03.`<foreach>`标签的使用
      • 04 `<if>标签`嵌入`<foreach>`标签
  • 十三、模糊查询
    • ①: MemberDAO中定义接口方法
    • ②:在MemberMapper中添加SQL语句
    • ③:测试代码
    • ④:#{}和${}的区别
  • 十四、MyBatis日志配置
    • ①:添加日志框架依赖
    • ②:添加日志配置文件
    • ③:日志信息的级别
  • 十五、整合Druid连接池
    • ①:常见的连接池
    • ②:添加Druid依赖
    • ③:将MyBatis的连接池替换为Druid
      • 01. 创建Druid连接池工厂
      • 02. 将DruidDataSourceFactory配置给MyBatis数据源
  • 十六、MyBatis缓存
    • ①:缓存的工作原理
    • ②:MyBatis缓存
      • 01.一级缓存(特性一)
      • 02.一级缓存(特性二)
      • 03.一级缓存(特性三)
      • 04.一级缓存(特性四)
    • ③:一级缓存使用存在的问题(两次查询与数据库不一致)
    • ④:二级缓存机制
    • ⑤:设置每次修改或查询后自动刷新缓存
  • 十七、延迟加载(只在子查询中生效)
    • ①:使用子查询完成(班级-->学生)一对多查询
    • ②:测试代码(不开启延迟加载)
    • ③:测试代码(开启延迟加载)

一、MyBatis简介

①:框架概念

框架,就是软件的半成品,完成了软件开发过程中的通用操作,程序员只需很少或者不用进行加工就能够实 现特定的功能,从而简化开发人员在软件开发中的步骤,提高开发效率。

②:常用框架

  • MWC框架:简化了Servlet的开发步骤

    • Struts
    • Struts2
    • SpringMVC
  • 持久层框架:完成数据库操作的框架
    • apache DBUtils
    • Hibernate
    • Spring JPA
    • MyBatis
  • 胶水框架:Spring
    • SSM Spring SpringMVC MyBatis
    • SSH Spring Struts2 Hibernate

③:MyBatis介绍

MyBatis.是一个半自动ORM框架
ORM (Object Relational Mapping)对象关系映射,将Java中的一个对象与数据表中一行记录一对应。
QRM框架提供了实体类与数据表的映射关系,通过映射文件的配置,实现对象的持久化。

  • MyBatis的前身是iBatis,iBatis是Apache软件基金会提供的一个开源项目
  • 2010年iBatisi迁移到Google code,正式更名为MyBatis
  • 2013年迁移到Github托管
  • MyBatis特点:
    • 支持自定义SQL、存储过程
    • 对原有的JDBC进行了封装,几乎消除了所有DBC代码,让开发者只需关注SQL本身
    • 支持XML和注解配置方式自定完成ORM操作,实现结果映射

二、MyBatis框架部署

框架部署,就是将框架引入到我们的项目中

①:创建Maven项目

  • Java 工程
  • Web工程
两者创建一个就可以了

②:在项目中添加MyBatis依赖

  • 在pom.xml中添加依赖

    • mybatis
    • mysql driver
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency>

③:创建MyBatis配置文件(模板文件)

MyBatis-config.xml 文件头

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration></configuration>
创建名为MyBatis文件
  • 配置数据库连接信息
    <!--在environments配置数据库连接后息--><!--在environments标签中可以定义多个environment标签,每个environment标签可以定义一套连接配置--><!-- default.属性,用来指定使用哪个environment标签--><environments default="mysql"><environment id="mysql"><!--transactionManager标签用于配置数据库管理方式--><transactionManager type="JDBC"></transactionManager><!--dataSource标签就是用来配置数据库连接信息--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/db_fmwy?characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment>
在mybatis-config.xml问及只能中配置数据库连接信息

三、MyBatis框架的使用

①:创建数据库

create table db_student(sid int primary key auto_increment,stu_num char(5) not null unique ,stu_name varchar(20) not null ,stu_gender char(2) not null ,stu_age int not null
);
tb_student表

②:安装lombok插件导入Lombok坐标

导入lombok坐标

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope>
</dependency>
安装lombok插件

③:创建实体类

  • @Data : 注在类上,提供类的get、set、equals、hashCode、toString等方法
  • @AllArgsConstructor :注在类上,提供类的全参构造
  • @NoArgsConstructor :注在类上,提供类的无参构造
  • @Setter :注在属性上,提供 set 方法
  • @Getter :注在属性上,提供 get 方法
  • @EqualsAndHashCode :注在类上,提供对应的 equals 和 hashCode 方法
  • @Log4j/@Slf4j :注在类上,提供对应的 Logger 对象,变量名为 log
Student.java

④:创建DAO接口,定义操作方法

StudentDAO.java

⑤:创建DAO接口的映射文件(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=""></mapper>
1. 创建模板
2. 在resources月录下,新建名为mappers文件夹
mappers中新建名为StudentMapper,xml的映射文件(根据模板创建)
3. 在映射问价中对DAO中定义的方法进行实现
public interface StudentDAO {public int insertStudent(Student student);public int deleteStudent(String stuNum);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--mapper文件相当于DA0接口的:实现类,,namespace属性要指定实现DAO接口的全限定名-->
<mapper namespace="com.it.dao.StudentDAO"><insert id="insertStudent">insert into db_student(stu_num, stu_name, stu_gender, stu_age)VALUES (#{stuNum},#{stuName},#{stu_Gender},#{stuAge})</insert><delete id="deleteStudent">delete from db_student where stu_num=#{stuNum}</delete>
</mapper>
4.将映射文件添加到主配置问价

四、单元测试

①:添加单元测试依赖

添加Junit依赖

        <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>

②:创建单元测试类

1.在被测试类名后alt+insert-选择Create Test

③:测试代码

    @Testpublic void insertStudent() {// 加载mybatis配置文件try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();// 会话工厂SqlSessionFactory factory = builder.build(is);// 会话(连接)SqlSession sqlSession = factory.openSession();// 通过会话获取DAO对象StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);// 测试StudentDAO中的方法int i = studentDAO.insertStudent(new Student(0, "10001", "张三", "男", 21));// 需要手动提交sqlSession.commit();System.out.println(i);} catch (IOException e) {e.printStackTrace();}}

五、MyBatis的CRUD操作

①:添加操作

略~可以参考上面的添加操作

②:删除操作

根据学号删除一条学生信息

1. 在StudentDAO中定义删除方法
2. 测试:在StudentDAO的测试类中添加测试方法
    @Testpublic void deleteStudent() {try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");// SqLSessionFactoryBuilderSqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();// SqLSessionFactory表示MyBatis的会话工厂SqlSessionFactory factory = builder.build(is);// SqlSession表示MyBatis与数据库,之间的会话:通过工厂方法设计模式SqlSession sqlSession = factory.openSession();// 通过SqLSession.对象调用getMapper方法获DAO接口对象StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);int i = studentDAO.deleteStudent("10001");sqlSession.commit();System.out.println(i);} catch (IOException e) {e.printStackTrace();}}
}

③:修改操作

根据学生学号,修改其他字段信息

1. 在StudentDAO中添加修改方法
2. 在StudentMapper.xml文件中新增修改sql语句
3.添加单元测试方法
    @Testpublic void testUpdateStudent(){try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(is);SqlSession sqlSession = factory.openSession();StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);int i = studentDAO.updateStudent(new Student(0, "10001", "李四", "♂", 18));sqlSession.commit();assertEquals(1,i);} catch (IOException e) {e.printStackTrace();}}
4. 运行测试代码

④:查询所有

1. 先在数据库中添加一些信息

01.查询方法一

1.在StudentDAO接口中定义方法
2. StudentMapper.xml问价中添加sql语句
3. 测试代码
    @Testpublic void testSelectStudent(){try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory function = builder.build(is);SqlSession sqlSession = function.openSession();StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);List<Student> studentList = studentDAO.selectStudent();for (Student s : studentList){System.out.println(s);}} catch (IOException e) {e.printStackTrace();}}

02.查询方式二

1. 只修改StudentMapper.xml中的sql语句即可

⑤:根据主键查询一条信息

1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码
    @Testpublic void testQueryStudent(){try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory function = builder.build(is);SqlSession sqlSession = function.openSession();StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);Student student = studentDAO.queryStudent("10001");System.out.println(student);} catch (IOException e) {e.printStackTrace();}}

⑥:分页查询-多个参数

01.方法一(arg0,arg1)

1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码

02.方法二 (使用HashMap)

1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码

03.方法三(使用@Param注解)

1. StudentDAO接口中定义方法
2. StudentMapper.xml问价中定义sql语句
3. 单元测试代码

⑦:查询总记录数(返回int)

1. StudentDAO接口中定义方法
2.在StudentMapper.xmlg配置sql,通过resultType指定当前操作的返回类型为int
3. 单元测试代码

⑧:添加操作回填生成的主键

  1. StudentDAO接口中定义添加方法(之前已经完成)
2.在StudentMapper.xmlg配置sql
3. 单元测试代码

六、MyBatis工具类

package com.it.utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;public class MyBatisUtil {private static SqlSessionFactory factory;private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();static {try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(is);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getFactory(){return factory;}public static SqlSession getSqlSession(){SqlSession sqlSession = local.get();if (sqlSession == null) {sqlSession = factory.openSession();local.set(sqlSession);}return sqlSession;}public static <T>T getMapper(Class<T> clas){SqlSession sqlSession = getSqlSession();return sqlSession.getMapper(clas);}
}

七、事务管理

SqlSession对象

  • getMapper(DAQ.class)):获取Mapper(DAQ接口的实例)
  • 事务管理

①:手动提交事务

  • sqlSession.commit();提交事务
  • sqlSession.rol1back();事务▣滚
    @Testpublic void testUpdateStudent(){// 1.当我们获取SqlSession对象时,默认开启了事务SqlSession sqlSession = myBatisUtil.getSqlSession();try {// 2.通过会话获取DAO对象StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);// 3.测试StudentDAO中的方法int i = studentDAO.updateStudent(new Student(0, "10001", "李四", "♂", 18));// 4.操作完成并成功后,需要手动提交sqlSession.commit();assertEquals(1,i);} catch (Exception e) {// 5.当操作出现异常,调用rollback进行回滚sqlSession.rollback();}}

②:自动提交事务

通过SqlSessionFactoryi调用openSession方法获取SqlSession对象时,可以通过参数设置事务是香自动提交:

  • 如果参数设置为true,表示自定提交事务:factory.openSession(true:
  • 如果参数设置为false,或者不设置参数,表示手动提交:factory.openSession0;/factory…openSession(false);
  1. MyBatisUTil代码优化
package com.it.utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;/*** @program: 02_mybatis_demo1* @description: 这是一个提供SqlSession的工具类* @author: Coke66666* @create: 2022-08-11 21:12**/public class MyBatisUtil {private static SqlSessionFactory factory;private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();static {try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(is);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getFactory(){return factory;}public static SqlSession getSqlSession(boolean isAutoCommit){SqlSession sqlSession = local.get();if (sqlSession == null) {sqlSession = factory.openSession(isAutoCommit);local.set(sqlSession);}return sqlSession;}public static <T>T getMapper(Class<T> clas){SqlSession sqlSession = getSqlSession(true);return sqlSession.getMapper(clas);}
}
  1. 测试代码(举例)
    @Testpublic void testUpdateStudent(){// 1.当我们获取SqlSession对象时,默认开启了事务SqlSession sqlSession = myBatisUtil.getSqlSession(true);try {// 2.通过会话获取DAO对象StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);// 3.测试StudentDAO中的方法int i = studentDAO.updateStudent(new Student(0, "10001", "李四", "♂", 18));// 4.操作完成并成功后,需要手动提交sqlSession.commit();assertEquals(1,i);} catch (Exception e) {// 5.当操作出现异常,调用rollback进行回滚sqlSession.rollback();}}
    @Testpublic void testSelectStudent(){MyBatisUtil myBatisUtil = new MyBatisUtil();StudentDAO studentDAO = myBatisUtil.getMapper(StudentDAO.class);List<Student> studentList = studentDAO.selectStudent();for (Student s : studentList){System.out.println(s);}}

八、MyBatis主配置文件

①:properties标签

用于设置键值对,或者加载属性文件

1. 在resources目录下创建jdbc.proper1es`文件,配置键值对如下:
mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/db_mybatis_demo1?characterEncoding=utf-8
mysql_username=root
mysql_password=root
2. 在mybatis-config,.xml中通过properties标签引用jdbc.properties文件;
引入之后,在配置environment时可以直接使用id地C.properties的key获取对应的value
3.代码测试

②:settings标签

    <!--设置mybatis属性--><settings><!--启动二级缓存--><setting name="cacheEnabled" value="true"/><!--启动延迟加载--><setting name="lazyLoadingEnabled" value="true"/></settings>

③:typeAliases标签

    <!--typeAliases标签用于给实体类取别名,在映射文件中可以直接使用别名来替代实体类的全限定名--><typeAliases><typeAlias type="com.it.pojo.Student" alias="Student"></typeAlias></typeAliases>
在映射文件中可以直接使用别名来替代实体类的全限定名

④:plugins标签

    <!--plugin 标签,用于配置myBatis插件(分页插件)--><plugins><plugin interceptor=""></plugin></plugins>

⑤:environments标签

  <!--在environments配置数据库连接后息--><!--在environments标签中可以定义多个environment标签,每个environment标签可以定义一套连接配置--><!-- default.属性,用来指定使用哪个environment标签--><environments default="mysql"><!--environment标签用于配置数据库连接信息--><environment id="mysql"><!--transactionManager标签用于配置数据库管理方式--><!--dataSource标签就是用来配置数据库连接信息type="DBC”可以进行事务的提交和回滚操作type="MANAGED”依赖容器完成事务管理,本身不进行事务的提交和回滚操作--><transactionManager type="JDBC"> </transactionManager><!--dataSource标签就是用来置数据库连接信息POOLED|UNPOOLED--><dataSource type="POOLED"><property name="driver" value="${mysql_driver}"/><property name="url" value="${mysql_url}"/><property name="username" value="${mysql_username}"/><property name="password" value="${mysql_password}"/></dataSource></environment></environments>

⑥:mapper标签

    <!-- 加载映射配置(映射文件、DAQ注解)--><mappers><mapper resource="mappers/StudentMapper.xml"></mapper></mappers>

九、映射文件

①:MyBatis Mapper初始化

②:Mapper根标签

mapper3文件相当于DAQ接口的‘实现类’,amespacel属性要指定实现DAQ接口的全限定名

③:insert标签

声明添加操作(sql:insert)
常用属性

  • id属性,绑定对应DAQ接口中的方法
  • parameterType属性,用以指定接口中对应方法的参数类型(可省略)
  • useGeneratedKeys属性,设置添加操作是否需要回填生成的主键
  • keyProperty属性,指定回填的id设置到参数对象中的哪个属性
  • timeout属性,设置此操作的超时时间,如果不设置则一直等待

主键回填

  • 方法一
    <insert id="insertStudent" useGeneratedKeys="true" keyProperty="stuId">insert into db_student(stu_num, stu_name, stu_gender, stu_age)VALUES (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})</insert>
  • 方法二
    <insert id="insertStudent"><selectKey keyProperty="stuId" resultType="java.lang.Integer">select last_insert_id()</selectKey>insert into db_student(stu_num, stu_name, stu_gender, stu_age)VALUES (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})</insert>

④:delete标签

声明删除操作

    <delete id="deleteStudent">deletefrom db_studentwhere stu_num = #{stuNum}</delete>

⑤:update标签

声明修改操作

    <update id="updateStudent">update db_studentset stu_name=#{stuName},stu_gender=#{stuGender},stu_age=#{stuAge}where stu_num = #{stuNum}</update>

⑥:select标签

声明查询操作

  • id属性,指定绑定方法的方法名
  • parameterType属性,设置参数类型
  • resultType属性,指定当前sq返回数据封装的对象类型(实体类)
  • resultMap属性,指定从数据表到实体类的字段和属性的对应关系
  • useCache属性,指定此查询操作是否需要缓存
  • timeout属性,设置超时时间
  • 方式一(不使用ResultMap)
    <!--resultType指定查询结果封装的对象的实体类--><!--resultSets指定当前操作返回的集合类型(可省略)--><select id="selectStudent" resultType="com.it.pojo.Student" resultSets="java.util.List">select stu_num stuNum, stu_name stuName, stu_gender stuGender, stu_age stuAgefrom db_student</select>
  • 方式二(使用ResultMap)
    <!--resultMap标签用于定义实体类与数据表的陕时关系(ORM)--><resultMap id="studentMap" type="Student"><id column="sid" property="stuId"/><result column="stu_num" property="stuNum"/><result column="stu_name" property="stuName"/><result column="stu_gender" property="stuGender"/><result column="stu_age" property="stuAge"/></resultMap><!--resultMap用于引用一个实体的映射关系,当配置了resultMap.之后resultType就可以省略--><select id="selectStudent" resultMap="studentMap">select stu_num, stu_name, stu_gender, stu_agefrom db_student</select>

⑦:resultMap标签

    <!--resultMap标签用于定义实体类与数据表的陕时关系(ORM)--><resultMap id="studentMap" type="Student"><id column="sid" property="stuId"/><result column="stu_num" property="stuNum"/><result column="stu_name" property="stuName"/><result column="stu_gender" property="stuGender"/><result column="stu_age" property="stuAge"/></resultMap>

⑧:cache标签

设置当前DAQ进行数据库操作时的缓存属性设置

<cache type=""size=""readonly="false"/>

⑨:sql片段和include

十、分页插件

分页插件是一个独立于MyBatis框架之外的第三方插件;

①:添加分页插件的依赖

PageHelper

        <!-- pagehelper分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.2.0</version></dependency>

②:配置插件

在mybatisl的主配置文件mybatis-config.xml中通过plugins标签进行配置

    <!--plugin 标签,用于配置myBatis插件(分页插件)--><plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins>

③:分页实例

01.不带条件分页

对学生信息进行分页查询

    @Testpublic void testSelectStudentByPage2(){StudentDAO studentDAO = myBatisUtil.getMapper(StudentDAO.class);PageHelper.startPage(1, 3);List<Student> studentList = studentDAO.selectStudent();PageInfo<Student> pageInfo = new PageInfo<Student>(studentList);List<Student> list = pageInfo.getList();for (Student student : list) {System.out.println(student);}

02.带条件分页

1. 在StudentDAO中定义接口方法
2.在StudentMapper中定义SQl语句
3. 测试代码
    @Testpublic void testSelectStudentByGender() {StudentDAO studentDAO = myBatisUtil.getMapper(StudentDAO.class);PageHelper.startPage(1, 5);List<Student> studentList = studentDAO.selectStudentByGender("♂");PageInfo<Student> pageInfo = new PageInfo<Student>(studentList);List<Student> list = pageInfo.getList();for (Student student : list) {System.out.println(student);}}

十一、关联映射

①:实体关系

实体一一数据实体,实体关系指的就是数据与数据之间的关系
例如:用户和角色、房屋和楼栋、订单和商品

实体关系分为以下四种:

一对一关联

实例:人和身份证、学生和学生证、用户基本信息和详情

数据表关系:

主键关联(用户表主键和详情主键相同时,表示是匹配的数据
唯一外键关联

一对多关联、多对一关联

实例:

  • 一对多:班级和学生、类别和商品
  • 多对一:学生和班级、商品和类别

数据表关系:

  • 在多的一瑞添加外键和一的一段进行关联

多对多关联

实例:用户和角色、角色和权限、房屋和业主、学生和社团、订单和商品

数据库关系 :

  • 建立第三张关系表添加两个外键分别与两张表主键进行关联
  • 用户(user_id)         用户角色表uid,rid)              角色(role_id)

②:创建项目,部署MyBatis框架

创建web项目(Maven)

  • 添加项目依赖
    <!-- 添加web依赖 --><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency>
  • 部署Maven框架
    <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>
  • 创建jdbc.properties配置数据库信息
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_mybatis?characterEncoding=utf-8
username=root
password=root
  • 创建mybatis-config.xml文件 配置数据库连接信息
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="jdbc.properties"/><environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"></transactionManager><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>
</configuration>
  • 创建工具类
public class MyBatisUtil {private static SqlSessionFactory factory;private static ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>();static {try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(is);} catch (IOException e) {e.printStackTrace();}}public static SqlSessionFactory getSqlSessionFactory(){return factory;}public static SqlSession getSession(boolean isAutoCommit) {SqlSession sqlSession = local.get();if (sqlSession == null){sqlSession = factory.openSession(isAutoCommit);local.set(sqlSession);}return sqlSession;}public static SqlSession getSession(){return getSession(false);}public static <T>T getMapper(Class<T> clazz) {SqlSession session = getSession(true);return session.getMapper(clazz);}
}

③:一对一关联添加操作

01.创建数据库

实例:用户-----详情

-- 用户信息表
create table users(user_id int primary key auto_increment,user_name varchar(20) not null unique ,user_pwd varchar(30) not null ,user_realname varchar(30) not null ,user_img varchar(100) not null
);-- 用户详情表
create table details(detail_id int primary key auto_increment,user_addr varchar(50) not null ,user_tel char(11) not null ,user_desc varchar(200),uid int not null  unique
);

02.创建实体类

  • 导入lombok依赖(使用注解@Data不用写 get set 方法)
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version><scope>provided</scope>
</dependency>


03.一对一添加操作 1

1. 在接口中定义方法
2. UserMapper中添加Sql语句
3.在MyBatis-config.xml中添加映射关系
4.测试代码

04.一对一添加操作 2

1. 在DetailDAO接口中定义方法
2. 在DetailMapper.xml文件中添加sql方法
3. 在mybatis-config.xml中添加映射关系
4. 测试代码

④:一对一关联查询操作

01. 单表查询(查询User用户信息)

1. 在UserDAO接口中定义查询方法
2. 在mybatis-config.xml文件中给DAO类起别名方便后续使用
3. 在UserMapper文件中添加查询Sql语句
4. 测试代码

02.两个表关联查询

1. 关联查询方案1(连接查询)

1. UserDao接口中定义方法
2. 在User类中加入detail属性
3. 在UserMapper文件中添加sql语句
    <select id="queryUserAndDetailByName" resultMap="userMap">select user_id, user_name, user_pwd, user_realname, user_img,detail_id, user_addr, user_tel, user_descfrom users ujoin details d on u.user_id = d.uidwhere user_name = #{userName};</select>
4. 在resultMap中添加detail属性映射关系
5. 测试代码

2.关联查询方案2(子查询)

1. 分别在UserDao和DetailDAO中定义接口方法
2. 分别在UserMapper和DetailMapper文件中添加sql语句
3. 测试代码

⑤:一对多关联查询

案例:班级(1)—> 学生(n)

01. 创建数据表

-- 创建班级信息表
create table classes(cid int primary key auto_increment,cname varchar(30) not null unique ,cdesc varchar(100)
);
-- 创建学生信息
create table students(sid char(5) primary key ,sname varchar(28) not null ,sage int not null ,scid int not null
);

02.创建实体类

Class班级类 student学生类

03.一对多关联查询

查询一个班级要关联查询出该班级下的所有学生

1. 添加数据

class班级表 student学生表

2.关联查询方式一(连接查询)

1. 创建ClazzDAO接口定义接口方法
2. 添加Mapper并起别名
3. 在ClazzMapper文件中添加Sql语句
4. 测试代码

3.关联查询方式二(子查询)

1.在ClazzDAO中定义接口方法 在StudentDAO中定义接口方法
2. 在mybatis-config.xml文件中添加映射关系
3.分别在ClazzMapper和StudentMapper文件中添加Sql语句
4. 测试代码

⑥:多对一关联查询

01.创建实体类

Students2 Clazz2

02.关联查询方式一(连接查询)

1. 定义接口方法
2. 创建Students2Mapper文件并在mybatis-config文件中进行关联
3. 在Student2Mapper文件中添加Sql语句
4. 测试代码

03. 关联查询方式二(子查询)

1. 分别在Student2DAO和Clazz2DAO接口中定义方法
2. 创建Clazz2Mapper文件并在mybatis-config文件中进行关联
3. 分别在Clazz2Mapper.xml和Student2Mapper.xml文件中添加Sql语句
4. 测试代码

⑦:多对多关联查询

案例:学生(m)—> 课程(n)

01.创建数据表

-- 课程信息表
create table courses(course_id int primary key auto_increment,course_name varchar(50) not null
);-- 课程信息
create table grades(sid char(5) not null ,cid int not null ,score int not null
);
添加数据

02.关联查询方式一(连接查询)

根据课程名称查询课程时,同时查询选择了这门课的学生

1. 创建实体类
2. 在CourseDAO添加接口方法
3. 创建CourseMapper.xml文件并在mybatis-config.xml文件中添加关联关系
4. CourseMapper.xml文件中添加Sql语句
5. 测试代码

03.关联查询方式二(子查询)

1. 分别在StudentDAO和CourseDAO中定义接口方法
2. 分别在StudentMapper.xml和CourseMapper.xml中添加语句
3. 测试代码

十二、动态SQL

①:什么时动态SQL?

根据查询条件动态完成SQL的拼接

②:动态SQL使用案例

案例:心仪对象搜索

01.创建项目

步骤略~ 可以参考上面的

02.创建数据表

create table members(member_id int primary key auto_increment,member_nick varchar(20) not null unique ,member_gender char(2) not null ,member_age int not null ,member_city varchar(30) not null
);

03. 创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Member {private int memberId;private String memberNick;private String memberGender;private int memberAge;private String memberCity;
}

03.添加数据

③:动态SQL实现1(if)

1. 创建MemberDAO接口并定义接口方法
2. 创建MemberMapper.xml文件并在mybatis-config.xml文件中关联
3. 在MemberMapper.xml文件中添加SQl语句
4. 测试代码

④:动态SQL实现2(where)

01. 使用<where>标签

1. 使用方法
2. 查询的结果还是一样的

02.使用<trim>标签

1. 使用方法
2. 查询结果

03.<foreach>标签的使用

1. 定义接口方法
2. 在MemberMapper文件中添加SQL语句
3. 测试代码

04 <if>标签嵌入<foreach>标签

1. 在MemberDAO中添加接口方法
2. 定义SQL语句
3. 测试代码

十三、模糊查询

//根据昵称查询用户信息--模糊查询
//模糊查询需要使用${}取值,与sq1进行拼接
//在使用${}时,即使只有一个参数也需要使用@Param注解声明参数的key(非String对象参数可以不用声明)

①: MemberDAO中定义接口方法

②:在MemberMapper中添加SQL语句

③:测试代码

④:#{}和${}的区别

  • S{key}表示获取参数,先获取参数的值拼接到SQL语句中,再编译执行SQL语句;可能引起SQL注入问题
  • #{ky}表示获取参数,先完成SQL编译(预编译),预编译之后再将获取的参数设置到SQL与中,可以避免SQL注入问题

十四、MyBatis日志配置

MyBatis做为一个封装好的QRM框架,其运行过程我们没办法跟踪,为了让开发者了解yBatis执行流程及每个执行步骤所完成的工作,MyBatis框架本身支持og4i日志框架,对运行的过程进行跟踪记录。我们只需对MyBatisi进行相关的日志配置,就可以看到MyBatisi运行过程中的日志信息。

①:添加日志框架依赖

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>

②:添加日志配置文件

  • 在resources目录下创建名为 log4j.properties文件(可以创建模板)
{.brush:xml;toolbar: .true; .auto-links: .false;}
log4j.rootLogger=DEBUG, INFO, ERROR
# 输出控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=INFO
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%p]%d{yyyy-MM-dd HH:mm:ss} %l -  %m%n

详细日志控制台

# Global logging configuration
# 设置日志输出级别以及输出目的地,可以设置多个输出目的地,开发环境下,日志级别要设置成DEBUG或者ERROR
# 前面写日志级别,逗号后面写输出目的地:我自己下面设置的目的地相对应,以逗号分开
# log4j.rootLogger = [level],appenderName1,appenderName2,…
log4j.rootLogger=DEBUG,CONSOLE,LOGFILE#### 控制台输出 ####
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
# 输出到控制台
log4j.appender.CONSOLE.Target = System.out
# 指定控制台输出日志级别
log4j.appender.CONSOLE.Threshold = DEBUG
# 默认值是 true, 表示是否立即输出
log4j.appender.CONSOLE.ImmediateFlush = true
# 设置编码方式
log4j.appender.CONSOLE.Encoding = UTF-8
# 日志输出布局
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%c:%L) - %m%n#### 输出错误信息到文件 ####
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
# 指定输出文件路径
#log4j.appender.LOGFILE.File =F://Intellij idea/logs/error.log
log4j.appender.LOGFILE.File =./logs/error.log #日志输出到文件,默认为true
log4j.appender.LOGFILE.Append = true
# 指定输出日志级别
log4j.appender.LOGFILE.Threshold = ERROR
# 是否立即输出,默认值是 true,
log4j.appender.LOGFILE.ImmediateFlush = true
# 设置编码方式
log4j.appender.LOGFILE.Encoding = UTF-8
# 日志输出布局
log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout
# 如果日志输出布局为PatternLayout 自定义级别,需要使用ConversionPattern指定输出格式
log4j.appender.LOGFILE.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

③:日志信息的级别

级别 描述
ALL 所有级别包括自定义级别。
DEBUG 调试消息日志。
ERROR 错误消息日志,应用程序可以继续运行。
FATAL 严重错误消息日志,必须中止运行应用程序。
INFO 输出提示消息。
OFF 最高可能的排名,旨在关闭日志记录。
TRACE 高于DEBUG。
WARN 用于警告消息。

十五、整合Druid连接池

MyBatis做为一个ORM框架,在进行数据库操作时是需要和数据库连接池连接的,MyBatis支持基于数据库连接池的连接创建方式。
当我们配置MyBatis数据源时,只要配置了data Source标签的type属性值为POOLEDI时,就可以使用MyBatis内置的连接池管理连接。
如果我们想要使用第三方的数据库连接池,则需进行自定义配置。

①:常见的连接池

  • DBCP
  • C3PO
  • Druid性能也比较好,提供了比较便捷的监控系统
  • Hikari性能最好
功能 dbcp druid c3p0 tomcat-jdbc HikariCP
是否支持PSCache
监控 jmx jmx/log/http jmx,log jmx jmx
扩展性
sql拦截及解析 支持
代码 简单 中等 复杂 简单 简单
更新时间 2015.8.6 2015.10.10 2015.12.09 2015.12.3
特点 依赖于common-pool 阿里开源,功能全面 历史久远,代码逻辑复杂,且不易维护 优化力度大,功能简单,起源于boneCP
连接池管理 LinkedBlockingDeque 数组 FairBlockingQueue threadlocal+CopyOnWriteArrayList

②:添加Druid依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version>
</dependency>

③:将MyBatis的连接池替换为Druid

01. 创建Druid连接池工厂

public class DruidDataSourceFactory extends PooledDataSourceFactory {public DruidDataSourceFactory() {this.dataSource = new DruidDataSource();}
}

02. 将DruidDataSourceFactory配置给MyBatis数据源

    <environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"/><!--POOLED使MyBatis内置的,连接池实现--><!--mybatis.需要一个连接池工厂,这个工厂可以产生数据库连接池PooLedDataSourceFactory--><dataSource type="com.it.utils.DruidDataSourceFactory"><property name="driverClass" value="${driver}"/><property name="jdbcUrl" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>

十六、MyBatis缓存

MyBatis是基于DBC的封装,使数据库操作更加便捷;MyBatisl除了对JDBC操作步骤进行封装之外也对其性能进行了优化:

  • 在MyBatis引入缓存机制,用于提升MyBatis的检索效率

①:缓存的工作原理

②:MyBatis缓存

MyBatis缓存分为一级缓存和二级缓存

01.一级缓存(特性一)

一 级缓存也叫做SqlSession级缓存,为每个SqlSession单独分配的缓存内存,无需手动开启可直接使用;多个SqlSessionl的缓存是不共享的。

1.如果多次查询使用的是同一个SqlSession对象,则第一次查询之后数据会存放到缓存,后续的查询则直接访问缓存中存储的数据:

1. 在MemberDAO中定义接口方法
2. MemberMapper.xml中添加SQL语句
3.测试代码(使用同一SqlSession)
4.测试代码(使用不同的SqlSession)

02.一级缓存(特性二)

2.如果第一次查询完成之后,对查询出的对象进行修改(此修改会影响到缓存),第二次查询会直接访问缓存,造成第二次查询的结果与数据库不一致;

1. 不清楚缓存

03.一级缓存(特性三)

3.当我们进行在查询时想要跳过缓存直接查询数据库,则可以通过sqlSession…clearCache0;来清除当前SqlSession的缓存;

1. 进行缓存清除

04.一级缓存(特性四)

4.如果第一次查询之后第二查询之前,使用当前的sqlsession执行了修改操作,此修改操作会使第一次查询并缓存的数据失效,因此第二次查询会再次访问数据库。

1. 新增修改方法
2. 添加修改语句
3, 测试代码

③:一级缓存使用存在的问题(两次查询与数据库不一致)

④:二级缓存机制

二级缓存也称为SqlSessionFactory级缓存,通过同一个factory对象获取的Sqlsession可以共享二级缓存;在应
用服务器中SqlSessionFactory是单例的,因此我们二级缓存可以实现全局共享。
特性:

  • 1.二级缓存默认没有开启,需要在mybatis-config,xml中的settings标签开启
  • 2.二级缓存只能缓存实现序列化接口的对象
1. 在mybatis-config.xml文件中开启二级缓存
    <settings><setting name="cacheEnabled" value="true"/></settings>
2. 在需要使用二级缓存的Mapper文件中配置cache标签使用功能二级缓存
<cache/>

2.1<cache/>中标签的使用
3.使用二级缓存(被缓存的实体类实现序列化接口)
4. 测试代码1
(第一次查询,之后执行sqlSession1.commit(),会将当前sqlsession的查询结果缓存到二级缓存)
5. 测试代码2

⑤:设置每次修改或查询后自动刷新缓存

true:使用缓存 fase:不使用缓存

十七、延迟加载(只在子查询中生效)

延迟加载–如果在MyBatis开启了延迟加载,在执行了子查询(至少查询两次及以上)时,默认只执行第一次查询,当用到子查询的查询结果时,才会触发子查询的执行;如果无需使用子查询结果,则子查询不会执行。

①:使用子查询完成(班级–>学生)一对多查询

1.分别创建两个实体类(Student)(Clazz)
2. 创建两个实体类的Mapper文件并在mybatis-config文件中起别名等
3.在ClazzDAO中添加接口方法
4. 在ClazzMapper文件中添加Sql语句
5.在StudentDAO中添加接口方法
6在ClazzMapper文件中添加Sql语句

②:测试代码(不开启延迟加载)

1. 不开启延迟加载情况下只打印班级名称

③:测试代码(开启延迟加载)

1. 开启延迟加载
2.测试代码1(发现并没有去查询学生信息)
3.测试代码(查询学生信息)

36-Mybatis相关推荐

  1. Java设计流程执行器_Java进阶面试精选系列:SpringMVC+SpringBoot+Hibernate+Mybatis+设计模式...

    小编精心收集:为金三银四准备,以下面试题先过一遍,为即将到了的面试做好准备,也过一遍基础知识点. 一.Spring/Spring MVC 1.为什么要使用 spring? 2.解释一下什么是 aop? ...

  2. 一个基本的spring+mybatis所需要的包

    spring+mybatis需要的包: org.springframework.spring-webmvc(spring框架DispatcherServlet需要,spring-webmvc会依赖sp ...

  3. 尚硅谷 MyBatis 新版视频教程发布

    人是这样的-- 一旦有了对别人的期待, 就可能承受期待带给你的痛苦. 真实的世界很残酷, 永远不要把期待放在别人身上, 因为别人没有义务要实现你的期待. 除非-- 这个"别人"是尚 ...

  4. java面试开发过程中用到的问题

    1.如何解决线程安全问题? 使用同步关键字synchronized. 2.类的加载过程:加载.验证.准备.解析.初始化. 3.java中的集合,有何区别? LIst:有序排列元素,元素可以重复. Se ...

  5. 项目管理与SSM框架——Spring

    Spring 文章目录 Spring @[TOC](文章目录) 一.Spring介绍 1.Spring简介 2.Spring体系结构 二.SpringIOC 1.控制反转思想 2.自定义对象容器 3. ...

  6. Java系列技术之Mybatis3-钟洪发-专题视频课程

    Java系列技术之Mybatis3-106人已学习 课程介绍         Mybatis3.4.6里的基础核心用法以及涉及到的ssm初步整合,mbg代码生成工具使用,分页插件的使用,学完这门课程M ...

  7. 经过半个月的深入发现CRM-SSM项目如此简单

    ​ ​ 活动地址:CSDN21天学习挑战赛 学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩:迟一天就多一天平庸的困扰.各位小伙伴,如果您: 想系统/深入学习某技术知识点- 一个人摸索学习很难坚持 ...

  8. 史上最强Java八股文面试题,堪称2023最强!!!

    前言 很多同学会问Java面试八股文有必要背吗? 我的回答是:很有必要.你可以讨厌这种模式,但你一定要去背,因为不背你就过不了. 国内的互联网面试,恐怕是现存的.最接近科举考试的制度. 而且,我国的八 ...

  9. 史上最强的Java八股文面试,堪称2022年最强!!!

    篇幅所限本文就只贴一下题目了,同学们可以自己先看看有哪些题是会的,答案的话我整理的一本<Java面试八股文>PDF里都有,获取的方法在文末名片了哦! 一.Java基础 44 道 1. 解释 ...

  10. 【面经一】Java高级面经

    文章目录 一.Java基础 1. 解释下什么是面向对象?面向对象和面向过程的区别? 2. 面向对象的三大特性?分别解释下? 3. JDK.JRE.JVM 三者之间的关系? 4. 重载和重写的区别? 5 ...

最新文章

  1. Python3中的成员保护和访问限制
  2. MVC的Model Binder总结
  3. pycharm连接远程mysql_CentOS7安装mysql以及使用pycharm远程连接mysql时遇到的问题
  4. ThreadLocal应用-使用ThreadLocal做线程缓存变量池
  5. Android界面开发工具DroidDraw
  6. 程序员面试金典——17.6最小调整有序
  7. eclipse的全局替换快捷键
  8. 笔记本键盘有几个键失灵了怎么办?
  9. 20135231 —— Linux 基础入门学习
  10. 显示屏色温调节 影响 测试软件,教你把显示器调到最佳效果
  11. 豆瓣电影top250信息爬取
  12. Matlab LZW编码
  13. Re:从0开始的微服务架构:(二)如何快速体验微服务架构?
  14. layui表格重载后界面闪动解决方案
  15. UNI-APP,推广二维码页面实现
  16. 获取img的src 或者给img赋值
  17. unity使用ugui自制调色面板
  18. 数据分析平台要点梳理
  19. vue项目中 使用百度地图 轨迹动画
  20. 将两个有序数组合并成一个有序数组

热门文章

  1. 计算机电子电路原理图,学看电路原理图入门知识积累
  2. CST2018学习笔记:六、构建喇叭模型
  3. 编译Android系统源码--搭建环境
  4. 远程控制,我用MicroSoft 远程桌面连接
  5. ctfshow--网络迷踪
  6. (程序员的“玩笑”)超简单的bat木马病毒
  7. DVD Slideshow Builder V6.2 软件原创打包
  8. Windows下使用脚本文件删除指定文件
  9. CUDA10.1安装 +VS2015开发环境搭建
  10. windos 批处理