typora-copy-images-to: img
MyBatis_01
学习目标
- 能够了解什么是框架
- 掌握Mybatis框架开发快速入门
- 掌握Mybatis框架的基本CRUD操作
- 掌握SqlMapConfig.xml配置文件
- 掌握Mybatis的parameterType的配置
- 掌握Mybatis的resultType的配置
- 了解Mybatis连接池与事务操作
- 掌握Mybatis动态SQL
第一章-框架概述
知识点-框架概述
1.目标
- 能够了解什么是框架
2.路径
- 什么是框架
- 框架要解决的问题
3.讲解
3.1什么是框架
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。
简而言之,框架是软件(系统)的半成品,框架封装了很多的细节,使开发者可以使用简单的方式实现功能,大大提高开发效率。
开发好比表演节目, 开发者好比演员, 框架好比舞台.
3.2框架要解决的问题
框架要解决的最重要的一个问题是技术整合的问题,在 J2EE 的 框架中,有着各种各样的技术,不同的软件企业需要从J2EE 中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。
框架一般处在低层应用平台(如 J2EE)和高层业务逻辑之间的中间层。
4.小结
- 框架: 框架可以封装重复代码,提供更简洁的API;框架可以实现代码间的解耦
- SSM框架
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LW8iC4w-1632266516439)(img/image-20191226084539029.png)]
知识点-MyBatis框架概述
1.目标
- 能够了解什么是MyBatis
2.路径
- jdbc 程序回顾
- 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 问题分析
- 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
- Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大, sql 变动需要改变java 代码。
- 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
- 对结果集解析存在硬编码(查询列名), 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.小结
- MyBatis: 持久层的一个框架, 封装了JDBC. 操作数据库
- 为什么要学习MyBatis?
- JDBC和DBUtils都有一些很明显的缺点, JDBC和DBUtils不适合做项目
- MyBatis是工作里面的主流的持久层框架, 使用几率特别大
第二章-Mybatis入门
案例-Mybatis快速入门
1.需求
- 使用MyBatis查询所有的用户, 封装到List集合
2.分析
- 创建Maven工程(jar), 添加坐标
- 创建pojo
- 创建UserDao接口
- 创建UserDao映射文件
- 创建MyBatis核心配置文件SqlMapConfig.xml
- 编写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 映射文件
注意:
- 映射配置文件存储的路径在resources里面,要和对应的Dao接口的路径保持一致
- 映射配置文件的文件名必须和Dao接口名保持一致
- 一定要引入约束文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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 配置文件(核心配置文件)
注意事项
- 存放路径必须是resources的根路径
- 配置文件的名字,随便写
- 一定要引入约束文件
<?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.路径
- 入门案例回顾
- 规范
3.讲解
3.1入门案例回顾
3.1.2Mapper.xml(映射文件)
-
映射配置文件存储的路径在resources里面,要和对应的Dao接口的路径保持一致
-
映射配置文件的文件名必须和Dao接口名保持一致
-
一定要引入约束文件
-
namespace属性的值和对应Dao接口的全限定名一致
-
每一个子标签,就对应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接口开发需要遵循以下规范:
- 存储路径建议和对应的Dao接口保持一致
- 文件名建议和对应Dao接口的名字保持一致
- 配置文件的根标签的namespace属性必须和对应的Dao接口的全限定名保持一致
- 接口中的每一个方法,就对应映射配置文件中的一个标签:
- 查询方法,对应select标签
- 添加方法,对应insert标签
- 删除方法,对应delete标签
- 修改方法,对应update标签
- 映射配置文件中的标签的id属性,就必须和对应的方法的方法名保持一致
- 映射配置文件中的标签的parameterType属性,必须和对应的方法的参数类型(全限定名)保持一致
- 映射配置文件中的标签的resultType属性,必须和对应的方法的返回值类型(全限定名)保持一致,但是如果返回值是List则和其泛型保持一致
4.小结
- 我们使用MyBatis 遵循这些规范
知识点-核心配置文件详解
1.目标
- 掌握SqlMapConfig.xml配置文件
2.路径
- 核心配置文件的顺序
- properties
- typeAliases
- 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.小结
- 核心配置文件的顺序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJ1GH7Ru-1632266516445)(img/image-20191226101317581.png)]
- properties 引入properties文件的
- 创建properties文件
- 使用
<properties resource="文件的路径"/>
- 使用 ${key}
- typeAliases(类型别名) 在Dao映射文件里面 直接写类(pojo)的名字, 不需要写类全限定名了
<typeAliases>
<package name="com.itheima.bean"/>
</typeAliases>
- Mapper 引入Dao映射文件的
<mappers>
<package name="com.itheima.dao"></package>
</mappers>
第三章-MyBatis进阶
案例-使用Mybatis完成CRUD
1.需求
- 使用Mybatis完成CRUD
2.分析
- 在Dao接口定义方法
- 在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获取主键
属性 | 描述 |
---|---|
keyProperty | selectKey 语句结果应该被设置的目标属性。 |
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 #{}与${}的区别【面试】
- {}一定不能写在引号里面,${}一定要写在引号里面
- 如果是pojo、map类型的参数,无论是#{}还是${}里面都是些属性名
- 如果是简单类型的参数,#{}里面可以写任意字符串,但是${}里面只能写value
- 如果使用#{}引入参数的话,其实是先使用?占位符,然后再设置参数;而使用${}引入参数的话,是直接拼接SQL语句
3.5.SqlSessionFactory工具类的抽取
步骤:
- 创建SqlSessionFactoryUtils
- 定义一个getSqlSession()方法获得sqlSession
- 定义释放资源方法
- 保证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.路径
- 传递简单类型
- 传递 pojo 对象
- 传递 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.小结
-
如果我们执行的SQL语句需要一个参数,那么我们可以使用简单类型的参数
-
如果我们执行的SQL语句需要多个参数
- 我们使用pojo对象类型
- 我们使用map类型
- 如果我们执行的SQL语句需要的数据很复杂,pojo里面的属性还是pojo类型,那么我们就使用pojo的包装类型
知识点 - resultType深入
1.目标
- 掌握Mybatis的参数深入(resultType)
2.路径
- 输出简单类型
- 输出pojo对象
- 输出pojo列表
- 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.小结
- 输出简单类型 直接写
java类型名
eg: int - 输出pojo对象 直接写
pojo类型名
eg: User - 输出pojo列表类型 写
列表里面的泛型的类型
eg: List 写User - ResultMap
- 解决查询出来的结果的列名和javaBean属性不一致的请求
- 复杂的pojo复杂(明天讲)
第四章-日志【会用就可以】
知识点-日志的使用
1.目标
我们在使用MyBatis的时候, 其实MyBatis框架会打印一些必要的日志信息, 在开发阶段这些日志信息对我们分析问题,理解代码的执行是特别有帮助的; 包括项目上线之后,我们也可以收集项目的错误日志到文件里面去; 所有我们采用专门的日志系统来处理.
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.小结
-
日志系统就是一个工具
- 拷贝坐标
- 拷贝log4J.properties到项目
-
配置文件一般的配置
- 开发阶段: log4j.rootLogger= debug,std,file
- 上线之后: log4j.rootLogger= error ,file
第五章-Mybatis 连接池与事务(了解)
知识点-Mybatis 的连接池技术【了解】
1.目标
我们在前面的 WEB 课程中也学习过类似的连接池技术,而在 Mybatis 中也有连接池技术,但是它采用的是自己的连接池技术 。
在 Mybatis 的 SqlMapConfig.xml 配置文件中, 通过 <dataSource type=”pooled”>
来实现 Mybatis 中连接池的配置.
2.路径
- Mybatis 连接池的分类
- Mybatis 中数据源的配置
- 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.小结
-
配置
type=“POOLED” 使用连接池(MyBatis内置的)
type=“UNPOOLED” 不使用连接池 -
后面做项目, 工作里面的连接池, 我们都是使用的第三方的(C3P0,Druid,光连接池), 都有让Spring管理.此章节只做了解
知识点-Mybatis 的事务控制 【了解】
1.目标
- 了解MyBatis事务操作
2.路径
- JDBC 中事务的回顾
- Mybatis 中事务提交方式
- 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.小结
- MyBatis的事务使用的是JDBC事务策略.
- 通过设置autoCommit()去控制的
- 默认情况下, MyBatis使用的时候 就把autoCommit(false)
- 也就是意味着, 我们要进行增删改的时候, 需要手动的commit
- 后面做项目, 工作里面的事务管理, 基本上都是交给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.小结
- where标签用在自己写sql语句的时候 where关键字不好处理的情况,代替where ‘1’ = ‘1’
- 可以自动处理第一个 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.小结
- sql标签可以把公共的sql语句进行抽取, 再使用include标签引入. 好处:好维护, 提示效率
欢迎使用Markdown编辑器
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法1 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
功能快捷键
撤销: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.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
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)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎