Jdbc连接数据库(Java)根据b站韩老师视频写的文档

Jdbc连接数据库方式

首先需要添加数据需要的jar包:mysql-connector-java-版本号.jar
我使用的是:mysql-connector-java-5.1.47.jar
mysql 6及以上版本Driver = com.mysql.cj.jdbc.Driver
mysql 8及以上版本url=jdbc:mysql://localhost:3306/数据库名称?serverTimezone=UTC

1、第一种连接方式:

 @Test 
 public void connection01() throws SQLException {
        //1.创建 驱动
        Driver driver = new Driver();//创建Driver对象
        //2.得到连接
        String url = "jdbc:mysql://localhost:3306/数据库名";
//        String name = "数据库账号";
//        String password = "数据库密码";
        Properties properties = new Properties();
        properties.setProperty("user","数据库账号");
        properties.setProperty("password","数据库密码");
        Connection connect = driver.connect(url, properties);
        System.out.println("成功连接");
    }

2、第二种连接方式:(使用反射加载Driver)

 @Test
 public void connection02() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
     //使用反射加载Driver类
     Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
     Driver driver = (Driver) aClass.newInstance();

     String url ="jdbc:mysql://localhost:3306/数据库名";
     Properties properties = new Properties();
     properties.setProperty("user","数据库账号");
     properties.setProperty("password","数据库密码");


     Connection connect = driver.connect(url, properties);
     System.out.println("成功2");
 }

3、第三种连接方式:(使用反射加载Driver,使用DriverManager 替代 Driver 进行统一管理)

    @Test
    public void connection03() throws IllegalAccessException, InstantiationException, ClassNotFoundException, SQLException {
        //使用反射加载Driver
        Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) aClass.newInstance();
        //创建URL和uer和password
        String url = "jdbc:mysql://localhost:3306/java2023";
        String user = "root";
        String password = "root";
        //使用DriverManager 替代 Driver 进行统一管理
        DriverManager.registerDriver(driver);//注册Driver驱动
        Connection connection = DriverManager.getConnection(url, user, password);
        System.out.println("第三种连接方式:" + connection);
    }

4、第四种连接方式:(使用Class.forName 自动完成注册驱动)

 //使用Class.forName 自动完成注册驱动,简化代码
    @Test
    public void connection04() throws ClassNotFoundException, SQLException {
       //使用反射加载Driver类
        Class.forName("com.mysql.jdbc.Driver");
        String url  = "jdbc:mysql://localhost:3306/数据库名称";
        String user = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, user, password);
        System.out.println("第四种连接方式:" + connection);
    }

5、第五种连接方式:(使用文件mysql.properties进行连接)

在项目的scr目录下创建配置文件mysql.properties

user=数据库账号
password=数据库密码
url=jdbc:mysql://localhost:3306/数据库名称
driver=com.mysql.jdbc.Driver
@Test
   public void connection05() throws IOException, ClassNotFoundException, SQLException {
       Properties properties = new Properties();
       properties.load(new FileInputStream("src\\mysql.properties"));
       //获取相关的值
       String user = properties.getProperty("user");
       String password = properties.getProperty("password");
       String url = properties.getProperty("url");
       String driver = properties.getProperty("driver");

       Class.forName(driver);
       Connection connection = DriverManager.getConnection(url, user, password);
       System.out.println("第五种连接方式:"+ connection);
   }

Jdbc连接数据库全流程(statement操作数据库)

public class Statement_ {
   public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
       Scanner sc = new Scanner(System.in);
       System.out.print("请输入管理员姓名: ");
       String admin_name = sc.nextLine();
       System.out.print("请输入管理员密码: ");
       String admin_password = sc.nextLine();
       
       Properties properties = new Properties();
       properties.load(new FileInputStream("src\\mysql.properties"));
       String user = properties.getProperty("user");
       String password = properties.getProperty("password");
       String url = properties.getProperty("url");
       String driver = properties.getProperty("driver");
       Class.forName(driver);
       
       Connection connection = DriverManager.getConnection(url, user, password);
       String sql = "select * from actor where name = '"+ admin_name+"' and sex = '"+ admin_password+"'" ;
       Statement statement = connection.createStatement();
       //查询操作
       ResultSet resultSet = statement.executeQuery(sql);
       //ececuteUpdate(sql)处理DML操作(增删改),返回成功的行数
       //int row = statement.executeUpdate(sql);
       while(resultSet.next()){
           int id = resultSet.getInt(1);
           String name = resultSet.getString(2);
           String sex = resultSet.getString(3);
           Date borndate = resultSet.getDate(4);
           String phone = resultSet.getString(5);
           System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone );
       }
       //关闭连接
       sc.close();
       resultSet.close();
       statement.close();
       connection.close();
   }
}

JDBC连接数据库六步:

1.注册驱动

Driver driver = new Driver();
//Class.from(“com.mysql.jdbc.Driver”)
获取Driver对象

2.建立数据库连接

Connection connect = driver.connect(url, properties);
获取连接对象connection

3.创建数据库操作对象

Statement statement = connection.createStatement();
创建数据库操作对象,为执行sql语句做准备

4.执行 SQL语句

String sql = " ";

执行dml操作
int row = statement.executeUpdate(sql);
执行dql操作
ResultSet resultSet = statement.executeQuery(sql);

5.处理查询结果集(如果第4步用的是DQL(select)语句就要第5步)

while(resultSet.next()){
resultSet.getXxx();
}
处理ResultSet结果集,输出需要的对象

6.关闭资源 (finally {} 中从小到大依次close)

resultSet.close() 关闭结果集对象
statement.close() 关闭数据库操作对象statement(select操作独有)
connection.close() 关闭数据库连接

Statement

会产生的问题

会产生sql注入问题
select * from 数据库表 where name = ’ 1 ’ or ’ and password= ’ or ‘1’ ='1 ’

常用的statement方法

executeUpdate(sql):执行DML语句,返回影响的行数
executeQuery(sql): 执行DQL语句,返回ResultSet对象
execute(sql): 执行任意的sql,返回boolean值

PreparedStatement

对sql语句进行预处理操作,避免statement方法产生的sql注入问题

select * from 数据库表 where name = ? and password = ?
PreparedStatement执行SQL语句中的参数用问号(?)来表示,调用PerparedStatement对象的sexXxx()方法来设置这些参数,setXxx( snoNumber,value )有连个参数,第一个参数是要设置sql语句中的参数的索引(从1开始),第二个是设置sql语句中参数的值。

常用的PreparedStatement方法

executeUpdate(sql):执行DML语句,返回影响的行数
executeQuery(sql): 执行DQL语句,返回ResultSet对象
execute(sql): 执行任意的sql,返回boolean值
setXxx(snoNumber,value)

  • Xxx为数据库值对应的类型,
  • snoNumber为数据库预处理的位置,
  • value为预处理应该填写值

ResultSet

常用的ResultSet方法

next():向下移动一行,如果没有下一行,返回false。用while(ResultSet.next()){}进行判断
previous(): 向上移动一行
getXxx(列的索引|列名)

JDBCUtils开发

创建一个Utils类将注册驱动,建立连接和关闭资源的操作进行统一管理

public class JdbcUtils {

   private static String user;
   private static String password;
   private static String url;
   private static String driver;

//添加配置文件并完成注册驱动
   static{
       try {
           Properties properties = new Properties();
           properties.load(new FileInputStream("src\\mysql.properties"));
           user = properties.getProperty("user");
           password = properties.getProperty("password");
           url = properties.getProperty("url");
           driver = properties.getProperty("driver");
           Class.forName(driver);
       } catch (IOException | ClassNotFoundException e) {
           throw new RuntimeException(e);
       }
   }


   //得到数据库连接connection
   public static Connection getConnection() {
       try {
           return DriverManager.getConnection(url,user,password);
       } catch (SQLException e) {
           throw new RuntimeException(e);
       }
   }

   //关闭数据库资源
   public static void close(ResultSet resultSet, Statement statement,Connection connection) {
       try {
           if (resultSet != null) {
               resultSet.close();
           }
           if (statement != null) {
               statement.close();
           }
           if (connection != null) {
               connection.close();
           }
       } catch (SQLException e) {
          throw new RuntimeException(e);
       }
   }
}

JdbcUtilsDML操作

@Test
   public  void JdbcUtils_DML() {

       Connection connection = null;
       PreparedStatement preparedStatement =null;
       String sql = "update actor set name = ? where id = ?";

       try {
           connection = JdbcUtils.getConnection();
           preparedStatement = connection.prepareStatement(sql);
           preparedStatement.setString(1,"张三啊");
           preparedStatement.setInt(2,3);
           preparedStatement.executeUpdate();
       } catch (SQLException e) {
           e.printStackTrace();
       }finally {
               JdbcUtils.close(null,preparedStatement,connection);
       }
   }

JdbcUtilsDQL操作

@Test
  public void JdbcUtils_DQL(){
      Connection connection = null;
      PreparedStatement preparedStatement = null;
      ResultSet resultSet = null;
      String sql = "select * from actor ";
      try {
          connection = JdbcUtils.getConnection();
          preparedStatement = connection.prepareStatement(sql);
          resultSet = preparedStatement.executeQuery();
          while(resultSet.next()){
          //使用数据库名称完成对象的创建
//                int id = resultSet.getInt("id");
//                String name = resultSet.getString("name");
//                String sex = resultSet.getString("sex");
//                Date bondate = resultSet.getDate("bondate");
//                String phone = resultSet.getString("phone");
              int id = resultSet.getInt(1);
              String name = resultSet.getString(2);
              String sex = resultSet.getString(3);
              Date bondate = resultSet.getDate(4);
              String phone = resultSet.getString(5);

              System.out.println(id + "\t" + name + "\t" + sex + "\t" + bondate + "\t" + phone);
          }
      } catch (SQLException e) {
          e.printStackTrace();
      }finally {
          JdbcUtils.close(resultSet,preparedStatement,connection);

      }
  }

Jdbc事务处理

  • Jdbc程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
  • Jdbc程序为了让多个SQL语句作为一个整体执行,需要使用事务。
  • 调用Connection的setAutoConnection(false),取消自动提交事务。
  • 在所有的SQL语句都成功执行后,调用commit( ) 方法提交事务。
  • 在其中某个操作失败或出现异常时,调用rollback( )方法回滚事务。

setAutoCommit(false) 将数据事务提交设置为手动提交
commit( ) 事务成功完成就将数据库进行提交,完成持久化
rollback( ) 事务出现异常就将数据库进行回滚,返回到初始状态

@Test
  public void JdbcUtils_Transaction_Test(){
      Connection connection = null;
      String sql = "update account set blance = blance - 100 where name = ?";
      String sql1 = "update account set blance = blance + 100 where name = ?";
      PreparedStatement preparedStatement = null;
      try {
          connection = JdbcUtils.getConnection();
          
  		//将数据库事务提交设置为手动提交
          connection.setAutoCommit(false);
          
          preparedStatement = connection.prepareStatement(sql);
          preparedStatement.setString(1,"马云");
          int i = preparedStatement.executeUpdate();
//            int round = 1/0;
           preparedStatement = connection.prepareStatement(sql1);
           preparedStatement.setString(1,"马化腾");
          int i1 = preparedStatement.executeUpdate();
          
  		//成功完成数据库操作就提交事务,完成持久化操作
          connection.commit();
          
      } catch (Exception e) {
          try {
              //出现异常就将事务进行回滚操作
              connection.rollback();
              
              System.out.println("rollback执行了");
          } catch (SQLException throwables) {
              throwables.printStackTrace();
          }
          e.printStackTrace();
      }finally {
          JdbcUtils.close(null,preparedStatement,connection);
      }
  }

Jdbc批处理

  • 当需要称批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更加有效率。
  • Jdbc的批处理语句包括以下方法:
    • addBatch( ) 添加需要批处理的sql语句或参数
    • execueteBatch( ) 执行批处理语句
    • clearBatch( ) 清空批处理包的语句
  • Jdbc连接Mysql时,如果要使用批处理功能,需要在url中加参数?rewriteBatchedStatements=true
  • 批处理往往和PerparedStatement一起搭配使用,可以即减少编译次数又减少运行次数,效率大大提高。
@Test
    public void batch() throws SQLException {
        Connection connection = JdbcUtils.getConnection();
        String sql = "insert into admin2 values(null,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        System.out.println("开始:");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            preparedStatement.setString(1,"jack"+i);
            preparedStatement.setString(2,"1"+i);
            //添加批处理操作
            preparedStatement.addBatch();

            if((i + 1) % 1000 == 0){
                //提交
                preparedStatement.executeBatch();
                //清除
                preparedStatement.clearBatch();
            }
        }
        System.out.println("结束:");
        long end = System.currentTimeMillis();
        System.out.println("总用时 :" + (end - start));
        JdbcUtils.close(null,preparedStatement,connection);
    }

数据库连接池

Jdbc的数据库连接池使用javax.sql.DateSource来表示,DateSource只是一个接口,该接口通常由第三方提供实现。

  • 数据库连接池种类
    • C3P0数据库连接池:速度相对较慢,稳定性不错.
    • DBCP数据库连接池:速度相对C3P0较快,但不稳定。
    • Proxool数据库连接池:有监控数据库连接池状态的功能,稳定性较C3P0差一些
    • BoneCP数据库连接池:速度快
    • Druid(德鲁伊)数据库连接池:是由阿里提供的数据库连接池,集DBCP,C3P0,Proxool优点与一身的数据库连接池。

C3P0数据库连接池

添加c3p0-0.9.5.5.jar 和 mchange-commons-java-0.2.19.jar
添加c3p0-config.xml文件

第一种方式连接

  • c3p0-config.xml文件
<c3p0-config>
    <!--使用默认的配置读取数据库连接池对象 -->
    <default-config>
        <!--  连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/website?serverTimezone=Asia/Shanghai</property>
        <property name="user">root</property>
        <property name="password">root</property>

        <!-- 连接池参数 -->
        <!--初始化申请的连接数量-->
        <property name="initialPoolSize">5</property>
        <!--最大的连接数量-->
        <property name="maxPoolSize">10</property>
        <!--超时时间-->
        <property name="checkoutTimeout">3000</property>
    </default-config>

        <named-config name="otherc3p0">
            <!--  连接参数 -->
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/java2023</property>
            <property name="user">root</property>
            <property name="password">root</property>

            <!-- 连接池参数 -->
            <property name="initialPoolSize">5</property>
            <property name="maxPoolSize">8</property>
            <property name="checkoutTimeout">1000</property>
        </named-config>
</c3p0-config>
  • c3p0第一种连接方式(使用mysql.properties)
@Test
    public void test() throws IOException, SQLException, PropertyVetoException {
    //C3P0连接方式
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\mysql.properties"));
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String url = properties.getProperty("url");
        String driver = properties.getProperty("driver");

        comboPooledDataSource.setDriverClass(driver);
        comboPooledDataSource.setUser(user);
       comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setJdbcUrl(url);       comboPooledDataSource.setInitialPoolSize(10);

        comboPooledDataSource.setMaxPoolSize(50);
        long start = System.currentTimeMillis();
        System.out.println("开始:");
        for (int i = 0; i < 5000; i++) {
            Connection connection = comboPooledDataSource.getConnection();
//            System.out.println("连接成功");
            connection.close();
        }
        long end = System.currentTimeMillis();
        System.out.println("结束相差时间:" + (end - start));
    }
  • 第二种方式连接(使用配置文件c3p0-config.xml连接)
  • ComboPooleDateSource() 采用文件中的</default-config>中的内容。
  • ComboPooleDateSource(" otherc3p0 ") 采用配置文件中的<named-config name="otherc3p0">中的内容。
@Test
    public void JdbcUtils_c3p0_02() throws SQLException {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        Connection connection = comboPooledDataSource.getConnection();
        System.out.println("连接方式2成功");
        connection.close();
    }

Druid数据库连接池

  • 添加druid-1.1.0.jar
  • 引入druid.properties配置文件,添加到src目录下
driverClassName=com.mysql.jdbc.Driver
#URL连接数据库的URL,其中travel(以下面例子来说)为连接的数据库,后面的参数可不改但不删
url=jdbc:mysql://localhost:3306/java2023
#?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
characterEncoding=utf-8
#安装mysql时候设置的用户与密码
username=root
password=root
#初始化物理连接的个数
initialSize=5
#最大连接池数量
maxActive=10
#获取连接时最大等待时间
maxWait=3000
#用来检测连接是否有效的sql
validationQuery=SELECT 1
#保证安全性!
testWhileIdle=true

测试连接的代码

    @Test
    public void jdbcDruid_test() throws Exception {
        //加入Druid jar包
        //引入druid的配置文件 ,添加到src目录下
        //创建properties类,读取配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\druid.properties" ));

        //创建一个指定参数的数据库连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        Connection connection = dataSource.getConnection();
        System.out.println("连接成功");
        connection.close();    }

Druid的工具类

public class jdbcUtilsDruid {

    public static DataSource ds;

    static{

        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("src\\druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }


    public static void close(ResultSet resultSet, Statement statement, Connection connection){
        try {
            if(resultSet != null){
                resultSet.close();
            }
            if(statement != null){
                statement.close();
            }
            if (connection != null){
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

DBUtils工具类

  • 使用DBUtils类和接口,先引入DBUtils相关的jar包commons-dbutils-1.8.1.jar
  • 创建QueryRunner()对象来操作
@Test
    public void test() throws SQLException {
        //得到连接
        Connection connection = jdbcUtilsDruid.getConnection();
        //使用DBUtils 类和接口,先引入DBUtils相关的jar
        //创建QueryRunner()对象
        QueryRunner queryRunner = new QueryRunner();

        String sql = "select * from actor where id > ?";

        //就可以执行相关的方法,返回ArrayList结果集
        //query 方法就是执行sql语句,得到resultset ---> 封装到 ---> arrayList 集合中
        //返回集合
        //connection集合
        //sql: 执行sql语句
        //new BeanListHandler<>(Actor.class): 将 resultSet ----> 得到actor对象 -------> 封装到list集合中
        //底层是使用反射机制 去获得Actor 类的属性,然后进行封装
        //1 就是sql语句中的?赋值,可以有多个值,因为是可变参数Object。。。。
        //底层得到的resultSet 和 prepareStatement 会在query结束后进行关闭,不用再关闭了。
        List<actor> execute = queryRunner.query(connection, sql, new BeanListHandler<>(actor.class),1);

        System.out.println("输出结合的信息:");
        for (actor actor:execute) {
            System.out.println(actor);
        }

        jdbcUtilsDruid.close(null,null,connection);
    }

DBUtils来进行DML操作

  • 创建QueryRunner()对象
  • DML操作使用update(conneccion,sql,parameters)方法
    • connection 数据库的连接
    • sql 编写的sql语句
    • parameters是数据库中与处理的字段值
@Test
public int update(String sql, Object... parameters) {
QueryRunner queryRunner = new QueryRunner();
        Connection connection = null;
        try {
            connection = jdbcUtilsDruid.getConnection();
            int update = queryRunner.update(connection, sql, parameters);
            return update;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            jdbcUtilsDruid.close(null, null, connection);
        }
    }

DBUtils来进行DQL操作

查询返回的结果是多条结果

  • 创建QueryRunner()对象
  • DQL操作使用query(conneccion,sql,new BeanListHandler(clazz),parameters)方法
    • connection 数据库的连接
    • sql 编写的sql语句 select * from student where id >= ?
    • new BeanListHandler(clazz) 操作对象的class
    • parameters是数据库中与处理的字段值
@Test
public List<T> queryMulti(String sql, Class<T> clazz, Object... parameter) {
QueryRunner queryRunner = new QueryRunner();
        Connection connection = null;
        try {
            connection = jdbcUtilsDruid.getConnection();
            return queryRunner.query(connection, sql, new BeanListHandler<T>(clazz), parameter);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            jdbcUtilsDruid.close(null, null, connection);
        }
    }
 @Test
    public void testQueryMulti(){
        GoodsDao goodsDao = new GoodsDao();
        String sql = "select * from goods where id >= ?";
        List<Goods> goods = goodsDao.queryMulti(sql, Goods.class,1);
        for (Goods good: goods) {
            System.out.println(good);
        }
    }

返回的结果是一条数据

  • 创建QueryRunner()对象
  • DQL操作使用query(conneccion,sql,new BeanHandler(clazz),parameters)方法
    • connection 数据库的连接
    • sql 编写的sql语句 select * from student where id = ?
    • new BeanListHandler(clazz) 操作对象的class
    • parameters是数据库中与处理的字段值
public T querySingle(String sql, Class<T> clazz, Object... parameters) {
QueryRunner queryRunner = new QueryRunner();
        Connection connection = null;
        try {
            connection = jdbcUtilsDruid.getConnection();
            return queryRunner.query(connection, sql, new BeanHandler<T>(clazz), parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            jdbcUtilsDruid.close(null, null, connection);
        }
    }
@Test
    public void testQuerySingle(){
        GoodsDao goodsDao = new GoodsDao();
        String sql = "select * from goods where id = ?";
        Goods goods = goodsDao.querySingle(sql,Goods.class,1);
        System.out.println(goods);
    }

返回的结果是一个值

  • 创建QueryRunner()对象
  • DQL操作使用query(conneccion,sql,new ScalarHandler(clazz),parameters)方法
    • connection 数据库的连接
    • sql 编写的sql语句 select name from student where id = ?
    • new BeanListHandler(clazz) 操作对象的class
    • parameters是数据库中与处理的字段值
public Object queryScalar(String sql, Object... parameter) {
QueryRunner queryRunner = new QueryRunner();
        Connection connection = null;
        try {
            connection = jdbcUtilsDruid.getConnection();
            Object query = queryRunner.query(connection, sql, new ScalarHandler<>(), parameter);
            return query;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            jdbcUtilsDruid.close(null, null, connection);
        }
    }
@Test
    public void testQueryScalar(){
        GoodsDao goodsDao = new GoodsDao();
        String sql = "select goods_name from goods where id = ?";
        Object o = goodsDao.queryScalar(sql, 1);
        System.out.println(o);
    }

文章还有许多不足之处希望可以提出,有什么问题也可以进行讨论。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值