36-Mybatis

36-Mybatis-qianfeng-笔记


文章目录


一、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 mapper
        PUBLIC "-//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
在这里插入图片描述
在这里插入图片描述

③:测试代码

    @Test
    public 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的测试类中添加测试方法
在这里插入图片描述
在这里插入图片描述
    @Test
    public void deleteStudent() {
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            // SqLSessionFactoryBuilder
            SqlSessionFactoryBuilder 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.添加单元测试方法
在这里插入图片描述
    @Test
    public 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. 测试代码
在这里插入图片描述在这里插入图片描述
    @Test
    public 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. 单元测试代码
在这里插入图片描述
    @Test
    public 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();事务▣滚
    @Test
    public 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. 测试代码(举例)
    @Test
    public 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();
        }
    }
    @Test
    public 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">
        delete
        from db_student
        where stu_num = #{stuNum}
    </delete>

⑤:update标签

声明修改操作

    <update id="updateStudent">
        update db_student
        set 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 stuAge
            from 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_age
        from 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.不带条件分页

对学生信息进行分页查询

    @Test
    public 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. 测试代码
在这里插入图片描述
    @Test
    public 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_desc
        from users u
                 join details d on u.user_id = d.uid
        where 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.创建实体类

Students2Clazz2
在这里插入图片描述在这里插入图片描述

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性能最好
功能dbcpdruidc3p0tomcat-jdbcHikariCP
是否支持PSCache
监控jmxjmx/log/httpjmx,logjmxjmx
扩展性
sql拦截及解析支持
代码简单中等复杂简单简单
更新时间2015.8.62015.10.102015.12.092015.12.3
特点依赖于common-pool阿里开源,功能全面历史久远,代码逻辑复杂,且不易维护优化力度大,功能简单,起源于boneCP
连接池管理LinkedBlockingDeque数组FairBlockingQueuethreadlocal+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.测试代码(查询学生信息)
在这里插入图片描述在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

七@归七

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

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

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

打赏作者

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

抵扣说明:

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

余额充值