数据库的事务_JDBC_HTML

1. 数据库的事务

什么是事务
在实际业务操作过程中,可能同时需要执行多张表的sql语句或者一张表的多个sql(update,delete,insert into)使用事务将多个sql语句进行管理,如果整个sql执行没问题,提交事务(表示整个完成);如果有问题,回滚事务(撤销这个sql语句的所有操作,回滚到原来起始点,操作sql之前的操作)

1.1 事务特点 ACID

  1. 原子性(Atomicity) : 操作多个sql,要么同时执行成功或者要么同时执行失败
  2. 一致性(Consistency) : 频繁进行写入操作时,保证数据内容一致(针对具体的业务操作)
  3. 隔离性(Isolation) : 事务和事务之间是独立的,互不影响的
  4. 持久性(Durability) : 事务在提交commit之后, 对数据的添加,修改,删除是永久性的

1.2 数据库的隔离级别

read uncommitted 读未提交,会造成"脏读"
read committed 读已提交,能有效防止"脏读",但会出现"不可重复读"
repeatable read 可重复读,mysql默认级别,有效防止"脏读"和"不可重复读",但是可能会出现"幻读"的问题
serializable 串行化

-- 三个指令 : 
start transaction -- 开启事务 , 如果没有开启事务,针对sql语句都是默认提交
执行sql语句
-- 如果没有问题
commit  -- 提交事务
-- 如果有问题
rollback  -- 回滚事务
-- mysql5.7查询事务的隔离级别的指令
SELECT @@tx_isolation ;
-- 修改隔离级别
set global transaction isolation level 级别的名称;
-- mysql8.0以上查询事务的隔离级别指令
select tranaction_isolation

2. JDBC

Java Database Connectivity : Java数据库连接
使用Java语言编写的应用程序直接操作数据库,对数据库表进行添加,删除,修改,查询
sun提供的接口, 数据库厂商提供数据库驱动jar包(sun提供的接口的实现类)

2.1 JDBC原生操作

/**
 *  jdbc原生操作步骤:
 *  1)导入MySQL的驱动jar包
 *  2)注册驱动
 *  3)创建数据库的连接对象Connection
 *  4)通过连接对象来获取执行对象Statement
 *  5)准备好sql语句
 *  6)执行sql语句
 *  7)释放资源
 */
public class JDBCDemo {
    @SuppressWarnings("all")
    public static void main(String[] args) throws Exception {
        //1)导入驱动MySQL的jar包
        //2)注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //3)创建数据库的连接对象
        Connection root = DriverManager.getConnection("jdbc:mysql://localhost:3306/库名", "用户名", "密码");
        //4)通过连接对象获取执行对象
        Statement statement = root.createStatement();
        //5)准备好sql语句
        String sql = "insert into student (name, gender) values('张三','男')";
        //6)执行sql语句
        int count = statement.executeUpdate(sql);
        System.out.println("共影响了" + count + "行");
        //7)释放资源
        statement.close();
        root.close();
    }
}

2.2 自定义工具类

public class JDBCUtils {

    //private static String driverClass = null;
    private static String url = null;
    private static String user = null;
    private static String password = null;

    //构造方法私有化
    private JDBCUtils() {
    }

    static {
        try {
            //读取src下的jdbc.properties配置文件
            InputStream resourceAsStream = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //创建属性集合列表
            Properties prop = new Properties();
            prop.load(resourceAsStream);
            //获取value,并给成员变量赋值
            //driverClass = prop.getProperty("driverClass");
            url = prop.getProperty("url");
            user = prop.getProperty("user");
            password = prop.getProperty("password");
            //注册驱动
            //Class.forName(driverClass);
            Class.forName(prop.getProperty("driverClass"));
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //对外提供静态方法,获取连接对象
    public static Connection getConnection() {
        try {
            //获取连接对象并返回
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    //释放资源
    public static void close(ResultSet resultSet, Statement statement, Connection connection){
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void close(Statement statement, Connection connection) {
        close(null, statement, connection);
    }
}

/*
jdbc.properties
	driverClass=com.mysql.jdbc.Driver
	url=jdbc:mysql://localhost:3306/库名
	user=用户名
	password=密码
*/

2.3 Statement来模拟用户登录操作,有什么弊端

Statement 本身执行的静态sql语句—>存在SQL拼接,造成sql注入!

当前表中只有两位用户
在这里插入图片描述
使用statement来模拟用户登录,sql语句中存在拼接,输入错误的用户名及密码,依然显示登录成功,所以使用statement来执行sql语句,是不安全的

2.4 PrepareStatement

以后不会用Statement,以后都是PreparedStatement预编译对象

/**
     * 根据id值查询员工,将员工数据封装在员工类中
     */
    @Override
    public Employee selectEmpById(int id) throws SQLException {
        //声明Employee对象
        Employee employee = null;
        //注册驱动,获取数据库连接对象
        Connection connection = JDBCUtils.getConnection();
        //sql语句
        String sql = "select * from employee where id = ? ;" ;
        //通过连接对象获取执行对象Statement
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,id);
        //执行sql语句
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            employee = new Employee();
            employee.setId(resultSet.getInt("id"));
            employee.setName(resultSet.getString("name"));
            employee.setAge(resultSet.getInt("age"));
            employee.setGender(resultSet.getString("gender"));
            employee.setAddress(resultSet.getString("address"));
            employee.setBirthday(resultSet.getDate("birthday"));
        }
        //释放资源
        JDBCUtils.close(resultSet, preparedStatement, connection);
        return employee;
    }

2.5 Statement 和PreparedStatement的区别

共同点: 
    能够将sql语句发送给数据库进行操作,都称为执行对象
    后者继承前者
不同点:
    1)是否能够造成SQL注入
    Statement操作的是静态sql语句,存在sql语句的字符串拼接,会存在安全漏洞,造成SQL注入
    PreparedStatement预编译对象,发送的sql数据,是一种参数化sql,不存在sql拼接,相对于Statement更安全,不会造成SQL注入
    2)执行sql语句效率的区别
    Statement执行sql语句的效率比较低
    PreparedStatement执行sql语句的效率相对来说比较高

Statement是执行静态sql语句,存在sql语句拼接,容易出现sql注入的问题
PreparedStatement可以对sql语句进行预编译,我们只需要填入相关参数,
	有效防止了sql注入的问题

2.6 JDBC控制事务

/*
 *void setAutoCommit(boolean autoCommit) throws SQLException
 *      是否开启手动提交,参数true,就是自动提交,false,禁用自动提交,手动提交----->相当于mysql的指令 start transaction;
 *void rollback() throws SQLException撤销在当前事务中所做的所有更改----->事务回滚方法---->相当于msyql指令 rollback;
 * void commit()throws SQLException使上次提交/回滚之后所做的所有更改都将永久性  (提交事务)---->mysql的指令 commit;
 *
 *  Jdbc控制事务:当某个业务执行过程中需要同时指定多个sql(添加/删除/修改)需要将这个多个sql看成一个整体,他们要么
 *  同时执行成功,要么同时执行失败!
 *
 *  需求:
 *          account表:针对多个账户更新操作,"转账的操作"
 */
public class JdbcDemo {
    public static void main(String[] args) {
        //现在使用JDBC控制事务
        Connection conn = null ;
        PreparedStatement ps = null ;
        PreparedStatement ps2 = null ;
        try {
            //获取数据库连接对象
            conn = JdbcUtils.getConnection();
            //开启事务
            //void setAutoCommit(boolean autoCommit) throws SQLException
            conn.setAutoCommit(false) ;//禁用自动提交
            //sql语句
            String sql1 = "update account set balance = balance -? where id= ? " ;
            String sql2 = "update account set balance = balance +? where id = ?" ;

            //获取预编译对象
            ps = conn.prepareStatement(sql1);
            //赋值
            ps.setInt(1,500);
            ps.setInt(2,3);

            //将sql2进行发送数据库,获取预编译对象
            ps2 = conn.prepareStatement(sql2);
            //赋值
            ps2.setInt(1,500) ;
            ps2.setInt(2,4);

            //通过预编译对象执行sql
            int count = ps.executeUpdate();

            //操作过程中,给一段代码(有问题的代码)
            //int i = 10 /0 ;//除数不能0  try中的某行代码一出问题,就执行catch语句,处理异常
            int count2 = ps2.executeUpdate();

            System.out.println(count+"---"+count2);

          //更新完上面的所有操作,正常提交数据
            conn.commit();
            System.out.println("转账成功");

        } catch (ArithmeticException throwables) {

            try {
                //回滚事务
                //void rollback() throws SQLException撤销在当前事务中所做的所有更改---
                conn.rollback();
                //回滚完之后,手动提交
                conn.commit();
            } catch (SQLException e) {
                e.printStackTrace();
            }

            throwables.printStackTrace(); //交个jvm处理  将异常信息打印控制台
            //System.out.println("出问题了...除数为0");
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //释放资源
            JdbcUtils.close(ps,conn);
            JdbcUtils.close(ps2,conn);
        }
    }
}

2.7 数据库连接池概念以及使用步骤

跟线程池一样,都属于"池化技术"
早期的dbcp
c3p0
现在使用阿里提供的连接池 Druid 德鲁伊(为监控而生)
提供连接池的jar包   druid.jar

后期使用sun提供的接口---java.sql.DataSource(数据源接口)   代替DriverManager

public Connection getConnection() ;  连接池的jar包来实现接口

连接池的好处
    会创建一个固定的可重复用的连接对象,当某个线程使用完毕这个连接对象,
    	将连接对象归还连接池中!

使用步骤
1)导入druid的jar包
2)准备好连接池的配置文件
    配置好数据库的连接信息以及一些连接参数(最大连接数量, 超时时间, 空闲数量)
3)创建连接池对象--->数据源DataSource接口不能实例化,  
	com.alibaba.druid.pool.DruidDataSource它具体类,可以创建
4)DruidDataSourceFactory  连接池数据源工厂类

加入Druid的好处

1)资源重用; 针对连接池提供的参数----初始化连接数量,最大激活数量,最大等待时间
	等等, 就是"共享资源"----->"资源池"
2)连接对象被释,将连接对象归还给连接池,大大提高系统性能!(防止资源浪费)
3)防止连接对象被泄露掉,强制将使用完的连接对象必须归还给连接池!
4)Druid连接池 为监控而生(一直在监听资源池中的连接数量)

2.8 加入连接池后对JDBCUtils的优化

public class JdbcUtilsWithDruid {
    //成员变量
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); //类一加载,就创建线程
    private static DataSource dataSource; //数据源

    //无参构造方法私有化
    private JdbcUtilsWithDruid() {
    }

    //静态代码块
    static {
        try {
            //创建新的属性集合列表
            Properties properties = new Properties();
            //读取druid.properties
            InputStream resourceAsStream = JdbcUtilsWithDruid.class.getClassLoader().
                    getResourceAsStream("druid.properties");
            //将资源文件输入流中的内容加载到属性集合列表properties中
            properties.load(resourceAsStream);

            //将配置文件进行加载,DruidDataSource自动封装
            //通过DruidDataSourceFactory创建数据源
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //定义方法,获取数据源对象
    public static DataSource getDataSource() {
        return dataSource;
    }

    //定义方法,创建连接对象
    public static Connection getConnection() {
        //从当前线程获取连接对象
        Connection conn = threadLocal.get();
        try {
            //判断当前线程中的连接对象是否为null
            if (conn == null) {
                //如果为null,则从连接池中获取连接对象
                Connection connection = dataSource.getConnection();
                //将连接池中获取的连接对象绑定在当前线程中
                threadLocal.set(connection);
                return connection;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    //释放资源
    public static void close(ResultSet rs, Statement stmt, Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
                //从当前线程中解绑
                threadLocal.remove();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    //复用上面的close,第一个参数为null
    public static void close(Statement stmt,Connection conn){
        close(null,stmt,conn);
    }

    public static void main(String[] args) {
        DataSource dataSource = JdbcUtilsWithDruid.getDataSource();
        System.out.println(dataSource);

        Connection connection = JdbcUtilsWithDruid.getConnection();
        System.out.println(connection);
    }
}

2.9 DButils

common-Dbutils的使用步骤
    1)导入dbutils.jar包
    2)创建执行对象
         public QueryRunner(DataSource ds)----->自动提交方式 (前期都用这个)
         public QueryRunner() ----->空参构造---手动提交(牵扯事务的使用)
    3)准备sql语句  update/delete/insert  /select...
    4)执行
         QueryRunner针对update/delete/insert----通用方法
              int update(String sql,Object[]...params):参数1:sql语句   参数2:就是可变参数,给占位符赋值 (属于自动提交更新)
              int update(Connection conn,String sql,Object[]...params) 更新方法
          //通用的查询方法
          public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)
          //参数1:sql语句
          //参数2:结果集的处理---接口--->需要子实现类
                         BeanListHandler<T> :将数据库查询的多条记录--->封装List<T>集合中
                         BeanHandler<T>:将数据库中查询的某条记录---->封装某个实体类中
                         ScalarHandler<T>:将数据库查询的记录--->封装Object类中---返回的数据单行单列的数据(聚合函数)---->查询总记录数
          //参数3:可变参数,在select语句如果有条件查询,传入条件值;如果没有参数,不需要传!

引入DButils后的JDBCUtils

public class JdbcUtilsByDruid {
    //模拟线程
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal();
    private static DataSource dataSource;
    private JdbcUtilsByDruid() {
    }
    static {
        try {
            //读取配置文件
            Properties properties = new Properties();
            properties.load(new FileInputStream("src/druid.properties"));
            //通过DruidDataSourceFactory获取数据源(连接池)
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取数据源
    public static DataSource getDataSource() {
        return dataSource;
    }
    //获取连接对象
    public static Connection getConnection() {
        try {
            //从当前线程中获取连接对象
            Connection connection = threadLocal.get();
            //判断从线程中获取的对象是否为null
            if (connection == null) {
                //如果为null,则从连接池中获取
                connection = dataSource.getConnection();
                //将从连接池中获取的对象绑定到当前线程
                threadLocal.set(connection);
            }
            return connection;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }
    //不需要关闭资源,CommonDbutils.jar包中的QueryRunner执行对象会自动关闭
}

/*
druid.properties
	driverClassName=com.mysql.jdbc.Driver
	url=jdbc:mysql://localhost:3306/库名
	username=用户名
	password=密码
	//初始化数量
	initialSize=5
	//最大连接数据
	maxActive=10
	//最大等待时长
	maxWait=3000
*/

3. HTML

Hypert Text Markup Language:超文本记语言

网页标签

常见的文本标签
1)标题标签h1-h6 :从大到小的标题
2)段落标签 p
3)滚动标签marquee
	属性:
		behivour:滚动的方式
		slide:默认从右滚到左边结束
		alternate:默认从右滚动到左边然后来回滚动
		默认值​ scroll:​穿梭滚动
		srollamount:滚动速度,正数值 值越大,速度越快
		direction:滚动方向,默认left,从右到左
		rigth从左到右
		bgcolor:背景颜色
4) div标签和span标签     
		div:占一行空间 
		span:行内标签---在一行上,不会换行
		div----层级布局去使用  div+Css-----完成页面布局
5)引用标签:blockquote ----
	针对某个段落的文字进行解释说明,自带段落缩进的效果
6)原样输出  pre标签,按照文本的原先格式---原封不动的展示!
7)上下标标签    sup和sub
    上标 sup使用居多----结合html转义字符
	版权所有  &copy;  ----©
	注册商品  &reg;     
8)无序列表 ul li
	ul 	
		type属性 列表项前的标记 默认值 disc(实心原点)
		circle:空心原点
		square:正方形

9)有序列表
	ol  li
		ol里面 type属性的默认值从1开始
10)超链接标签 a标签
	属性:href:连接到本地地址或者服务器地址(url地址:同意资源定位符)
	协议://域名/地址
		协议
			http协议--https--联网
			thunder://迅雷协议
			file://本地文件协议
			后面用的服务器 tomcat --window系统本地部署
			linux系统---远程部署
			http://localhost:8080/findproduct
			127.0.0.1
			域名 -- 绑定 -- ip地址
					
	target属性:
		打开新页面地址的方式
		默认值:_self 当前页面直接打开
		_blank:新建一个窗口打开
11)超链接
	 <a ></a>
    属性:
        href: 连接到本地地址或者服务器地址(url地址:统一资源定位符)
            协议://域名/地址
            http://
            thunder://迅雷协议
            file://本地文件协议
        target: 打开新页面地址的方式
            默认值: _self 当前页面直接打开
            _blank  新建窗口打开
    超链接应用
        <a href="跳转url地址" target="打开方式">文本内容</a>
        锚链接的使用
            同一个页面使用
            a)创建一个锚点 (创建一个标记)
                <a name="锚点名称"></a>
            b)创建跳转连接
                <a href="#锚点名称">跳转</a>
            在不同页面上使用
            a)在另一个页面某个位置创建一个锚点 (创建一个标记)
                <a name="锚点名称"></a>
            b)在当前页面中,进行跳转链接
                <a href="另一个页面地址#锚点名称">跳转</a>
12)表格标签 table
	<table></table>

    html语言中只有行的概念 tr, 没有列的概念 td : 理解为列
    tr 一行中有多少个td
    
    属性:
        要表格边框线 border 边框线  单位px
        表格对齐方式 align  left right center 
        bgcolor  背景色
        width和height  宽度和高度
        cellspacing  设置单元格和边框线的距离
    
    子标签
        tr : 行
        td : 是一个普通单元格
        th : 是一个特殊单元格(表格的表头  自动居中,加粗)
        caption : 表格的标题标签
        
        
    普通单元格合并
        colspan : 合并列,当前单元格占的格子数
        rowspan : 合并行,当前单元格占的格子数
13)表单标签 form
<form></form>

    表单场景 : 注册或者登录
        注册--将用户的信息提交后端服务器上,校验用户信息是否存在,如果存在,不能注册;
        登录---将用户信息提狡服务器上,查看是否有这个用户,有才能的登录;
        表单提交的时候,里面所有的表单项标签必须有一个name属性
        	---后端服务器才能知道用户的输入内容
        
    属性: 
        action : url地址  将表单中的表单项的数据提交到后台服务器地址上
        method : 表单的提交工具
            get/post
   
    常见表单标签的表单项
        跟input 标签相关的表单项
            input type = "text"  文本输入框
            input type = "password"  密码输入框
            input type = "radio"  单选按钮-
            input type = "checkbox"  复选框
            input type = "date"  日期组件
            input type = "file"  文件上传组件
        
            普通按钮
            input type = "button"  必须和value="属性值"
            特殊按钮
            input type = "submit"  表单提交按钮
            input type = "reset"  重置按钮, 清空表单项
        select : 下拉菜单
            option : 下拉选项
14)框架标签 frame
	整个结构是2个或者2个以上的html组成,不能使用frame(只能包含一个html页面)
	需要使用 frameset框架集,不能body共存,要么在加载在他前面,或者删除body
15)图像标签 img
	scr属性 : 连接到图片地址(可以是本地图片或者网络图片)
    width:  图片宽度 指定像素px或者百分比(占整个宽度分辨率的百分之几)
    heigh:  图片高度 指定像素px或者百分比(占整个宽度分辨率的百分之几)
    title : 当鼠标悬浮在图片上的时候,有提示信息
    alt :  替代文本  当这个图片失效(地址找不到),他会给一个信息描述
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、JDBC(Java Database Connection):java连接数据库统一接口API,底层主要通过直接的JDBC驱动和 JDBC-ODBC桥驱动实现与数据库的连接。 1>.JDBC驱动程序类型: <1>.JDBC-ODBC桥加ODBC驱动程序:需要ODBC驱动,适合于企业网或三层结构应用程序 <2>.本地API:需要驱动程序的二进制代码支持 <3>.JDBC网络纯java驱动程序:将JDBC转换为与DBMS无关的网络协议,又被某服务器转换为一种DBMS 协议,以操作各种数据库 <4>.本地协议纯java驱动程序:将JDBC调用直接转换成JDBC所使用的网络协议 2、JDBC操作基本流程: 1>.导入驱动:实例化时自动向DriverManager注册(DriverManager.registerDriver()) <1>.Class.forName(driver) <2>.Class.forName(driver).newInstance() <3>.new driver() 2>.取得数据库连接(Connect to the DataBase) <1>.用DriverManager取数据库连接 Connection cn = DriverManager.getConnection(url,uid,pwd); <2>.用jndi(java的命名和目录服务)方式:多用于jsp Context ctx = (Context) new InitialContext().lookup("java:comp/env"); DataSource ds = (DataSource) ctx.lookup(jndi); Connection cn = ds.getConnection(); 3>.执行sql语句(Execute the SQL) <1>.用Statement来执行sql语句 Statement sm = cn.createStatement(); sm.executeQuery(sql); // 执行数据查询语句(select) sm.executeUpdate(sql); // 执行数据更新语句(delete、update、insert、drop等) <2>.用PreparedStatement来执行sql语句 String sql = "insert into user (id,name) values (?,?)"; PreparedStatement ps = cn.prepareStatement(sql); ps.setInt(1,xxx); ps.setString(2,xxx); ... ResultSet rs = ps.executeQuery(); // 查询 int c = ps.executeUpdate(); // 更新 4>.处理执行结果: <1>.查询语句,返回记录集ResultSet <2>.更新语句,返回数字,表示该更新影响的记录数 <3>.ResultSet的方法:while(re.next()) next(),将游标往后移动一行,如果成功返回true;否则返回false getInt("id")或getSting("name"),返回当前游标下某个字段的值 5>.释放数据库连接 rs.close(); ps.close(); /stat.close(); con.close(); 3、创建可滚动、更新的记录集 1>.创建Statement时指定参数:该Statement取得的ResultSet就是可滚动的 Statement sm = cn.createStatement(ResultSet.TYPE_SCROLL_ENSITIVE, ResultSet.CONCUR_READ_ONLY); 2>.创建PreparedStatement时指定参数 PreparedStatemet ps = cn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs.absolute(9000);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值