Day64 Mybatis的多表查询、ResultMap、注解以及缓存

mybatis的多表查询

AutoMapping自动注入(默认):
概念:如果数据库表的字段和实体类的属性名一致,则字段的值自动赋值给实体类的属性。
    数据库表设计:
        学生表:
            学号
            姓名
            年龄
            教师编号
        教师表:
            教师编号
            姓名
    业务装配方式:根据业务分开查询其需要的数据,并将查询的数据存储到实体类中
        一对一查询:
            示例  查询学生及其教师信息  
                先查询所有的学生信息
                根据学生信息中的老师编号查询其对应的教师信息,并存储到该学生实体类的教师属性中
            注意:
                学生实体类的设计中应该包含教师属性
        一对多查询:
            示例  查询教师及其学生信息
                先查询教师信息
                根据教师编号查询其学生信息,并将学生信息存储到教师实体类的学生集合属性中
            注意:
                教师实体类的设计中应该包含集合类型的学生属性
        特点:
            效率低下。
            SQL语句执行了n+1条
ResultMap n+1方式:
resultMap属性:
            如果实体类的属性名和表的字段不一致,这也就需要
            指明的将某个字段的值赋值给实体类的指定的属性。
            在mapper.xml中使用ResultMap属性进行指明赋值即可。
            示例:
            <resultMap type="student2" id="stu">
                <id column="sid" property="sid2"/>
                <!-- <result column="sname" property="sname"/> -->
                <result column="sage" property="sage2"/>
                <result column="tid" property="tid2"/>
            </resultMap>
            <select id="selStuResultMap" resultMap="stu">
                select * from student
            </select>
            注意:ResultType和ResultMap选择其中一个使用。
        一对一查询:
            示例:查询学生及其教师信息
                在mapper.xml文件中声明标签语句完成查询
                select标签中声明sql语句查询所有的学生信息
                使用标签属性ResultMap指明Student实体类属性的teacher属性的值执行一次查询
                代码:
                <resultMap type="student" id="rm">
                <!-- <id column="sid" property="sid"/>
                <result column="sname" property="sname"/>
                <result column="sage" property="sage"/> -->
                <result column="tid" property="tid"/>
                <association property="teacher" column="tid" select="com.bjsxt.mapper.TeacherMapper.selTeaById"></association>
            </resultMap>
            <select id="selStuRm" resultMap="rm">
                select * from student
            </select>
        一对多查询:
            示例 查询教师及其学生信息
            在mapper.xml中声明标签语句完成教师查询
            然后使用ReultMap属性进行自定义赋值,同时指明学生集合属性的查询。
            代码:
            <resultMap type="teacher" id="rm">
            <id column="tid" property="tid"/>
            <result column="tnname" property="tname"/>
            <collection property="ls" column="tid" select="com.bjsxt.mapper.StudentMapper.selStuByTid"></collection>
        </resultMap>
        <select id="selTeaRm" resultMap="rm">
            select * from teacher
        </select>
    总结特点:
        效率低下的。SQL语句执行了n+1条。
        如果实体类的属性是一个对象则在ResultMap中使用association 标签即可
        如果实体类的属性是一个集合对象,则使用collection 标签即可
ResultMap 联合查询方式:
一对一查询:
            示例  查询学生及其教师信息
            <resultMap type="student" id="rms">
            <id column="sid" property="sid"/>
            <result column="sname" property="sname"/>
            <result column="sage" property="sage"/>
            <result column="tid" property="tid"/>
            <association property="teacher" javaType="teacher">
                <result column="tid" property="tid"/>
                <result column="tname" property="tname"/>
            </association>
            </resultMap>
        <select id="selStuUn" resultMap="rms">
            select * from student s
            left join teacher t
            on s.tid=t.tid
        </select>
        一对多查询:  
            示例:查询教师及其学生信息
        <resultMap type="teacher" id="rt">
            <id column="tid" property="tid"/>
            <result column="tname" property="tname"/>
            <collection property="ls" ofType="student">
                <id column="sid" property="sid"/>
                <result column="sname" property="sname"/>
                <result column="sage" property="sage"/>
                <result column="tid" property="tid"/>
            </collection>
        </resultMap>
        <select id="selTeaUn" resultMap="rt">
            select * from teacher t
            left join student s
            on t.tid=s.tid
        </select>
Automapping多表注入
    <!-- 一对一 查询学生及其教师信息 autoMapping注入  -->
        <select id="selStuUn2" resultType="Student">
            select s.*,t.tid `teacher.tid`,t.tname `teacher.tname` from student s
            left join teacher t
            on s.tid=t.tid
        </select>

mybatis的注解

注解学习:
    注解的作用(了解):
        替代XML文件配置的。
    特点:
        注解可以节省我们的工作量,但是耦合性比较高。
    注意:
        mybatis的注解和mapper.xml配置文集可以同时使用
    示例:
    //查询所有的学生信息
    @Select("select * from student")
    List<Student> selStu();

    //根据ID查询学生信息
    @Select("select * from student where sid=#{0}")
    Student selStuById(int sid);

    //插入一条学生信息
    @Insert("insert into student values(default,#{0},#{1},#{2})")
    int insStu(String sname,int sage,int tid);

    //删除一条学生信息
    @Delete("delete from student where sid=#{0}")
    int delStu(int sid);

缓存

一级缓存:(SqlSession)
    当SqlSession对象完成数据库操作后,会将此次操作的数据库命令对象(preparedStatement)放入缓存中,
    以后执行相同的mapper.xml中配置的标签时,直接从缓存获取即可。 
二级缓存:(Factory缓存)
    第一步:
        在mapper.xml文件中使用标签开启:
            <cache readOnly="true"></cache>
    第二步:
        SqlSession对象在Close的时候会将其缓存的数据刷新到Factory缓存中

其他知识点:

其他知识点:

数据库设计:
  表关系设计:

 一对多   :主外键关联     有外键的是子表
多对多    :通过中间表

查询结果集的处理:  
相当于原生JDBC的while()循环对结果集的赋值。
实体类设计: 把一个实体类根据业务需求作为另一个实体类的属性。

 业务装配模式:  效率低下 ,SQL语句简单,分开查询
            使用JAVA代码进行逻辑判断,在一条SQL语句查询时候调用另一条查询语句。
 ResultMap n+1方式: 效率低下,但完全解耦,有关联的列必须写,没关联的列可以省略。SQL语句简单,分开查询
    在XML文件中用标签进行逻辑判断赋值

 ResultMap  多表联合查询: SQL语句复杂。但效率高。
           使用SQL多表联合查询语句替代逻辑判断。
    在ResultMap 里进行一对一,和一对多的标签操作进行对字段进行赋值。
ResultType 和ResultMap不能同时使用
 ResultMap   相关字段解释:
https://blog.csdn.net/wxwzy738/article/details/24742495
    Type:该条数据返回值类型   
        id:和select 的ResultMap的值同名。
    Id标签  :一般为表的主键 
         column:数据库字段名
         property:实体类属性
   Result标签:一般为表字段赋值
    column:数据库字段名
         property:实体类属性
   Association标签: 适用于一对一,也就是连接的表查询条件是一个对象的数据,比如一个学生对应一个教师,如果是多表查询,可以在该标签里面用ID和Result标签给连接表赋值
       column:数据库字段名   (单表查询)
         property:实体类属性
        select:需要调用查询语句的全限定路径,包名到查询语句名   (单表查询使用这个继续查另一个表)  
       JavaType:完整java类名或别名  (联合查询)
   Collection标签:适用于一对多,也就是连接的表是一个集合。比如一个教师对应多个学生
可以在该标签里面用ID和Result标签给连接表赋值

     column:数据库字段名   (单表查询)
         property:实体类属性
        select:需要调用查询语句的全限定路径,包名到查询语句名   (单表查询使用这个继续查另一个表)  
       OfType: 连接表的完整java类名或别名  (联合查询)

JavaType和OfType的区别:
JavaType和ofType都是用来指定对象类型的,但是JavaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型。都是指定对象的类型 不同的是当使用反向查询select从另一个maper文件中取出数据时必须用ofType


 使用注解进行单表查询比使用XML方式简单。但是对于多表查询不建议用注解方式进行查询,注解大大阻碍了解耦。

缓存:







细节:

注意mybatis里要扫描mapper包
select 要写 resultType 代表的是每条语句的返回值类型   
 对应的接口里的方法里的写的是整个结果集用什么去存,接口方法要与xml里的查询方法ID同名。

小案例:

需求:
这里写图片描述

数据库设计:
学生表:
CREATE TABLE student (
sid int(10) NOT NULL AUTO_INCREMENT,
sname varchar(100) NOT NULL,
sage int(3) NOT NULL,
tid int(10) NOT NULL,
PRIMARY KEY (sid)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
教师表:
CREATE TABLE teacher (
tid int(10) NOT NULL,
tname varchar(100) NOT NULL,
PRIMARY KEY (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

导入Mybatis相关jar包 Gson jar包 js1.9 log4j jar包
配置XML文件

搭建环境,建包,写代码

src:
mybatis.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>
    <typeAliases>
        <package name="com.bjsxt.pojo"/>
    </typeAliases>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>
      <mappers>
        <package name="com.bjsxt.mapper"/>
      </mappers>
  </configuration>

log4j.properties:


log4j.rootCategory=info



log4j.logger.com.bjsxt.mapper=debug, CONSOLE
log4j.logger.com.bjsxt.serviceImpl=debug, CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=- %c-%d-%m%n


log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=- %c-%d-%m%n

com.bjsxt.mapper:
ShowMapper.xml:

<?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.bjsxt.mapper.ShowMapper">
    <!--
        分页查询学生及其教师信息
      -->
      <resultMap type="student" id="rs">
        <id column="sid" property="sid"/>
        <result column="sname" property="sname"/>
        <result column="sage" property="sage"/>
        <result column="tid" property="tid"/>
        <association property="teacher" javaType="teacher">
            <result column="tid" property="tid"/>
            <result column="tname" property="tname"/>
        </association>
      </resultMap>
      <select id="selStu" resultMap="rs">
        select * from student s
        left join teacher t
        on s.tid=t.tid
        <where>
            <if test="param1 !='' and param1 !=null">
                <bind name="sa" value="'%'+param1+'%'"/>
                and sname like #{sa}
            </if>
            <if test="param2 !='' and param2 !=null">
                <bind name="ta" value="'%'+param2+'%'"/>
                and tname like #{ta}
            </if>
        </where>
         limit #{param3},#{param4}
      </select>

 </mapper>

ShowMapper.java:

package com.bjsxt.mapper;

import java.util.List;

import com.bjsxt.pojo.Student;

public interface ShowMapper {
    /**
     * 分页查询学生及其教师信息
     * @param tname 
     * @param sname 
     * @param pageStart
     * @param pageSize
     * @return
     */
    List<Student> selStu(String sname, String tname, int pageStart,int pageSize);


}

com.bjsxt.pojo:
Student.java:

package com.bjsxt.pojo;

public class Student {
    private int sid;
    private String sname;
    private int sage;
    private int tid;
    private Teacher teacher;
    public int getSid() {
        return sid;
    }
    public void setSid(int sid) {
        this.sid = sid;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public int getSage() {
        return sage;
    }
    public void setSage(int sage) {
        this.sage = sage;
    }
    public int getTid() {
        return tid;
    }
    public void setTid(int tid) {
        this.tid = tid;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
    @Override
    public String toString() {
        return "Student [sid=" + sid + ", sname=" + sname + ", sage=" + sage + ", tid=" + tid + ", teacher=" + teacher
                + "]";
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Student(int sid, String sname, int sage, int tid, Teacher teacher) {
        super();
        this.sid = sid;
        this.sname = sname;
        this.sage = sage;
        this.tid = tid;
        this.teacher = teacher;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + sage;
        result = prime * result + sid;
        result = prime * result + ((sname == null) ? 0 : sname.hashCode());
        result = prime * result + ((teacher == null) ? 0 : teacher.hashCode());
        result = prime * result + tid;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (sage != other.sage)
            return false;
        if (sid != other.sid)
            return false;
        if (sname == null) {
            if (other.sname != null)
                return false;
        } else if (!sname.equals(other.sname))
            return false;
        if (teacher == null) {
            if (other.teacher != null)
                return false;
        } else if (!teacher.equals(other.teacher))
            return false;
        if (tid != other.tid)
            return false;
        return true;
    }



}

Teacher.java:

package com.bjsxt.pojo;

public class Teacher {
    private int tid;
    private String tname;
    public int getTid() {
        return tid;
    }
    public void setTid(int tid) {
        this.tid = tid;
    }
    public String getTname() {
        return tname;
    }
    public void setTname(String tname) {
        this.tname = tname;
    }
    @Override
    public String toString() {
        return "Teacher [tid=" + tid + ", tname=" + tname + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + tid;
        result = prime * result + ((tname == null) ? 0 : tname.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Teacher other = (Teacher) obj;
        if (tid != other.tid)
            return false;
        if (tname == null) {
            if (other.tname != null)
                return false;
        } else if (!tname.equals(other.tname))
            return false;
        return true;
    }
    public Teacher() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Teacher(int tid, String tname) {
        super();
        this.tid = tid;
        this.tname = tname;
    }




}

PageInfo.java:

package com.bjsxt.pojo;

import java.util.List;

public class PageInfo {
    private int pageNum;
    private int pageSize;
    private List<Student> ls;
    public int getPageNum() {
        return pageNum;
    }
    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }
    public int getPageSize() {
        return pageSize;
    }
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
    public List<Student> getLs() {
        return ls;
    }
    public void setLs(List<Student> ls) {
        this.ls = ls;
    }
    @Override
    public String toString() {
        return "PageInfo [pageNum=" + pageNum + ", pageSize=" + pageSize + ", ls=" + ls + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((ls == null) ? 0 : ls.hashCode());
        result = prime * result + pageNum;
        result = prime * result + pageSize;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PageInfo other = (PageInfo) obj;
        if (ls == null) {
            if (other.ls != null)
                return false;
        } else if (!ls.equals(other.ls))
            return false;
        if (pageNum != other.pageNum)
            return false;
        if (pageSize != other.pageSize)
            return false;
        return true;
    }
    public PageInfo() {
        super();
        // TODO Auto-generated constructor stub
    }
    public PageInfo(int pageNum, int pageSize, List<Student> ls) {
        super();
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.ls = ls;
    }




}

com.bjsxt.service:
ShowService.java:

package com.bjsxt.service;

import java.io.IOException;

import com.bjsxt.pojo.PageInfo;

public interface ShowService {

    /**
     * 根据pageNum和pageSize获取学生分页数据
     * @param pageNum
     * @param pageSize
     * @param tname 
     * @param sname 
     * @return
     */
    PageInfo getStuInfoService(int pageNum,int pageSize, String sname, String tname)throws IOException ;

}   

com.bjsxt.serviceImpl:
ShowServiceImpl.java:

package com.bjsxt.serviceImpl;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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 com.bjsxt.mapper.ShowMapper;
import com.bjsxt.pojo.PageInfo;
import com.bjsxt.pojo.Student;
import com.bjsxt.service.ShowService;

public class ShowServiceImpl implements ShowService{

    @Override
    public PageInfo getStuInfoService(int pageNum,int pageSize, String sname, String tname) throws IOException {
        //获取SqlSession对象
                InputStream is = Resources.getResourceAsStream("mybatis.xml");
                SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
                SqlSession ss=factory.openSession();
        //获取mapper接口对象
                ShowMapper sm=ss.getMapper(ShowMapper.class);
        //换算分页查询起始点
                int pageStart=pageNum*pageSize-pageSize;
        //查询数据
                List<Student> ls=sm.selStu(sname,tname,pageStart, pageSize);
        //将数据存储到pageInfo对象中
                PageInfo p=new PageInfo();
                p.setPageNum(pageNum);
                p.setPageSize(pageSize);
                p.setLs(ls);
        return p;
    }

}

com.bjsxt.servlet:
ShowServlet.java:

package com.bjsxt.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.bjsxt.pojo.PageInfo;
import com.bjsxt.service.ShowService;
import com.bjsxt.serviceImpl.ShowServiceImpl;
import com.google.gson.Gson;

/**
 * Servlet implementation class ShowServlet
 */
@WebServlet("/show")
public class ShowServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求编码格式
        req.setCharacterEncoding("utf-8");
        //设置响应编码格式
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //获取请求信息
        int pageNum=Integer.parseInt(req.getParameter("pageNum"));
        int pageSize=Integer.parseInt(req.getParameter("pageSize"));
        String sname=req.getParameter("sname");
        String tname=req.getParameter("tname");
        //处理请求信息
            //创建业务层对象
            ShowService ss=new ShowServiceImpl();
            PageInfo p=ss.getStuInfoService(pageNum, pageSize,sname,tname);
        //响应处理结果
            resp.getWriter().write(new Gson().toJson(p));
    }
}

WebContext:
show.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<!--引入jQuery文件  -->
<script type="text/javascript" src="js/j.js"></script>
<!--声明js代码域  -->
<script type="text/javascript">
    $(function(){
        //声明变量记录当前页码数
        var pn;
        //页面加载调用getData获取第一个数据
        getData(1,2);
        //给查询按钮添加事件
        $("#btn").click(function(){
            $("input[type=radio]").each(function(){
                if(this.value==2){
                    this.checked=true
                }else{
                    this.checked=false;
                }
            })
            getData(1,2);

        })
        //给上一页添加事件
        $("#up").click(function(){
            getData(pn-1,2);
        })
        //给下一页添加事件
        $("#down").click(function(){
            getData(pn+1,2);
        })
        //给radio单选按钮添加事件
        $("input[type=radio]").click(function(){
            getData(1,$(this).val());
        })
        //封装ajax请求
        function getData(pageNum,pageSize){
            //发送ajax请求 请求第一页的数据
            $.get("show",{pageNum:pageNum,pageSize:pageSize,sname:$("#sname").val(),tname:$("#tname").val()},function(data){
                //使用eval方法将数据转换为js对象
                eval("var p="+data);
                pn=p.pageNum;
                //获取表格对象
                var ta=$("#ta");
                ta.empty();
                ta.append("<tr height='35px'>"+
                        "<td width='100px'>编号</td>"+
                        "<td width='100px'>学生姓名</td>"+
                        "<td width='100px'>年龄</td>"+
                        "<td width='100px'>教师姓名</td>"+
                    "</tr>");
                //遍历,将数据填充到表格中
                for(var i=0;i<p.ls.length;i++){
                    ta.append("<tr height='35px'>"+
                            "<td width='100px'>"+p.ls[i].sid+"</td>"+
                            "<td width='100px'>"+p.ls[i].sname+"</td>"+
                            "<td width='100px'>"+p.ls[i].sage+"</td>"+
                            "<td width='100px'>"+p.ls[i].teacher.tname+"</td>"+
                        "</tr>");
                }
            })
        }
    })

</script>
</head>
<body>
    <input type="radio" id="" name="page" value="2" checked="checked"/>2&nbsp;&nbsp;&nbsp;
    <input type="radio" id="" name="page" value="3"/>3&nbsp;&nbsp;&nbsp;
    <input type="radio" id="" name="page" value="4"/>4&nbsp;&nbsp;&nbsp;
    <br />
    学生姓名:<input type="text" id="sname"/>&nbsp;&nbsp;&nbsp;
    教师姓名: <input type="text" id="tname"/>&nbsp;&nbsp;&nbsp;
        <input type="button" id="btn"  value="查询"/>&nbsp;&nbsp;&nbsp;
    <hr />
    <table border="1px" cellpadding="0" cellspacing="0" id="ta"></table>
    <a href="javascript:void(0)" id="up">上一页</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <a href="javascript:void(0)" id="down">下一页</a>
</body>
</html>

源码:

链接:https://pan.baidu.com/s/1zPvko3yKRELiQIMREhXekg 密码:9om2

小结:

Mybatis的多表查询
注解
缓存
其他知识点
小案例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值