浅谈数据库连接池

第十章:数据库连接池与DBUtils 一、数据库连接池 1.1 什么是数据库连接池 在使用jdbc编程时,每次访问数据库都需要创建连接对象,访问完毕后也需要断开连接(销毁对象)。 比如说:网站的每日用户访问量是10万次,这时候就需要对数据库访问10万次,需要10万次创建和断开连接对象,频繁的创建和断开连接,这使访问数据库的效率非常低。 数据库连接池技术:管理连接对象。 1.应用程序就不需要创建和断开连接对象,而是交给数据库连接池管理 2.数据库连接池断开,不是销毁对象,而是把连接对象归还给连接池。 数据库连接池基本参数: 1. 阅读详情

池参数(所有池参数都有默认值):

初始大小:10个

最小空闲连接数:3个

增量:一次创建的最小单位(5个)

最大空闲连接数:12个

最大连接数:20个

最大的等待时间:1000毫秒

 

四大连接参数

连接池也是使用四大连接参数来完成创建连接对象!

 

实现的接口

连接池必须实现:javax.sql.DataSource接口!

 

连接池返回的Connection对象,它的close()方法与众不同!调用它的close()不是关闭,而是把连接归还给池!

 

数据库连接池

 

1 数据库连接池的概念

用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。

 

2 JDBC数据库连接池接口(DataSource)

Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

 

3 自定义连接池(ItcastPool)

  分析:ItcastPool需要有一个List,用来保存连接对象。在ItcastPool的构造器中创建5个连接对象放到List中!当用人调用了ItcastPool的getConnection()时,那么就从List拿出一个返回。当List中没有连接可用时,抛出异常。

  我们需要对Connection的close()方法进行增强,所以我们需要自定义ItcastConnection类,对Connection进行装饰!即对close()方法进行增强。因为需要在调用close()方法时把连接“归还”给池,所以ItcastConnection类需要拥有池对象的引用,并且池类还要提供“归还”的方法。

 

ItcastPool.java

public class ItcastPool implements DataSource {

private static Properties props = new Properties();

private List<Connection> list = new ArrayList<Connection>();

static {

InputStream in = ItcastPool.class.getClassLoader()

.getResourceAsStream("dbconfig.properties");

try {

props.load(in);

Class.forName(props.getProperty("driverClassName"));

} catch (Exception e) {

throw new RuntimeException(e);

}

}

 

public ItcastPool() throws SQLException {

for (int i = 0; i < 5; i++) {

Connection con = DriverManager.getConnection(

props.getProperty("url"), props.getProperty("username"),

props.getProperty("password"));

ItcastConnection conWapper = new ItcastConnection(con, this);

list.add(conWapper);

}

}

 

public void add(Connection con) {

list.add(con);

}

 

public Connection getConnection() throws SQLException {

if(list.size() > 0) {

return list.remove(0);

}

throw new SQLException("没连接了");

}

    ......

}

 

ItcastConnection.java

public class ItcastConnection extends ConnectionWrapper {

private ItcastPool pool;

 

public ItcastConnection(Connection con, ItcastPool pool) {

super(con);

this.pool = pool;

}

 

@Override

public void close() throws SQLException {

pool.add(this);

}

}

 

 

DBCP

 

1 什么是DBCP?

DBCP是Apache提供的一款开源免费的数据库连接池!

Hibernate3.0之后不再对DBCP提供支持!因为Hibernate声明DBCP有致命的缺欠!DBCP因为Hibernate的这一毁谤很是生气,并且说自己没有缺欠。

 

2 DBCP的使用

public void fun1() throws SQLException {

BasicDataSource ds = new BasicDataSource();

ds.setUsername("root");

ds.setPassword("123");

ds.setUrl("jdbc:mysql://localhost:3306/mydb1");

ds.setDriverClassName("com.mysql.jdbc.Driver");

 

ds.setMaxActive(20);

ds.setMaxIdle(10);

ds.setInitialSize(10);

ds.setMinIdle(2);

ds.setMaxWait(1000);

 

Connection con = ds.getConnection();

System.out.println(con.getClass().getName());

con.close();

}

 

3 DBCP的配置信息

下面是对DBCP的配置介绍:

#基本配置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/mydb1

username=root

password=123

 

#初始化池大小,即一开始池中就会有10个连接对象

默认值为0

initialSize=0

 

#最大连接数,如果设置maxActive=50时,池中最多可以有50个连接,当然这50个连接中包含被使用的和没被使用的(空闲)

#你是一个包工头,你一共有50个工人,但这50个工人有的当前正在工作,有的正在空闲

#默认值为8,如果设置为非正数,表示没有限制!即无限大

maxActive=8

 

#最大空闲连接

#当设置maxIdle=30时,你是包工头,你允许最多有20个工人空闲,如果现在有30个空闲工人,那么要开除10个

#默认值为8,如果设置为负数,表示没有限制!即无限大

maxIdle=8

 

#最小空闲连接

#如果设置minIdel=5时,如果你的工人只有3个空闲,那么你需要再去招2个回来,保证有5个空闲工人

#默认值为0

minIdle=0

 

#最大等待时间

#当设置maxWait=5000时,现在你的工作都出去工作了,又来了一个工作,需要一个工人。

#这时就要等待有工人回来,如果等待5000毫秒还没回来,那就抛出异常

#没有工人的原因:最多工人数为50,已经有50个工人了,不能再招了,但50人都出去工作了。

#默认值为-1,表示无限期等待,不会抛出异常。

maxWait=-1

 

#连接属性

#就是原来放在url后面的参数,可以使用connectionProperties来指定

#如果已经在url后面指定了,那么就不用在这里指定了。

#useServerPrepStmts=true,MySQL开启预编译功能

#cachePrepStmts=true,MySQL开启缓存PreparedStatement功能,

#prepStmtCacheSize=50,缓存PreparedStatement的上限

#prepStmtCacheSqlLimit=300,当SQL模板长度大于300时,就不再缓存它

connectionProperties=useUnicode=true;characterEncoding=UTF8;useServerPrepStmts=true;cachePrepStmts=true;prepStmtCacheSize=50;prepStmtCacheSqlLimit=300

 

#连接的默认提交方式

#默认值为true

defaultAutoCommit=true

 

#连接是否为只读连接

#Connection有一对方法:setReadOnly(boolean)和isReadOnly()

#如果是只读连接,那么你只能用这个连接来做查询

#指定连接为只读是为了优化!这个优化与并发事务相关!

#如果两个并发事务,对同一行记录做增、删、改操作,是不是一定要隔离它们啊?

#如果两个并发事务,对同一行记录只做查询操作,那么是不是就不用隔离它们了?

#如果没有指定这个属性值,那么是否为只读连接,这就由驱动自己来决定了。即Connection的实现类自己来决定!

defaultReadOnly=false

 

#指定事务的事务隔离级别

#可选值:NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE

#如果没有指定,那么由驱动中的Connection实现类自己来决定

defaultTransactionIsolation=REPEATABLE_READ

 

C3P0

 

1 C3P0简介

C3P0也是开源免费的连接池!C3P0被很多人看好!

 

2 C3P0的使用

C3P0中池类是:ComboPooledDataSource。

public void fun1() throws PropertyVetoException, SQLException {

ComboPooledDataSource ds = new ComboPooledDataSource();

ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb1");

ds.setUser("root");

ds.setPassword("123");

ds.setDriverClass("com.mysql.jdbc.Driver");

 

ds.setAcquireIncrement(5);

ds.setInitialPoolSize(20);

ds.setMinPoolSize(2);

ds.setMaxPoolSize(50);

 

Connection con = ds.getConnection();

System.out.println(con);

con.close();

}

 

配置文件要求:

  1. 文件名称:必须叫c3p0-config.xml
  2. 文件位置:必须在src下

 

 

c3p0也可以指定配置文件,而且配置文件可以是properties,也可骒xml的。当然xml的高级一些了。但是c3p0的配置文件名必须为c3p0-config.xml,并且必须放在类路径下。

<?xml version="1.0" encoding="UTF-8"?>

<c3p0-config>

<default-config>

<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>

<property name="driverClass">com.mysql.jdbc.Driver</property>

<property name="user">root</property>

<property name="password">123</property>

<property name="acquireIncrement">3</property>

<property name="initialPoolSize">10</property>

<property name="minPoolSize">2</property>

<property name="maxPoolSize">10</property>

</default-config>

<named-config name="oracle-config">

<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>

<property name="driverClass">com.mysql.jdbc.Driver</property>

<property name="user">root</property>

<property name="password">123</property>

<property name="acquireIncrement">3</property>

<property name="initialPoolSize">10</property>

<property name="minPoolSize">2</property>

<property name="maxPoolSize">10</property>

</named-config>

</c3p0-config>

 

c3p0的配置文件中可以配置多个连接信息,可以给每个配置起个名字,这样可以方便的通过配置名称来切换配置信息。上面文件中默认配置为mysql的配置,名为oracle-config的配置也是mysql的配置,呵呵。

public void fun2() throws PropertyVetoException, SQLException {

ComboPooledDataSource ds = new ComboPooledDataSource();

Connection con = ds.getConnection();

System.out.println(con);

con.close();

}

public void fun2() throws PropertyVetoException, SQLException {

ComboPooledDataSource ds = new ComboPooledDataSource("orcale-config");

Connection con = ds.getConnection();

System.out.println(con);

con.close();

}

 

Tomcat配置连接池

 

1 Tomcat配置JNDI资源

JNDI(Java Naming and Directory Interface),Java命名和目录接口。JNDI的作用就是:在服务器上配置资源,然后通过统一的方式来获取配置的资源。

我们这里要配置的资源当然是连接池了,这样项目中就可以通过统一的方式来获取连接池对象了。

配置JNDI资源需要到<Context>元素中配置<Resource>子元素:

  1. name:指定资源的名称,这个名称可以随便给,在获取资源时需要这个名称;
  2. factory:用来创建资源的工厂,这个值基本上是固定的,不用修改;
  3. type:资源的类型,我们要给出的类型当然是我们连接池的类型了;
  4. bar:表示资源的属性,如果资源存在名为bar的属性,那么就配置bar的值。对于DBCP连接池而言,你需要配置的不是bar,因为它没有bar这个属性,而是应该去配置url、username等属性。

 

<Context>  

  <Resource name="mydbcp"

type="org.apache.tomcat.dbcp.dbcp.BasicDataSource"

factory="org.apache.naming.factory.BeanFactory"

username="root"

password="123"

driverClassName="com.mysql.jdbc.Driver"    

url="jdbc:mysql://127.0.0.1/mydb1"

maxIdle="3"

maxWait="5000"

maxActive="5"

initialSize="3"/>

</Context>  

<Context>  

  <Resource name="myc3p0"

type="com.mchange.v2.c3p0.ComboPooledDataSource"

factory="org.apache.naming.factory.BeanFactory"

user="root"

password="123"

classDriver="com.mysql.jdbc.Driver"    

jdbcUrl="jdbc:mysql://127.0.0.1/mydb1"

maxPoolSize="20"

minPoolSize ="5"

initialPoolSize="10"

acquireIncrement="2"/>

</Context>  

 

2 获取资源

  配置资源的目的当然是为了获取资源了。只要你启动了Tomcat,那么就可以在项目中任何类中通过JNDI获取资源的方式来获取资源了。

获取资源:

  1. Context:javax.naming.Context;
  2. InitialContext:javax.naming.InitialContext;
  3. lookup(String):获取资源的方法,其中”java:comp/env”是资源的入口(这是固定的名称),获取过来的还是一个Context,这说明需要在获取到的Context上进一步进行获取。”bean/MyBeanFactory”对应<Resource>中配置的name值,这回获取的就是资源对象了。

 

        Context cxt = new InitialContext();

        DataSource ds = (DataSource)cxt.lookup("java:/comp/env/mydbcp");

        Connection con = ds.getConnection();

        System.out.println(con);

        con.close();

        Context cxt = new InitialContext();

            Context envCxt = (Context)cxt.lookup("java:/comp/env");

        DataSource ds = (DataSource)env.lookup("mydbcp");

        Connection con = ds.getConnection();

        System.out.println(con);

        con.close();

上面两种方式是相同的效果。

Mysql-数据库优化-连接参数 这个参数是管理连接池数量的,和线程池的思想一样,spring.datasource.druid.min-idle这个相当于核心线程数,无论怎样连接池始终保持这么多的连接数量。数据库连接池化的思想也就是提前将连接创建好并保存用的时候直接拿来用,同时要进行管理,也就有了上面这些相关的参数,如果不适用池化的思想,数据库会有一个最大的连接数,如果超过这个最大连接数,数据库直接无法处客户端的查询请求。可以看到一旦达到最大连接数就会报错,异常比例是相当高的,但是使用连接池就不会有这种大量报错的现象。 阅读详情

相关推荐

高并发服务优化篇:浅谈数据库连接池

被N多大号转载的一篇优快云博客,引起了我的注意,说的是数据库连接池使用threadlocal的原因,文中结论如下图所示。来自优快云的一篇文章,被很多号转载过姑且不谈threadlocal的作用和工作原理,单说数据库连接池这个知识点,猛地一看挺有理;仔细一看,怎么感觉不太对啊,同学,这是什么虎狼之词。$ 实践是检验真理的唯一标准个人理解,连接池提供的获取连接的能力,需要对"任务"唯一,即,只有当某一线程完成了本次数据操作,将连接放回到连接池之后,其他线程才能够再次获取并使用。原因我们后面细说,先

无 1295

MySQL 笔记二(连接池的简要介绍)

文章目录简要原理优点注意要点1. 连接池中到底应该放置多少连接,才能使系统的性能最佳?2. 如何确保连接池中的最小连接数呢?dbcp参数设置c3p0c3p0与dbcp区别python-SQLalchemy使用用法参数设置 原文: https://www.cnblogs.com/aspirant/p/6747238.html 简要 最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库...

hea_gui_lion的博客 979

干扰管理学习日志4-------信道估计方法 LS(最小二乘)、MMSE(最小均方误差)

信道估计,就是从接收数据中将假定的某个信道模型的模型参数估计出来的过程。如果信道是线性的话,那么信道估计就是对系统冲激响应进行估计。需强调的是信道估计是信道对输入信号影响的一种数学表示,而“好”的信道估计则是使得某种估计误差最小化的估计算法。本文主要讲述非盲信道估计中的LS估计和MMSE估计。LS全称为,即估计的信道参数与实际信道参数的差,进行平方求和后得到的误差累积最小。MMSE估计是LS估计的改进,在LS估计的最终结果的基础上乘以加权矩阵,使之与实际信道参数更为接近。

taiyuezyh的博客 1万+

常用的 Druid 参数

Druid 是一个功能强大的连接池,支持众多的参数配置,以下是一些常用的 Druid 参数

洪晓鸿 3442

【电机控制入门】——电机控制书籍推荐

电机控制入门书籍推荐及分享 阅读须知: 1.电机控制的入门是涉及到机械、电子与控制等复杂交叉学习,它需要持续投入时间才可以看到学习的效果,如同“一万小时定律”。俗话说,九层之台,起于垒土,因此电机控制入门没有所谓的速成培训班。相反,还需要夯实好一定的基础。为此,博主建议从基础理论抓起,故推荐相关的书籍并分享给大家。 2.学习电机贵在动手实践,无论是借助于MATLAB/Simulink仿真平台来验证理论分析,或是使用板子对所设计的控制系统进行物理实现,博主极力推荐在一定基础(看完部分以下推荐的书籍),一边动手

昔时扬尘处 3万+

合成孔径雷达Chirp Scaling(CS)算法MATLAB仿真实现

本人也是初学《合成孔径雷达成像算法与实现》,在GitHub上下载的关于CS算法的代码,仔细读了读,发现中间有一些不合理之处,动手改了一改,重新写了一个代码供初学者学习,有什么问题留言即可。 非常感谢源代码的作者,虽然中间有少许不正确的地方,但是对我理解cs算法的帮助非常大,非常感谢!!! 代码中提到的(4.31)这种均是在《合成孔径雷达成像算法与实现》中的公式 以下是MATLAB的仿真程序,直接复...

weixin_41700188的博客 7851

数据库连接池参数

数据库连接池参数

weixin_44121790的博客 2005

深度学习之Pytorch---本人踩过的坑(报错总结)第十篇

深度学习之Pytorch安装时遇到的问题—本人踩过的坑(报错总结) 报错一:pip install torchvision 出现“由于目标计算机积极拒绝,无法连接”的问题 解决方案:找到自己浏览器的工具或选项,我的是火狐,具体解决方案如下图 然后找到桌面左下角,点击搜索internet,然后点击internet选项 最后回到Anaconda Prompt命令行输入pip install...

qq_41570307的博客 1914

浅谈JDBC和数据库连接池

浅谈JDBC和数据库连接池 一、JDBC的概念 JDBC,全称"Java Database Connectivity",意为"java与数据库的连接",是java中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。jdbc接口的具体方法由各大数据库厂商去实现,即数据库驱动,开发人员无需理会具体实现方法,只需学会调用相应接口的方法即可。 要使用jdbc,需要导入相应数据库的驱动包 二、JDBC使用步骤 导入要操作的数据库的驱动包 加载、注册数据库驱动(以m

weixin_46210148的博客 402

RabbitMQ的使用(JAVA)

Java快速上手的MQ上线!

.............. 1万+

基于STM32F103C8T6的红外循迹避障小车

编程思路:控制核心板IO口的电平(即电机驱动模块的AIN1,AIN2,BIN1,BIN2)从而控制AO1、AO2、BO1、BO2的电平高低,进而控制电机使其正转、反转、不转。由于单纯地拉高拉低电平只能让电机在转与不转的状态切换,故决定利用TIM4的两个通道分别产生两路PWM信号来控制电机速度,四个电机两个一组,同一侧的两个连接在同一个PWM上。(#include "dianji.h"文件中同时写了对循迹模块引脚的初始化)

weixin_48743503的博客 1万+

mysql连接池_浅谈数据库连接池

DB的连接模式及优缺点应用程序对DB的连接,分为两种模式:短连接直连: 应用程序在操作DB的时候,新建DB连接,SQL操作完毕后,关闭连接。连接池: 应用程序在启动时,由连接池组件预先按照配置的规则,缓存一定量的DB连接,程序在操作DB的时候,从连接池获取一个连接,SQL操作完毕后,将连接放回到连接池。各自优缺点:连接模式优点不足短连接直连对DB异常感知能力强1.影响应用并发...

weixin_39543758的博客 263

机器学习 线性回归 头歌实训

第1关:简单线性回归与多元线性回归 第2关:线性回归的正规方程解 第3关:衡量线性回归的性能指标 第4关:scikit-learn线性回归实践 - 波斯顿房价预测

weixin_57270536的博客 1万+

浅谈数据库连接池原理及优势

连接池的工作原理主要由三部分组成,分别为 第一、连接池的建立。   一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。 Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。 第二、连接池的管理。   连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是: 当客户请求数据库连接时,首先查看连接...

C99965的博客 1077

EuROC 数据集格式及相关代码

Euroc提供ROS和zip两种数据格式。

~勿据散客~的博客 2093

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

浅谈各种数据库连接池

1.各种数据库连接池 开源的免费连接池: DBCP C3P0 Proxool Druid Jakarta DDConnectionBroker BoneCP XAPool Primrose SmartPool MiniConnectionPoolManager 商业的中间件连接池: weblogic的连接池...

weixin_30807677的博客 177

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

浅谈DBCP、C3P0数据库连接池技术

连接池: (1)传统JDBC: ①Class.forName() //加载驱动 ②Connection conn = DriverManager.getConnection(uri,user,pwd); //此方法的连接指向数据库 ③PreparedStatement pstmt = conn.preparedStatement(); ...

李公子的博客 367

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

浅谈tomcat的配置及数据库连接池的配置

1.如何修改tomcat的端口 在某些情况下,可能需要修改tomcat监听的端口8080,比如: a.需要启动两份tomcat服务器 b.某个服务占用了8080端口(1433,1521,3306...) Windows查看端口使用命令:netstat -an 修改tomcat端口的方法: 修改~tommcat/conf/server.xml文件中port="8080"数据将8080修改

徐守威 2339

浅谈Sqlsession和数据库的连接池

之前mybatis关于Sqlsession的事务的提交,有很多的不解,通过这两天的努力,大致了解了下,分享下,也顺便总结下: 其实我们早就应该知道,在使用mybatis的时候,事务提交的时候,每次,我们都会调用SqlSession来进行事务的提交,提交完成后,也进行了手动的关闭操作;不难理解,这个似乎和JDBC在操作数据的时候,大家经常写的 BaseDao一样,也就是,在操作JDBC的时

mostlove 1万+

浅谈JSP数据库连接池的必要性

最近我作了JSP数据库的频繁连接,在此给出数据库连接池的必要性,对于JSP来说一个很好的J2EE服务器是很必要的,JBOOS,WebLogic都是很好的解决方案。 <br /> <br />一般情况下,在使用开发基于数据库的WEB程序时,传统的模式基本是按以下步骤:<br />1. 在主程序(如Servlet、Beans)中建立数据库连接。 <br />2. 进行SQL操作,取出数据。<br />3. 断开数据库连接。<br />使用这种模式开发,存在很多问题。首先,我们要为每一次WEB请求(例如察看

jianpingdu2009的专栏 338

浅谈数据库连接池(一)

一.DBCP (Database Connection Pool)     是一个依赖Jakarta commons-pool对象池机制的数据库连接池,Tomcat的数据源使用的就是DBCP。目前 DBCP 有两个版本分别是 1.3 和 1.4。1.3 版本对应的是 JDK 1.4-1.5 和 JDBC 3,而1.4 版本对应 JDK 1.6 和 JDBC 4。因此在选择版本的时候要看看你用的是...

兵哥LOVE坤 581
上一篇: 初识数据库事务
下一篇: 读《软件测试的艺术》笔记-草稿
MoveFlower
博客等级 码龄10年 23粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值