JDBC初探

在这里插入图片描述

If we did all the things we are capable of doing, we would literally astound ourselves.
如果把我们能做到的都做了,最终连我们自己都会被吓到。


1. JDBC基础操作

JAVA Database Connectivity java数据库连接

  • 为什么会出现JDBC

SUN公司提供的一种数据库访问规则、规范, 由于数据库种类较多,并且java语言使用比较广泛,sun公司就提供了一种规范,让其他的数据库提供商去实现底层的访问规则。 我们的java程序只要使用sun公司提供的jdbc驱动即可。

使用JDBC的基本步骤
  1. 注册驱动

    DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    
    
  2. 建立连接

    //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
    
    //2. 建立连接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/student", "root", "123");
    
  3. 创建statement

    //  创建statement , 跟数据库打交道,一定需要这个对象
    Statement st = conn.createStatement();
    
  4. 执行sql ,得到ResultSet

    // 执行查询, 得到结果集
    String sql = "select * from t_stu";
    ResultSet rs = st.executeQuery(sql);
    
  5. 遍历结果集

    // 遍历查询每一条记录
    while(rs.next()) {
      int id = rs.getInt("id");
      String name = rs.getString("name");
      int age = rs.getInt("age");
      System.out.println("id="+id + "===name="+name+"==age="+age);
    			
    }
    
  6. 释放资源

    if (rs != null) {
      try {
        rs.close();
      } catch (SQLException sqlEx) { } // ignore 
        rs = null;
    }
    

2. JDBC 工具类构建

1.资源释放工作的整合

    /**
     * des: 释放资源
     * @param conn connection
     * @param st   statement
     * @param rs   ResultSet
     */
    public static void release(Connection conn, Statement st, ResultSet rs) {
        closeRs(rs);
        closeSt(st);
        closeConn(conn);
    }

    private static void closeRs(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {

            } finally {
                rs = null;
            }
        }
    }

    private static void closeSt(Statement st) {
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {

            } finally {
                st = null;
            }
        }
    }

    private static void closeConn(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {

            } finally {
                conn = null;
            }
        }
    }
}

2.驱动防二次注册

  • DriverManager.registerDriver(new com.mysql.jdbc.Driver());
  • Driver 这个类里面有静态代码块,一上来就执行了,所以等同于我们注册了两次驱动。 其实没这个必要的。
注意: 通过下面的代码可知, 官方已经帮我们实现了注册驱动
//静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver());
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}
> 正确写法: Class.forName(com.mysql.jdbc.Driver());

Class.forName(com.mysql.jdbc.Driver()); 写法的解释

3.使用properties配置文件

  1. 在src底下声明一个文件 xxx.properties ,里面的内容吐下:

    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost/student(数据库名称)
    name=root
    password=123
    
  2. 在工具类里面,使用静态代码块,读取属性

static String driverClass = null;
static String URL         = null;
static String name        = null;
static String password    = null;

static{
    try {
          //1. 创建一个属性配置对象
          Properties properties = new Properties();
         // InputStream is = new FileInputStream("jdbc.properties"); //对应文件位于工程根目录

          //使用类加载器,去读取src底下的资源文件。 后面在servlet  //对应文件位于src目录底下
          InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
          //导入输入流。
          properties.load(is);

          //读取属性
          driverClass = properties.getProperty("driverClass");
          url = properties.getProperty("url");
          name = properties.getProperty("name");
          password = properties.getProperty("password");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

extra: 获取连接对象


    /**
     * 获取连接对象
     * @return
     */
    public static Connection getConn() {
        Connection conn = null;
        try {
            // 1. 注册驱动
            Class.forName(driverClass);
            // 2. 建立连接  参数1: 协议+访问的数据库, 参数2: 用户名 参数3: 密码
            conn = DriverManager.getConnection(URL, name, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

完整代码:

  • 项目结构

package jdbc.java.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtil {

    static String driverClass = null;
    static String URL         = null;
    static String name        = null;
    static String password    = null;

    static {
        try {
            // 1. 创建一个属性配置对象
            Properties properties = new Properties();
            // 2. 使用类加载器, 读取src底下的资源文件
            InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
            // 3.导入输入流
            properties.load(is);

            // 4. 读取属性
            driverClass = properties.getProperty("driverClass");
            URL = properties.getProperty("URL");
            name = properties.getProperty("name");
            password = properties.getProperty("password");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接对象
     * @return
     */
    public static Connection getConn() {
        Connection conn = null;
        try {
            // 1. 注册驱动
            Class.forName(driverClass);
            // 2. 建立连接  参数1: 协议+访问的数据库, 参数2: 用户名 参数3: 密码
            conn = DriverManager.getConnection(URL, name, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }


    /**
     * des: 释放资源
     * @param conn connection
     * @param st   statement
     * @param rs   ResultSet
     */
    public static void release(Connection conn, Statement st, ResultSet rs) {
        closeRs(rs);
        closeSt(st);
        closeConn(conn);
    }

    private static void closeRs(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {

            } finally {
                rs = null;
            }
        }
    }

    private static void closeSt(Statement st) {
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {

            } finally {
                st = null;
            }
        }
    }

    private static void closeConn(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {

            } finally {
                conn = null;
            }
        }
    }
}

3. 使用单元测试, 测试代码

  1. 在src目录下创建一个test文件夹, 定义一个类, TestXXX , 里面定义方法 testXXX.

  2. 添加junit的支持, 具体实现请参照 junit配置

  3. 在方法的上面加上注解 , 其实就是一个标记。

    @Test

    public void testQuery() {
    	...
    }
    
  4. 光标选中方法名字,然后右键执行单元测试。


4. 数据库的CRUD sql

  • insert

    INSERT INTO t_stu VALUES (NULL,'wangqiang',28)
    
    Connection conn = null;
    Statement st = null;	   
    // 1. 获取连接对象
    conn = JDBCUtil.getConn();
    // 2. 根据连接对象,得到statement
    st = conn.createStatement();
    
    //3. 执行添加
    String sql = "insert into t_stu values(null , 'aobama' , 59)";
    //影响的行数, ,如果大于0 表明操作成功。 否则失败
    int result = st.executeUpdate(sql);
    
    if(result > 0 ){
      System.out.println("添加成功");
    } else{
      System.out.println("添加失败");
    }
    
  • delete

    DELETE FROM t_stu WHERE id = 6

    // 1. 获取连接对象
    conn = JDBCUtil.getConn();
    // 2. 根据连接对象,得到statement
    st = conn.createStatement();
    
    //3. 执行添加
    String sql = "delete from t_stu where name='aobama'";
    //影响的行数, ,如果大于0 表明操作成功。 否则失败
    int result = st.executeUpdate(sql);
    
    if(result > 0 ){
      System.out.println("删除成功");
    } else {
      System.out.println("删除失败");
    }
    
  • query

    SELECT * FROM t_stu

    // 1. 获取连接对象
    conn = JDBCUtil.getConn();
    // 2. 根据连接对象,得到statement
    st = conn.createStatement();
    
    // 3. 执行sql语句,返回ResultSet
    String sql = "select * from t_stu";
    rs = st.executeQuery(sql);
    
    // 4. 遍历结果集
    while (rs.next()) {
    String name = rs.getString("name");
    int age = rs.getInt("age");
    
    System.out.println(name + "   " + age);
    }
    
  • update

    UPDATE t_stu SET age = 38 WHERE id = 1;

    // 1. 获取连接对象
    conn = JDBCUtil.getConn();
    // 2. 根据连接对象,得到statement
    st = conn.createStatement();
    
    //3. 执行添加
    String sql = "update t_stu set age = 26 where name ='qyq'";
    //影响的行数, ,如果大于0 表明操作成功。 否则失败
    int result = st.executeUpdate(sql);
    
    if(result > 0 ){
    	System.out.println("更新成功");
    } else{
    	System.out.println("更新失败");
    }
    

完整代码

  • 项目结构

    package com.daohewang.jdbc.test;
    
    import com.daohewang.jdbc.util.JDBCUtil;
    import org.junit.jupiter.api.Test;
    
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    public class UnitTest {
    
        /**
         * 查询测试
         */
        @Test
        public void testQuery() {
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                // 1. 获取连接对象
                conn = JDBCUtil.getConn();
                // 2. 根据连接对象,得到statement语句
                st = conn.createStatement();
                // 3. 执行sql语句,返回ResultSet
                String sql = "select * from score";
                rs = st.executeQuery(sql);
                // 4. 遍历结果
                while (rs.next()) {
                    String name = rs.getString("name");
                    int age = rs.getInt("age");
                    System.out.println("name  " + name + " age  " + age);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, st, rs);
            }
        }
    
        /**
         * 添加测试
         */
        @Test
        public void testInsert() {
            Connection conn = null;
            Statement st = null;
            try {
                conn = JDBCUtil.getConn();
                st = conn.createStatement();
    
                String sql = "INSERT INTO score VALUES (NULL, 'weny', 21)";
                int res = st.executeUpdate(sql);
                if (res > 0) {
                    System.out.println("添加成功");
                } else {
                    System.out.println("添加失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, st);
            }
        }
    
        /**
         * 删除测试
         */
        @Test
        public void testDelete() {
            Connection conn = null;
            Statement st = null;
            try {
                conn = JDBCUtil.getConn();
                st = conn.createStatement();
    
                String sql = "DELETE FROM score WHERE name='weny'";
                int res = st.executeUpdate(sql);
                if (res > 0) {
                    System.out.println("删除成功");
                } else {
                    System.out.println("删除失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, st);
            }
        }
    
        /**
         * 更新测试
         */
        @Test
        public void testUpdate() {
            Connection conn = null;
            Statement st = null;
            try {
                conn = JDBCUtil.getConn();
                st = conn.createStatement();
    
                String sql = " UPDATE score SET age=12 WHERE id=2";
                int res = st.executeUpdate(sql);
                if (res > 0) {
                    System.out.println("更新成功");
                } else {
                    System.out.println("更新失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JDBCUtil.release(conn, st);
            }
        }
    
    
    }
    
    

    6. Dao模式

    Data Access Object 数据访问对象

    项目结构

    49.png

    1. 新建一个dao的接口, 里面声明数据库访问规则

      	/**
      	 * 定义操作数据库的方法
      	 */
      	public interface UserDao {
      	
      		/**
      		 * 查询所有
      		 */
      		void findAll();
      	}
      
    2. 新建一个dao的实现类,具体实现早前定义的规则

      public class UserDaoImpl implements UserDao{
      	@Override
      	public void findAll() {
      		Connection conn = null;
      		Statement st = null;
      		ResultSet rs = null;
      		try {
      			//1. 获取连接对象
      			conn = JDBCUtil.getConn();
      			//2. 创建statement对象
      			st = conn.createStatement();
      			String sql = "select * from t_user";
      			rs = st.executeQuery(sql);
      			
      			while(rs.next()){
      				String userName = rs.getString("username");
      				String password = rs.getString("password");
      				
      				System.out.println(userName+"="+password);
      			}
      			
      		} catch (Exception e) {
      			e.printStackTrace();
      		} finally {
      			JDBCUtil.release(conn, st, rs);
      		}
      	}
      
      }
      
    3. 直接使用实现

       ```java
       @Test
       public void testFindAll(){
       	UserDao dao = new UserDaoImpl();
       	dao.findAll();
       }
       ```
      

    Statement安全问题

  1. Statement执行 ,其实是拼接sql语句的。 先拼接sql语句,然后在一起执行。

    String sql = "select * from t_user where username='"+ username  +"' and password='"+ password +"'";
    
    UserDao dao = new UserDaoImpl();
    dao.login("admin", "100234khsdf88' or '1=1");
    
    SELECT * FROM t_user WHERE username='admin' AND PASSWORD='100234khsdf88' or '1=1' 
    
    前面先拼接sql语句, 如果变量里面带有了 数据库的关键字,那么一并认为是关键字。 不认为是普通的字符串。 
    rs = st.executeQuery(sql);
    

PrepareStatement

该对象就是替换前面的statement对象。

  1. 相比较以前的statement, 预先处理给定的sql语句,对其执行语法检查。 在sql语句里面使用 ? 占位符来替代后续要传递进来的变量。 后面进来的变量值,将会被看成是字符串,不会产生任何的关键字。

    String sql = "insert into t_user values(null , ? , ?)";
    ps = conn.prepareStatement(sql);
    
    //给占位符赋值 从左到右数过来,1 代表第一个问号, 永远你是1开始。
    ps.setString(1, userName);
    ps.setString(2, password);
    

实现代码:

定义user类

package com.daohewang.jdbc.dao.impl;
public class User {
    private String username;
    private String password;
    private String gender;
    private String email;
    private String telephone;

    public User() {
    }

    public User(String username, String password, String gender, String email, String telephone) {
        this.username = username;
        this.password = password;
        this.gender = gender;
        this.email = email;
        this.telephone = telephone;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", email='" + email + '\'' +
                ", telphone='" + telephone + '\'' +
                '}';
    }
}

定义dao接口

package com.daohewang.jdbc.dao;
import com.daohewang.jdbc.dao.impl.User;

import java.util.ArrayList;
public interface UserDao {
    /**
     * 增加
     * @param username
     * @param password
     */
    int insert(String username, String password, String gender, String email, String telphone);

    /**
     * 删除
     * @param username
     * @return
     */
    int delete(String username);

    /**
     * 更新
     * @param name
     * @param password
     * @return
     */
    int update(String name, String password);


    /**
     * 查询数据库所有信息
     */
    ArrayList<User> findAll();

    /**
     * 登录
     * @param username
     * @param password
     */
    ArrayList<User> login(String username, String password, String gender, String email, String telephone);

}

定义dao接口实现

package com.daohewang.jdbc.dao.impl;
import com.daohewang.jdbc.dao.UserDao;
import com.daohewang.jdbc.util.JDBCUtil;
import java.sql.*;
import java.util.ArrayList;

public class UserDaoImp implements UserDao {

    Connection conn = null;
    Statement st = null;
    ResultSet rs = null;


    /**
     * 增加操作
     * @param username
     * @param password
     * @param gender
     * @param email
     * @param telephone
     * @return
     */
    @Override
    public int insert(String username, String password, String gender, String email, String telephone) {
        PreparedStatement ps = null;
        int res = 0;
        try {
            // 1. 获取连接对象
            conn = JDBCUtil.getConn();

            String sql = "INSERT INTO t_login VALUES(null,?,?,?,?,?)";
            //预先对sql语句执行语法的校验, ? 对应的内容,后面不管传递什么进来,都把它看成是字符串。 or select
            ps = conn.prepareStatement(sql);
            ps.setString(1, username);
            ps.setString(2, password);
            ps.setString(3, gender);
            ps.setString(4, email);
            ps.setString(5, telephone);
            int result = ps.executeUpdate();
            if (result > 0) {
                res ++;
                System.out.println("插入成功");
            } else {
                System.out.println("插入失败");
                res = 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, ps);
        }
        return res;
    }

    /**
     * 删除操作
     * @param username
     * @return
     */
    @Override
    public int delete(String username) {
        PreparedStatement ps = null;
        int res = 0;
        try {
            Connection conn = JDBCUtil.getConn();
            String sql = "DELETE FROM t_login WHERE username = ?";
            // 预加载
            ps = conn.prepareStatement(sql);

            // 给占位符赋值
            ps.setString(1, username);

            int result = ps.executeUpdate();
            if (result > 0) {
                System.out.println("删除成功");
                res++;
            } else {
                System.out.println("删除失败");
                res = 0;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn,st,rs);
        }
        return res;
    }

    /**
     * 更新
     * @param username
     * @param password
     * @return
     */
    @Override
    public int update(String username, String password) {
        PreparedStatement ps = null;
        int res = 0;
        try {
            Connection conn = JDBCUtil.getConn();
            String sql = "UPDATE t_login SET password = ? WHERE username=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1, password);
            ps.setString(2, username);
            int result = ps.executeUpdate();
            if (result > 0) {
                System.out.println("修改成功");
                res++;
            } else {
                System.out.println("修改失败");
                res = 0;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, ps);
        }
        return res;
    }

    /**
     * 查找操作
     * @return
     */
    @Override
    public ArrayList<User> findAll() {
        ArrayList<User> list = new ArrayList<>();
        try {
            // 获取连接对象
            conn = JDBCUtil.getConn();
            // 创建 statement对象
            st = conn.createStatement();

            String sql = "SELECT * FROM t_login";
            rs = st.executeQuery(sql);

            while (rs.next()) {
                String username = rs.getString("username");
                String password = rs.getString("password");
                String gender = rs.getString("gender");
                String email = rs.getString("email");
                String telephone = rs.getString("telphone");
                list.add(new User(username,password,gender,email,telephone));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, st, rs);
        }
        return list;
    }

    /**
     * 登录操作
     * @param userName
     * @param password
     * @param gender
     * @param email
     * @param telephone
     * @return
     */
    @Override
    public ArrayList<User> login(String userName, String password, String gender, String email, String telephone) {
        ArrayList<User> list = new ArrayList<>();
        try {
            // 1. 获取连接对象
            conn = JDBCUtil.getConn();

            String sql = "select * from t_login where username=? and password=? AND gender=? AND email=? AND telphone=?";
            //预先对sql语句执行语法的校验, ? 对应的内容,后面不管传递什么进来,都把它看成是字符串。 or select
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, userName);
            ps.setString(2, password);
            ps.setString(3, gender);
            ps.setString(4, email);
            ps.setString(5, telephone);
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                list.add(new User(userName, password, gender, email, telephone));
                System.out.println("登录成功");
            } else {
                System.out.println("登录失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, st, rs);
        }
        return list;
    }


}

单元测试类

package com.daohewang.jdbc.test;
import com.daohewang.jdbc.util.JDBCUtil;
import org.junit.jupiter.api.Test;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class UnitTest {

    /**
     * 查询测试
     */
    @Test
    public void testQuery() {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            // 1. 获取连接对象
            conn = JDBCUtil.getConn();
            // 2. 根据连接对象,得到statement语句
            st = conn.createStatement();
            // 3. 执行sql语句,返回ResultSet
            String sql = "select * from score";
            rs = st.executeQuery(sql);
            // 4. 遍历结果
            while (rs.next()) {
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println("name  " + name + " age  " + age);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, st, rs);
        }
    }

    /**
     * 添加测试
     */
    @Test
    public void testInsert() {
        Connection conn = null;
        Statement st = null;
        try {
            conn = JDBCUtil.getConn();
            st = conn.createStatement();

            String sql = "INSERT INTO score VALUES (NULL, 'weny', 21)";
            int res = st.executeUpdate(sql);
            if (res > 0) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, st);
        }
    }

    /**
     * 删除测试
     */
    @Test
    public void testDelete() {
        Connection conn = null;
        Statement st = null;
        try {
            conn = JDBCUtil.getConn();
            st = conn.createStatement();

            String sql = "DELETE FROM score WHERE name='weny'";
            int res = st.executeUpdate(sql);
            if (res > 0) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, st);
        }
    }

    /**
     * 更新测试
     */
    @Test
    public void testUpdate() {
        Connection conn = null;
        Statement st = null;
        try {
            conn = JDBCUtil.getConn();
            st = conn.createStatement();

            String sql = " UPDATE score SET age=12 WHERE id=2";
            int res = st.executeUpdate(sql);
            if (res > 0) {
                System.out.println("更新成功");
            } else {
                System.out.println("更新失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.release(conn, st);
        }
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值