2021-09-22


typora-copy-images-to: img


MyBatis_01

学习目标

  • 能够了解什么是框架
  • 掌握Mybatis框架开发快速入门
  • 掌握Mybatis框架的基本CRUD操作
  • 掌握SqlMapConfig.xml配置文件
  • 掌握Mybatis的parameterType的配置
  • 掌握Mybatis的resultType的配置
  • 了解Mybatis连接池与事务操作
  • 掌握Mybatis动态SQL

第一章-框架概述

知识点-框架概述

1.目标

  • 能够了解什么是框架

2.路径

  1. 什么是框架
  2. 框架要解决的问题

3.讲解

3.1什么是框架

​ 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。

​ 简而言之,框架是软件(系统)的半成品,框架封装了很多的细节,使开发者可以使用简单的方式实现功能,大大提高开发效率。

​ 开发好比表演节目, 开发者好比演员, 框架好比舞台.

3.2框架要解决的问题

​ 框架要解决的最重要的一个问题是技术整合的问题,在 J2EE 的 框架中,有着各种各样的技术,不同的软件企业需要从J2EE 中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。

​  框架一般处在低层应用平台(如 J2EE)和高层业务逻辑之间的中间层。

4.小结

  1. 框架: 框架可以封装重复代码,提供更简洁的API;框架可以实现代码间的解耦
  2. SSM框架

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LW8iC4w-1632266516439)(img/image-20191226084539029.png)]

知识点-MyBatis框架概述

1.目标

  • 能够了解什么是MyBatis

2.路径

  1. jdbc 程序回顾
  2. MyBatis框架概述

3.讲解

3.1jdbc 程序回顾
3.1.1程序回顾
  • 注册驱动
  • 获得连接
  • 创建预编译sql语句对象
  • 设置参数, 执行
  • 处理结果
  • 释放资源
    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //1.加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.通过驱动管理类获取数据库链接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "123456"); 
            //3.定义 sql 语句 ?表示占位符
            String sql = "select * from user where username = ?";
            //4.获取预处理 statement
            preparedStatement = connection.prepareStatement(sql);
            //5.设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
            preparedStatement.setString(1, "王五");
            //6.向数据库发出 sql 执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            //7.遍历查询结果集
            while (resultSet.next()) {
                System.out.println(resultSet.getString("id") + "
                        "+resultSet.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
		//8.释放资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
3.1.2jdbc 问题分析
  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
  2. Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大, sql 变动需要改变java 代码。
  3. 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名), sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便
3.2 MyBatis框架概述

​ mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

​ mybatis 通过xml 或注解的方式将要执行的各种statement 配置起来,并通过java 对象和statement 中sql的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql并将结果映射为 java 对象并返回。

​ 采用 ORM 思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与 jdbc api打交道,就可以完成对数据库的持久化操作。

​ 官网: http://www.mybatis.org/mybatis-3/

4.小结

  1. MyBatis: 持久层的一个框架, 封装了JDBC. 操作数据库
  2. 为什么要学习MyBatis?
    • JDBC和DBUtils都有一些很明显的缺点, JDBC和DBUtils不适合做项目
    • MyBatis是工作里面的主流的持久层框架, 使用几率特别大

第二章-Mybatis入门

案例-Mybatis快速入门

1.需求

  • 使用MyBatis查询所有的用户, 封装到List集合

2.分析

  1. 创建Maven工程(jar), 添加坐标
  2. 创建pojo
  3. 创建UserDao接口
  4. 创建UserDao映射文件
  5. 创建MyBatis核心配置文件SqlMapConfig.xml
  6. 编写java代码测试

3.实现

3.1准备工作
  • 数据库
CREATE DATABASE mybatis_day;
USE mybatis;
CREATE TABLE t_user(
		uid int PRIMARY KEY auto_increment,
		username varchar(40),
	 	sex varchar(10),
		birthday date,
		address varchar(40)
);

INSERT INTO `t_user` VALUES (null, 'zs', '男', '2018-08-08', '北京');
INSERT INTO `t_user` VALUES (null, 'ls', '女', '2018-08-30', '武汉');
INSERT INTO `t_user` VALUES (null, 'ww', '男', '2018-08-08', '北京');
3.2.MyBatis快速入门

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v5ZmFpj6-1632266516441)(img/tu_10-1574303439390.png)]

3.2.1创建Maven工程(jar)导入坐标
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!--引入lombok的依赖-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.10</version>
    </dependency>
    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <!--mybatis的依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.3</version>
    </dependency>
  </dependencies>
3.2.2创建User实体类
  • User .java
public class User implements Serializable{
    private int uid; //用户id
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址
	
}
3.2.3 创建 UserDao 接口
  • UserDao 接口就是我们的持久层接口(也可以写成 UserMapper) .我们就写成UserDao ,具体代码如下:
public interface UserDao {
    public List<User> findAll();
}
3.2.4 创建 UserDao.xml 映射文件

注意:

  1. 映射配置文件存储的路径在resources里面,要和对应的Dao接口的路径保持一致
  2. 映射配置文件的文件名必须和Dao接口名保持一致
  3. 一定要引入约束文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MdIuGr0w-1632266516442)(img/1544705827942-1574303439289.png)]

<?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">
<!--namespace属性: 接口类的全限定名-->
<mapper namespace="com.itheima.dao.UserDao">
    <!--
        每一个子标签,就对应Dao接口中的一个方法
            查询方法就对应select标签
            添加方法就对应insert标签
            删除方法就对应delete标签
            修改方法就对应update标签

        标签的id就对应方法的名字

        标签的parameterType就对应方法的参数类型

        标签的resultType(只有select标签才有)就对应方法的返回值类型,如果返回值类型是List,那么
        resultType就是List的泛型类型
    -->
    <select id="findAll" resultType="com.itheima.pojo.User">
        select * from t_user
    </select>
</mapper>
3.2.5 创建 SqlMapConfig.xml 配置文件(核心配置文件)

注意事项

  1. 存放路径必须是resources的根路径
  2. 配置文件的名字,随便写
  3. 一定要引入约束文件
<?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>

    <!--配置连接数据库的环境 default:指定使用哪一个环境-->
    <environments default="dev">
        <environment id="dev">
            <!--配置事务,MyBatis事务用的是jdbc-->
            <transactionManager type="JDBC"/>
            <!--配置连接池, POOLED:使用连接池(mybatis内置的); UNPOOLED:不使用连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_day01?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
        <environment id="test">
            <!--配置事务,MyBatis事务用的是jdbc-->
            <transactionManager type="JDBC"/>
            <!--配置连接池, POOLED:使用连接池(mybatis内置的); UNPOOLED:不使用连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_day02?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--引入映射文件; resource属性: 映射文件的路径-->
        <mapper resource="com/itheima/dao/UserDao.xml"/>
    </mappers>
</configuration>
3.2.6测试
@Before
public void init() throws IOException {
    //1. 创建SqlSessionFactoryBuilder对象
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    //2. 读取核心配置文件,转换成字节输入流
    is = Resources.getResourceAsStream("SqlMapConfig.xml");
    //3. 创建SqlSessionFactory对象
    SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(is);
    //4. 创建SqlSession对象
    sqlSession = sessionFactory.openSession();
    //5. 创建UserDao的代理对象
    userDao = sqlSession.getMapper(UserDao.class);
}
@Test
public void testFindAll(){
    //测试执行findAll()方法
    //6. 调用你想执行的方法
    List<User> userList = userDao.findAll();

    for (User user : userList) {
        System.out.println(user);
    }
}
@After
public void destroy() throws IOException {
    //提交事务!!!!!!!!!!!!!
    sqlSession.commit();
    //7. 关闭资源
    sqlSession.close();
    is.close();
}

4.小结

4.1步骤

​ 1. 创建maven工程(javase)

2. 引入依赖:mysql、mybatis、Junit、lombok
3. 创建POJO类、创建Dao接口
4. 创建Dao接口对应的映射配置文件
5. 创建mybatis的核心配置文件
6. 编写mybatis的测试代码进行测试 

知识点-Mapper动态代理方式规范

1.目标

  • 掌握Mapper动态代理方式规范

2.路径

  1. 入门案例回顾
  2. 规范

3.讲解

3.1入门案例回顾
3.1.2Mapper.xml(映射文件)
  1. 映射配置文件存储的路径在resources里面,要和对应的Dao接口的路径保持一致

  2. 映射配置文件的文件名必须和Dao接口名保持一致

  3. 一定要引入约束文件

  4. namespace属性的值和对应Dao接口的全限定名一致

  5. 每一个子标签,就对应Dao接口中的一个方法
    查询方法就对应select标签
    添加方法就对应insert标签
    删除方法就对应delete标签
    修改方法就对应update标签
    
    标签的id就对应方法的名字
    
    标签的parameterType就对应方法的参数类型
    
    标签的resultType(只有select标签才有)就对应方法的返回值类型,如果返回值类型是List,那么
    resultType就是List的泛型类型
    
<?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.itheima.dao.UserDao">
    <select id="findAll" resultType="User">
        SELECT *FROM t_user
    </select>
</mapper>
3.1.2Mapper.java(dao接口)
public interface UserDao {
    /**
     * 查询所有的用户
     * @return
     */
    List<User> findAll();
}
3.2规范

Mapper接口开发需要遵循以下规范:

  1. 存储路径建议和对应的Dao接口保持一致
  2. 文件名建议和对应Dao接口的名字保持一致
  3. 配置文件的根标签的namespace属性必须和对应的Dao接口的全限定名保持一致
  4. 接口中的每一个方法,就对应映射配置文件中的一个标签:
    1. 查询方法,对应select标签
    2. 添加方法,对应insert标签
    3. 删除方法,对应delete标签
    4. 修改方法,对应update标签
  5. 映射配置文件中的标签的id属性,就必须和对应的方法的方法名保持一致
  6. 映射配置文件中的标签的parameterType属性,必须和对应的方法的参数类型(全限定名)保持一致
  7. 映射配置文件中的标签的resultType属性,必须和对应的方法的返回值类型(全限定名)保持一致,但是如果返回值是List则和其泛型保持一致

4.小结

  1. 我们使用MyBatis 遵循这些规范

知识点-核心配置文件详解

1.目标

  • 掌握SqlMapConfig.xml配置文件

2.路径

  1. 核心配置文件的顺序
  2. properties
  3. typeAliases
  4. Mapper

3.讲解

3.1.核心配置文件的顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-42j2Mxkm-1632266516444)(img/image-20191226095424936.png)]

properties(引入外部properties文件)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

​ environment(环境子属性对象)

​ transactionManager(事务管理)

​ dataSource(数据源)

mappers(映射器)

3.2.properties
  • jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_day01?characterEncoding=utf-8
jdbc.user=root
jdbc.password=123
  • 引入到核心配置文件
<configuration>
   <properties resource="jdbc.properties">
    </properties>
    <!--数据源配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="UNPOOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    ....
</configuration>
3.3.typeAliases(类型别名)
3.3.1定义单个别名
  • 核心配置文件
<typeAliases>
      <typeAlias type="com.itheima.bean.User" alias="user"></typeAlias>
 </typeAliases>
  • 修改UserDao.xml
<select id="findAll" resultType="user">
    SELECT  * FROM  user
</select>
3.3.2批量定义别名

使用package定义的别名:就是pojo的类名,大小写都可以

  • 核心配置文件
<typeAliases>
    <package name="com.itheima.bean"/>
</typeAliases>
  • 修改UserDao.xml
<select id="findAll" resultType="user">
         SELECT  * FROM  user
</select>
3.4.Mapper
3.4.1方式一:引入映射文件路径
<mappers>
     <mapper resource="com/itheima/dao/UserDao.xml"/>
 </mappers>
3.4.2方式二:扫描接口
  • 配置单个接口
<mappers>
 	<mapper class="com.itheima.dao.UserDao"></mapper>
</mappers>
  • 批量配置
<mappers>
   <package name="com.itheima.dao"></package>
</mappers>

4.小结

  1. 核心配置文件的顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJ1GH7Ru-1632266516445)(img/image-20191226101317581.png)]

  1. properties 引入properties文件的
    • 创建properties文件
    • 使用 <properties resource="文件的路径"/>
    • 使用 ${key}
  2. typeAliases(类型别名) 在Dao映射文件里面 直接写类(pojo)的名字, 不需要写类全限定名了
<typeAliases>
    <package name="com.itheima.bean"/>
</typeAliases>
  1. Mapper 引入Dao映射文件的
<mappers>
   <package name="com.itheima.dao"></package>
</mappers>

第三章-MyBatis进阶

案例-使用Mybatis完成CRUD

1.需求

  • 使用Mybatis完成CRUD

2.分析

  1. 在Dao接口定义方法
  2. 在Dao映射文件配置

3.实现

3.1新增用户
3.1.1实现步骤
  • UserDao中添加新增方法
public interface UserDao {
    /**
     * 保存用户
     * @param user
     */
    void save(User user);
}
  • 在 UserDao.xml 文件中加入新增配置
    <insert id="save" parameterType="com.itheima.bean.User">
        INSERT INTO t_user(username,sex,birthday,address) VALUES (#{username},#{sex},#{birthday},#{address})
    </insert>

	<!--我们可以发现, 这个 sql 语句中使用#{}字符, #{}代表占位符,我们可以理解是原来 jdbc 部分所学的?,它们都是代表占位符, 具体的值是由 User 类的 username 属性来决定的。
	parameterType 属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的
全名称。-->
  • 添加测试类中的测试方法
@Test
public void testAddUser(){
    //1. 创建一个User对象
    User user = new User(0, "eson", "男", new Date(), "香港");
    //2. 调用userDao对象的addUser()方法添加用户信息
    userDao.addUser(user);
}
3.1.2新增用户 id 的返回值

​ 新增用户后, 同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回。

  • SelectKey获取主键
属性描述
keyPropertyselectKey 语句结果应该被设置的目标属性。
resultType结果的类型。MyBatis 通常可以算出来,但是写上也没有问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。
order这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素-这和如 Oracle 数据库相似,可以在插入语句中嵌入序列调用。

UserDao.xml

    <!--parameterType属性: 参数的类型 ;  赋值的时候直接写对象里面的属性名-->
    <insert id="save" parameterType="com.itheima.bean.User">
        <!--presultType: 主键类型; keyProperty:pojo里面对应的id的属性名; order属性: 指定是在目标的sql语句之前还是之后执行 -->
        <selectKey resultType="int" keyProperty="uid" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO t_user(username,sex,birthday,address)VALUES(#{username},#{sex},#{birthday},#{address})
    </insert>
3.2根据id查询用户
  • UserDao添加根据id查询方法
User findById(Integer id);
  • UserDao.xml文件中新增配置
<!--
   对应findById()方法
-->
<select id="findById" parameterType="int" resultType="user">
    select * from t_user where uid=#{id}
</select>
3.3修改用户
  • UserDao中添加修改方法
public interface UserDao {
    /**
     * 更新用户
     * @param user
     */
    void  update(User user);
}
  • 在 UserDao.xml 文件中加入新增配置
<update id="update" parameterType="com.itheima.bean.User">
    UPDATE t_user SET username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} WHERE uid=#{uid}
</update>
  • 添加测试类中的测试方法
@Test
public void testUpdate(){
    User user = userDao.findById(6);
    user.setUsername("aobama");
    user.setAddress("召唤师峡谷");

    userDao.updateUser(user);
}
3.3删除用户
  • UserDao中添加新增方法
public interface UserDao {

    /**
     * 删除用户
     * @param uid
     */
    void deleteById(int uid);
}
  • 在 UserDao.xml 文件中加入新增配置
<delete id="deleteById" parameterType="int">
    DELETE FROM t_user WHERE uid = #{uid}
</delete>
  • 添加测试类中的测试方法
@Test
public void testDeleteById(){
    //根据id删除用户
    userDao.deleteById(1);
}
3.4模糊查询
3.4.1 方式一(工作中不会采用这种做法)
  • UserDao 中添加新增方法
public interface UserDao {
    /**
     * 模糊查询
     * @param name
     * @return
     */
    List<User> searchByUsername(String name);
}
  • 在 UserDao.xml 文件中加入新增配置
<select id="searchByUsername" parameterType="string" resultType="User">
  	SELECT * FROM t_user WHERE username LIKE #{name}
</select>
  • 添加测试类中的测试方法
@Test
public void testSearch(){
    List<User> userList = userDao.searchByUsername("%a%");
    for (User user : userList) {
        System.out.println(user);
    }
}
3.4.2 方式二
  • UserDao 中添加新增方法
public interface UserDao {
    /**
     * 模糊查询
     * @param name
     * @return
     */
    List<User> searchByUsername(String name);
}
  • 在 UserMapper.xml 文件中加入新增配置
<select id="findByFirstName02" parameterType="string" resultType="User">
    	<!--select * from t_user where username like "%"#{username}"%"-->
        <!--select * from t_user where username like concat("%",#{username},"%")-->
        select * from t_user where username like "%${username}%"
</select>

我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。

  • 添加测试类中的测试方法
@Test
public void testSearch(){
    List<User> userList = userDao.searchByUsername("a");
    for (User user : userList) {
        System.out.println(user);
    }
}
3.4.3 #{}与${}的区别【面试】
  1. {}一定不能写在引号里面,${}一定要写在引号里面
  2. 如果是pojo、map类型的参数,无论是#{}还是${}里面都是些属性名
  3. 如果是简单类型的参数,#{}里面可以写任意字符串,但是${}里面只能写value
  4. 如果使用#{}引入参数的话,其实是先使用?占位符,然后再设置参数;而使用${}引入参数的话,是直接拼接SQL语句
3.5.SqlSessionFactory工具类的抽取

步骤:

  1. 创建SqlSessionFactoryUtils
  2. 定义一个getSqlSession()方法获得sqlSession
  3. 定义释放资源方法
  4. 保证SqlSessionFactory只有一个(静态代码块)

实现

package com.itheima.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;

/**
 * 包名:com.itheima.utils
 *
 * @author Leevi
 * 日期2020-07-29  11:39
 * mybatis的工具类
 */
public class SqlSessionFactoryUtils {
    private static InputStream is;
    private static SqlSessionFactory sessionFactory;

    static {
        try {
            //1. 创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //2. 读取核心配置文件,转换成字节输入流
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //3. 创建SqlSessionFactory对象
            sessionFactory = sqlSessionFactoryBuilder.build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取SqlSession对象的方法
     * @return
     */
    public static SqlSession openSession(){
        SqlSession sqlSession = null;
        try {
            //4. 创建SqlSession对象
            sqlSession = sessionFactory.openSession();
            is.close();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        return sqlSession;
    }

    /**
     * 提交事务并且关闭资源
     * @param sqlSession
     */
    public static void commitAndClose(SqlSession sqlSession){
        sqlSession.commit();
        sqlSession.close();
    }

    /**
     * 回滚事务并且关闭资源
     * @param sqlSession
     */
    public static void rollbackAndClose(SqlSession sqlSession){
        sqlSession.rollback();
        sqlSession.close();
    }
}

4.小结

4.1增删改查
  • 增加
<insert id="" parameterType="" resultType="" keyProperty="" useGeneratedKeys="true">
	sql语句
</insert>
  • 更新
<update id="" parameterType="" resultType="" >
	sql语句
</update>
  • 删除
<delete id="" parameterType="" resultType="" >
	sql语句
</delete>
  • 查询
<select id="" parameterType="" resultType="" >
	sql语句
</select>

知识点-parameterType深入

1.目标

  • 掌握Mybatis的参数深入(parameterType)

2.路径

  1. 传递简单类型
  2. 传递 pojo 对象
  3. 传递 pojo 包装对象类型

3.讲解

3.1传递简单类型

​ 基本的类型,字符串

​ 直接写#{任意字符串}或者'${value}'

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yCfkkbfe-1632266516446)(img/1535099951604.png)]

3.2传递 pojo 对象 或者 Map

​ Mybatis 使用 ognl 表达式解析对象字段的值, #{}或者’${}'括号中的值为 pojo 属性名称或者Map的key。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j1E92gvP-1632266516447)(img/1535100050378.png)]

3.3传递 pojo 包装对象类型

​ 开发中通过 pojo 传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。Pojo 类中包含 pojo。

​ 京东查询的例子:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yPNvNjKq-1632266516448)(img/1539830569011.png)]

​ 需求:根据用户id查询用户信息,查询条件放到 QueryVo 的 user 属性中。

  • QueryVo
@Data
public class QueryBean {

    private User user;
}
  • UserDao接口
public interface UserDao {
    /**
     * 复杂参数查询
     * @return
     */
    List<User> findByQueryBean(QueryBean queryBean);

}
  • UserDao.xml文件
<mapper namespace="com.itheima.dao.UserDao">
    <select id="findByQueryBean" resultType="com.itheima.pojo.User" parameterType="com.itheima.pojo.queryBean">
        SELECT * FROM t_user WHERE username > #{user.username}
    </select>
</mapper>
  • 测试代码
@Test
public void test04(){
    //使用POJO的包装类作为参数
    SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
    //获取LinkManDao的代理对象
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    User user = new user();
    linkMan.setUSername("李");
    List<User> userList = userDao.query(new QueryBean(user));

    for (User user : userList) {
        System.out.println(user);
    }

    //提交事务关闭资源
    SqlSessionFactoryUtils.commitAndClose(sqlSession);
}

4.小结

  1. 如果我们执行的SQL语句需要一个参数,那么我们可以使用简单类型的参数

  2. 如果我们执行的SQL语句需要多个参数

    1. 我们使用pojo对象类型
    2. 我们使用map类型
    3. 如果我们执行的SQL语句需要的数据很复杂,pojo里面的属性还是pojo类型,那么我们就使用pojo的包装类型

知识点 - resultType深入

1.目标

  • 掌握Mybatis的参数深入(resultType)

2.路径

  1. 输出简单类型
  2. 输出pojo对象
  3. 输出pojo列表
  4. resultMap结果类型

3.讲解

3.1输出简单类型

​ 直接写对应的Java类型. eg: 返回int

<select id="findCount" parameterType="int" resultType="int">
     SELECT  COUNT(*) FROM t_user
</select>
3.2输出pojo对象(一个pojo对象就对应一行数据)或者一个Map

​ 直接写当前pojo类的全限定名 eg: 返回User

<select id="findByUid" parameterType="int" resultType="com.itheima.bean.User">
        select * from t_user where uid = #{uid}
</select>
3.3输出pojo列表(一个pojo列表就对应多行数据)或者Map的列表

​ 直接写当前pojo类的全限定名 eg: 返回 List list;

<select id="findAll" resultType="com.itheima.bean.User">
        select * from t_user
</select>
3.4resultMap结果类型

resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。(下次课讲)

​ 那我们今天就来看返回的列名与实体类的属性不一致时的情况. 下次课再接着研究复杂的封装(多表查询)

​ 通过改别名的方式,现在返回结果集的列名已经与 User 类的属性名不相同了。

select uid uid_,username username_ ,birthday birthday_ ,sex sex_ ,address address_  from t_user where uid = #{id}
  • UserDao.java
public interface UserDao {
    /**
     * 根据uid查询
     * @param uid
     * @return
     */
    User findByUid(int uid);

}
  • UserDao.xml
    <select id="findByUid" parameterType="int" resultMap="findByUidMap">
        select uid uid_,username username_ ,birthday birthday_ ,sex sex_ ,address address_  from t_user where uid = #{id}
    </select>

    <resultMap id="findByUidMap" type="com.itheima.bean.User">
        <id property="uid" column="uid_"></id>
        <result property="username" column="username_"></result>
        <result property="birthday" column="birthday_"></result>
        <result property="sex" column="sex_"></result>
        <result property="address" column="address_"></result>
    </resultMap>
<!-- 
id:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个id。
type: 当前resultMap封装后返回的结果
property:表示 User 类的属性。
column:表示 sql 查询出来的字段名。(column 和 property 放在一块儿表示将 sql 查询出来的字段映射到指定的 pojo 类属性上。)
-->

4.小结

  1. 输出简单类型 直接写 java类型名 eg: int
  2. 输出pojo对象 直接写 pojo类型名 eg: User
  3. 输出pojo列表类型 写 列表里面的泛型的类型 eg: List 写User
  4. ResultMap
    • 解决查询出来的结果的列名和javaBean属性不一致的请求
    • 复杂的pojo复杂(明天讲)

第四章-日志【会用就可以】

知识点-日志的使用

1.目标

​ 我们在使用MyBatis的时候, 其实MyBatis框架会打印一些必要的日志信息, 在开发阶段这些日志信息对我们分析问题,理解代码的执行是特别有帮助的; 包括项目上线之后,我们也可以收集项目的错误日志到文件里面去; 所有我们采用专门的日志系统来处理.

2.步骤

  1. 导入坐标
  2. 拷贝日志配置文件到项目

3.讲解

  • 导入坐标
<!-- log start -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.6.6</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version>
</dependency>
  • 拷贝log4j.properties到resources目录
log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#[%-5p] %t %l %d %rms:%m%n
#%d{yyyy-MM-dd HH:mm:ss,SSS\} %-5p [%t] {%c}-%m%n
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %t %l %d %rms:%m%n
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:\\idea_project\\itheima_mm_backend.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS\} %-5p [%t] {%c}-%m%n

级别:error > warn > info>debug>trace

4.小结

  1. 日志系统就是一个工具

    • 拷贝坐标
    • 拷贝log4J.properties到项目
  2. 配置文件一般的配置

    • 开发阶段: log4j.rootLogger= debug,std,file
    • 上线之后: log4j.rootLogger= error ,file

第五章-Mybatis 连接池与事务(了解)

知识点-Mybatis 的连接池技术【了解】

1.目标

​ 我们在前面的 WEB 课程中也学习过类似的连接池技术,而在 Mybatis 中也有连接池技术,但是它采用的是自己的连接池技术 。

​ 在 Mybatis 的 SqlMapConfig.xml 配置文件中, 通过 <dataSource type=”pooled”>来实现 Mybatis 中连接池的配置.

2.路径

  1. Mybatis 连接池的分类
  2. Mybatis 中数据源的配置
  3. Mybatis 中 DataSource 配置分析

3.讲解

3.1Mybatis 连接池的分类
  • 可以看出 Mybatis 将它自己的数据源分为三类:

    • UNPOOLED 不使用连接池的数据源
    • POOLED 使用连接池的数据源
    • JNDI 使用 JNDI 实现的数据源,不要的服务器获得的DataSource是不一样的. 注意: 只有是web项目或者Maven的war工程, 才能使用. 我们用的是tomcat, 用的连接池是dbcp.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QSiP1phE-1632266516449)(img/tu_2-1572948297061.png)]

  • 在这三种数据源中,我们目前阶段一般采用的是 POOLED 数据源(很多时候我们所说的数据源就是为了更好的管理数据库连接,也就是我们所说的连接池技术),等后续学了Spring之后,会整合一些第三方连接池。

3.2Mybatis 中数据源的配置
  • 我们的数据源配置就是在 SqlMapConfig.xml 文件中, 具体配置如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E4UbI9zj-1632266516451)(img/tu_3-1572948297061.png)]

  • MyBatis 在初始化时,解析此文件,根据的 type 属性来创建相应类型的的数据源DataSource,即:

    ​ type=”POOLED”: MyBatis 会创建 PooledDataSource 实例, 使用连接池
    ​ type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例, 没有使用的,只有一个连接对象的
    ​ type=”JNDI”: MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用. 只有在web项目里面才有的,用的是服务器里面的. 默认会使用tomcat里面的dbcp

3.3Mybatis 中 DataSource 配置分析
  • 代码,在21行加一个断点, 当代码执行到21行时候,我们根据不同的配置(POOLED和UNPOOLED)来分析DataSource

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybgEU3gD-1632266516452)(img/1533783469075.png)]

  • 当配置文件配置的是type=”POOLED”, 可以看到数据源连接信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IDWsSqZv-1632266516453)(img/1533783591235.png)]

  • 当配置文件配置的是type=”UNPOOLED”, 没有使用连接池

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R6TvObZl-1632266516455)(img/1533783672422.png)]

4.小结

  1. 配置

    type=“POOLED” 使用连接池(MyBatis内置的)
    type=“UNPOOLED” 不使用连接池

  2. 后面做项目, 工作里面的连接池, 我们都是使用的第三方的(C3P0,Druid,光连接池), 都有让Spring管理.此章节只做了解

知识点-Mybatis 的事务控制 【了解】

1.目标

  • 了解MyBatis事务操作

2.路径

  1. JDBC 中事务的回顾
  2. Mybatis 中事务提交方式
  3. Mybatis 自动提交事务的设置

3.讲解

3.1JDBC 中事务的回顾

​ 在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。通过 JDK 文档,我们找到该方法如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k32N6ch7-1632266516456)(img/tu_8-1572948297061.png)]

​ 那么我们的 Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC的 setAutoCommit()方法来设置事务提交方式的。

3.2Mybatis 中事务提交方式
  • Mybatis 中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制。我们运行之前所写的代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8zcD8TsQ-1632266516457)(img/tu_9-1572948297061.png)]

  • userDao 所调用的 saveUser()方法如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BLnTD7Kq-1632266516458)(img/tu_10-1572948297061.png)]

  • 观察在它在控制台输出的结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NkYvnykP-1632266516458)(img/tu_11-1572948297061.png)]

    ​ 这是我们的 Connection 的整个变化过程, 通过分析我们能够发现之前的 CUD操作过程中,我们都要手动进行事务的提交,原因是 setAutoCommit()方法,在执行时它的值被设置为 false 了,所以我们在CUD 操作中,必须通过 sqlSession.commit()方法来执行提交操作。

3.3 Mybatis 自动提交事务的设置

​ 通过上面的研究和分析,现在我们一起思考,为什么 CUD 过程中必须使用 sqlSession.commit()提交事务?主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交。明白这一点后,我们现在一起尝试不进行手动提交,一样实现 CUD 操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B3re1KN5-1632266516459)(img/tu_12-1572948297062.png)]

​ 我们发现,此时事务就设置为自动提交了,同样可以实现 CUD 操作时记录的保存。虽然这也是一种方式,但就编程而言,设置为自动提交方式为 false 再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务情况来决定提交是否进行提交。

4.小结

  1. MyBatis的事务使用的是JDBC事务策略.
    • 通过设置autoCommit()去控制的
    • 默认情况下, MyBatis使用的时候 就把autoCommit(false)
      • 也就是意味着, 我们要进行增删改的时候, 需要手动的commit
  2. 后面做项目, 工作里面的事务管理, 基本上都是交给Spring管理. 所以此章节只做了解

第六章-Mybatis 映射文件的 SQL 深入【重点】

​ Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。

知识点-动态 SQL 之if标签

1.目标

​ 我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。

​ 比如在 id 如果不为空时可以根据 id查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到

2.讲解

  • LinkManDao.java
public interface UserDao {
   /**
     * 根据联系人的address查询联系人
     * @param address
     * @return
     */
    List<LinkMan> findByAddress(String address);
    
    /**
     * 测试if和where标签的使用
     * @param linkMan
     * @return
     */
    List<LinkMan> findByAddressAndSex(LinkMan linkMan);
}
  • LinkManDao.xml
<select id="findByAddress" resultType="LinkMan" parameterType="string">
    select * from linkman
    <!--
    加入判断,使用if标签判断
    -->
    <if test="address != null and address.length > 0">
    where address=#{address}
    </if>
</select>

<select id="findByAddressAndSex" resultType="LinkMan" parameterType="LinkMan">
    select * from linkman where 1=1
    <!--
                判断,如果address不为空,则添加address的条件
                如果sex不为空,则添加sex的条件
            -->
    <if test="address != null and address.length > 0">
        and address=#{address}
    </if>
    <if test="sex != null and sex.length > 0">
        and sex=#{sex}
    </if>
</select>
  • 测试
@Test
public void test08(){
    //目标:根据联系人的address查询联系人的信息,如果address为空,则查询出所有联系人
    //使用POJO的包装类作为参数
    SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
    //获取LinkManDao的代理对象
    LinkManDao linkManDao = sqlSession.getMapper(LinkManDao.class);

    List<LinkMan> linkManList = linkManDao.findByAddress("广西");
    if (linkManList != null) {
        for (LinkMan linkMan : linkManList) {
            System.out.println(linkMan);
        }
    }

    //提交事务关闭资源
    SqlSessionFactoryUtils.commitAndClose(sqlSession);
} 


@Test
public void test09(){
    //目标:根据联系人的address查询联系人的信息,如果address为空,则查询出所有联系人
    //使用POJO的包装类作为参数
    SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
    //获取LinkManDao的代理对象
    LinkManDao linkManDao = sqlSession.getMapper(LinkManDao.class);

    LinkMan man = new LinkMan();
    //man.setAddress("广东");
    //man.setSex("男");
    List<LinkMan> linkManList = linkManDao.findByAddressAndSex(man);
    if (linkManList != null) {
        for (LinkMan linkMan : linkManList) {
            System.out.println(linkMan);
        }
    }

    //提交事务关闭资源
    SqlSessionFactoryUtils.commitAndClose(sqlSession);
}

知识点-动态 SQL 之where标签

1.目标

​ 为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。

2.讲解

修改 UserDao.xml 映射文件如下:

注意: 可以自动处理第一个 and

<select id="findByAddressAndSex" resultType="LinkMan" parameterType="LinkMan">
    select * from linkman
    <!--
            where标签的作用是,如果有if条件成立,则会在SQL语句中添加WHERE关键字
            而且还会自动去掉第一个条件的and
        -->
    <where>
        <!--
                判断,如果address不为空,则添加address的条件
                如果sex不为空,则添加sex的条件
            -->
        <if test="address != null and address.length > 0">
            and address=#{address}
        </if>
        <if test="sex != null and sex.length > 0">
            and sex=#{sex}
        </if>
    </where>
</select>

3.小结

  1. where标签用在自己写sql语句的时候 where关键字不好处理的情况,代替where ‘1’ = ‘1’
  2. 可以自动处理第一个 and , 建议全部加上and

知识点-动态标签之foreach标签

1.目标

  • 掌握foreach标签的使用

2.讲解

2.1需求
  • 批量删除: 根据id的集合删除所有元素
2.2 LinkManDao代码
int deleteByIds(List<Integer> ids);
2.3 LinkManDao映射配置文件
<delete id="deleteByIds" parameterType="int">
    delete from linkman
    <!--
            使用foreach标签进行遍历
            collection属性就是要遍历的对象,如果要遍历的对象是一个集合,就写list
            item属性就是遍历出来的每一个元素
            index属性就是遍历出来的每一个元素的下标
            separator属性就是分隔符
            open属性 表示在遍历出来的第一个元素之前拼接字符串
            close属性 表示在遍历出来的最后一个元素之后拼接字符串
        -->
    <foreach open="where id in(" close=")" collection="list" item="id" index="i" separator=",">
        #{id}
    </foreach>
</delete>
2.4 测试代码
@Test
public void test10(){
    //使用POJO的包装类作为参数
    SqlSession sqlSession = SqlSessionFactoryUtils.openSession();
    //获取LinkManDao的代理对象
    LinkManDao linkManDao = sqlSession.getMapper(LinkManDao.class);
    List<Integer> ids = new ArrayList<>();

    ids.add(5);
    ids.add(45);
    ids.add(46);
    ids.add(49);

    linkManDao.deleteByIds(ids);

    //提交事务关闭资源
    SqlSessionFactoryUtils.commitAndClose(sqlSession);
}

知识点-动态标签之Sql片段

1.目标

​ Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。我们先到 UserDao.xml 文件中使用标签,定义出公共部分.

2.讲解

  • 使用sql标签抽取
<!--
        使用sql标签定义SQL片段:
        将当前映射配置文件中反复出现的SQL语句,定义成一个SQL片段,在需要使用的地方使用include标签引入即可
    -->
<sql id="selectAll">
    select id,name,sex,age,qq,email,address from linkman
</sql>
  • 使用include标签引入使用
<select id="findById" parameterType="int" resultType="LinkMan">
    <include refid="selectAll"></include>
    where id=#{id}
</select>

3.小结

  1. sql标签可以把公共的sql语句进行抽取, 再使用include标签引入. 好处:好维护, 提示效率

欢迎使用Markdown编辑器

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

居中的图片: Alt

居中并且带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目Value
电脑$1600
手机$12
导管$1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文本居中第二列文本居右第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.3.0 开始 我的操作 确认? 结束 yes no
  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的北极熊001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值