struts2+hibernate3+spring2读书笔记11(Hibernate查询)

[b] [size=large]第12章 Hibernate查询[/size][/b]

[b]本章导读语
数据库查询是数据库最常用的一种,Hibernate提供了HQL来进行数据库查询,另外还提供条件查询(Criteria Queries)SQL查询和连接查询等方式[/b]


[b][size=large]一. Hibernate查询语言:HQL[/size][/b]

[b]1. HQL概述[/b]
(1) 大小写敏感问题
在HQL语言中,java类和属性的名称是大小写敏感的,但是select ,from,group by ,order 和where等查询关键字大小写不敏感。
(2) from 子名
在SQL语句中,from后紧跟表的名称,而在HQL中,from后跟随的是实体的名称,如:from user

(3) select 子句
select 子句将哪些属性或将哪些对象放入醒询的结果集中,如:select user.username,user.password from User as user

(4) where子句
该子句用于限定的查询条件 如:from User where username=’amigo’

(5) order by 子句
该子句是用于按照类中的任何属性进行升序或降序的排序,如:from User as user order by user.age desc
(6) group by 子句
该子句用于分组查询,如:select user.age from User as user group by user.loginTimes
(7) 聚集函数
在HQL语句中,支持如下聚集函数:
Avg():求平均值。
Sum():求和。
Max():求最大值。
Min():求最小值。
Count();求记录数。
(8) 子查询
HQL语句也支持子查询,如:from User as user where user.age>(select avg(obj.age) from User as obj)
(8) join子句
在HQL语句中,支持如下的join子句
Inner join :内连接,inner join
Left outer join:左外连接
Right outer join:右外连接
Full join:全连接


[b]2.参数绑定[/b]

(1) 通过顺序位符“?”来填充参数
在HQL语句中,可使用顺序占位符“?”来填充参数信息。

例如:

  Query query = session.createQuery(“from User user where user.username like ? and user.age>?”);
Query.setParameter(0,”%amigo%”);
Query.setParameter(1,new Integer(25));
List userList=query.list();

(2)通过占位符“:”来填充参数 例如:

Query query= seesion.createQuery(“from User user where user.username like:username and user.age>:age”);
query.setParameter(“username”,”%amigo%”);
query.setParameter(“age”,new Integer(25));
List userList=query.list();

(3)分页查询 例如:
Query query = session.createQuery(“from User user”);
query.setFirstResult(0);
query.setFirstResult(5);
List userList = query.list();



[b]3. 查询实例[/b]
(1) 建立工程


(2) 创建数据库

CREATE DATABASE `hibernatequery` /*!40100 DEFAULT CHARACTER SET gb2312 */;
USE `hibernatequery`;

CREATE TABLE `tbl_dept` (
`deptId` int(11) NOT NULL auto_increment COMMENT '部门id',
`deptName` varchar(50) default NULL COMMENT '部门名称',
PRIMARY KEY (`deptId`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 COMMENT='部门信息表';

INSERT INTO `tbl_dept` (`deptId`,`deptName`) VALUES (1,'软件研发部');

CREATE TABLE `tbl_user` (
`userid` int(11) NOT NULL auto_increment COMMENT '用户id',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(50) NOT NULL COMMENT '密码',
`loginTimes` int(11) NOT NULL default '0' COMMENT '登录次数',
`createTime` datetime default NULL COMMENT '创建时间',
`deptId` int(11) default NULL COMMENT '所属部门',
PRIMARY KEY (`userid`),
KEY `deptId` (`deptId`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312 COMMENT='用户信息表';

INSERT INTO `tbl_user` (`userid`,`username`,`password`,`loginTimes`,`createTime`,`deptId`) VALUES (1,'amigo','1111',2,'2008-09-15 12:00:00',1);
INSERT INTO `tbl_user` (`userid`,`username`,`password`,`loginTimes`,`createTime`,`deptId`) VALUES (2,'xiexx','2222',5,'2008-09-15 13:05:00',1);
INSERT INTO `tbl_user` (`userid`,`username`,`password`,`loginTimes`,`createTime`,`deptId`) VALUES (3,'test','3333',3,'2008-09-15 12:40:30',1);
INSERT INTO `tbl_user` (`userid`,`username`,`password`,`loginTimes`,`createTime`,`deptId`) VALUES (4,'test4','4444',2,'2008-09-15 14:00:00',1);

ALTER TABLE `tbl_user`
ADD FOREIGN KEY (`deptId`) REFERENCES `tbl_dept` (`deptId`);

(3) 编写Hibernate配置文件:hibernate.cfg.xml

 <?xml version='1.0' encoding='UTF-8'?>      
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 在后台打印sql语句 -->
<property name="show_sql">true</property>
<!-- 指定sql的本地方言,根据连接的数据库确定-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 指定jdbc url,MySql的默认端口为3306,localhost为需要连接的主机,testhibernate为连接的数据库 -->
<property name="connection.url">jdbc:mysql://localhost:3306/hibernatequery</property>
<!-- 数据库的用户名 -->
<property name="connection.username">root</property>
<!-- 数据库的密码 -->
<property name="connection.password"></property>
<!-- 设定数据库的驱动类,MySql的驱动jar包为mysql-connector-java-5.0.4-bin.jar,驱动类为com.mysql.jdbc.Driver -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>


<!--指定0到多个hbm.xml映射文件-->
<mapping resource="amigo/hibernate/query/User.hbm.xml" />
<mapping resource="amigo/hibernate/query/Dept.hbm.xml" />
</session-factory>
</hibernate-configuration>



(4) 编写Hibernate映射文件:Dept.hbm.xml和Dept.java

Dept.java类的代码如下:

         package amigo.hibernate.query;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Dept implements Serializable {
private static final long serialVersionUID=1L;

/**部门id(自增)*/
private java.lang.Integer deptId;
/**部门名称*/
private java.lang.String deptName;
/**该部门关联的用户对象*/
private Set<User> users = new HashSet<User>();
public java.lang.Integer getDeptId() {
return deptId;
}
public void setDeptId(java.lang.Integer deptId) {
this.deptId = deptId;
}
public java.lang.String getDeptName() {
return deptName;
}
public void setDeptName(java.lang.String deptName) {
this.deptName = deptName;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}


映射文件Dept.hbm.xml的内容如下:

<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="amigo.hibernate.query">
<class name="Dept" table="tbl_dept">
<id name="deptId" column="deptId" type="java.lang.Integer">
<generator class="native"/>
</id>

<property name="deptName" column="deptName" type="java.lang.String" not-null="true"/>

<set name="users" cascade="save-update">
<key>
<column name="deptId"></column>
</key>
<one-to-many class="User"/>
</set>

</class>
</hibernate-mapping>


(5)编写Hibernate映射文件:User.hbm.xml和User.java

User.java类的代码如下:

package amigo.hibernate.query;

import java.io.Serializable;
import java.util.Date;


/**用户信息的POJO类*/
public class User implements Serializable {
private static final long serialVersionUID=1L;

/**用户id*/
private Integer userid;

/**用户名*/
private java.lang.String username;

/**密码*/
private java.lang.String password;
/**登录次数*/
private Integer loginTimes;

/**创建时间*/
private Date createTime;

/**部门*/
private Dept dept;

public Integer getUserid() {
return userid;
}

public void setUserid(Integer userid) {
this.userid = userid;
}

public java.lang.String getUsername() {
return username;
}

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

public java.lang.String getPassword() {
return password;
}

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

public Integer getLoginTimes() {
return loginTimes;
}

public void setLoginTimes(Integer loginTimes) {
this.loginTimes = loginTimes;
}

public Date getCreateTime() {
return createTime;
}

public void setCreateTime(Date createTime) {
this.createTime = createTime;
}

public Dept getDept() {
return dept;
}

public void setDept(Dept dept) {
this.dept = dept;
}



}


映射文件User.hbm.xml的内容如下:


 <?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="amigo.hibernate.query">
<class name="User" table="tbl_user">
<id name="userid" column="userid" type="java.lang.Integer">
<generator class="native"/>
</id>

<property name="username" column="username" type="java.lang.String" not-null="true"/>
<property name="password" column="password" type="java.lang.String" not-null="true"/>
<property name="loginTimes" column="loginTimes" type="java.lang.Integer" not-null="true"/>
<property name="createTime" column="createTime" type="java.util.Date" not-null="true"/>


<many-to-one name="Dept" column="deptId" class="Dept" />

</class>
</hibernate-mapping>


(6)编写Session工厂类:HibernateSessionFactory.java(该类提供获得当前Session和关闭Session的方法)

 package amigo.hibernate.query;   

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.apache.log4j.*;
/**
* Hibernate的session获取类.
* */
public class HibernateSessionFactory {

public static Logger log=(Logger)Logger.getLogger(HibernateSessionFactory.class);
private static SessionFactory sessionFactory;

/**持有一个单态的Session实例.*/
private static final ThreadLocal threadLocal=new ThreadLocal();

/**持有一个单态的configuration实例.*/
private static final Configuration cfg=new Configuration();

private static String CONFIG_FILE_LOCATION="/hibernate.cfg.xml";



/**
* 获得当前的Session实例
* */
public static Session currentSession() throws HibernateException{
Session session = (Session)threadLocal.get();
if(session==null||session.isOpen()==false){
if(sessionFactory==null){
try{
cfg.configure(CONFIG_FILE_LOCATION);
sessionFactory=cfg.buildSessionFactory();
}
catch(Exception e){
log.error(e);
log.error("Error Creating SessionFactory%%%%"+session.isOpen());

}
}
session=sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
/**关闭session*/
public static void closeSession() throws HibernateException{
Session session=(Session) threadLocal.get();
threadLocal.set(null);
if(session !=null){
session.close();

}
}
private HibernateSessionFactory(){

}

}

(7)编写HQL查询测试类:HqlTest.java

package amigo.hibernate.query.hql;

import java.util.List;
import org.hibernate.Query;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import amigo.hibernate.query.User;
import amigo.hibernate.query.HibernateSessionFactory;


/**hql语句使用实例*/
public class HqlTest {
private static Logger log=Logger.getLogger(HqlTest.class);

public static void main(String[] args)throws Exception{
Session session =HibernateSessionFactory.currentSession();

log.info("=========查询所有数据,最简单的hql============");
List allUserList=session.createQuery("from User").list();
printUserInfo(allUserList);

log.info("=========带有where查询子句的HQL,查询用户名为amigo的信息============");
List userList=session.createQuery("from User as user where user.username='amigo'").list();
printUserInfo(userList);

log.info("=========带有select子句的HQL查询用户的username和loginTimes信息================");
List userProList=session.createQuery("select user.username,user.loginTimes from User as user").list();
for(int i=0;i<userProList.size();i++){
Object[] array=(Object[])userProList.get(i);
String username=(String)array[0];
Integer loginTimes=(Integer)array[1];
log.info("i="+i+",username="+username+",loginTimes="+loginTimes);
}


log.info("=========带有order by 子句的HQL,按照loginTimes进行降序排序================");
List userOrderByList = session.createQuery("from User as user order by loginTimes desc").list();
printUserInfo(userOrderByList);

log.info("=========带有group by 子句的HQL,按照loginTimes进行分组================");
List userGroupByList = session.createQuery("select user.loginTimes,count(user.loginTimes),max(user.loginTimes)"+"from User as user group by user.loginTimes").list();
for(int i=0;i<userGroupByList.size();i++){
Object[] array = (Object[])userGroupByList.get(i);
Integer loginTimes = (Integer) array[0];
Long countLoginTimes = (Long) array[1];
Integer maxLoginTimes=(Integer)array[2];

log.info("i="+i+",loginTimes="+loginTimes+",countLoginTimes="+countLoginTimes+",maxLoginTimes="+maxLoginTimes);
}

log.info("=========带有子查询的HQL,查询登录次数大于平均登录次数的记录================");
List userSubQueryList = session.createQuery("from User as user where user.loginTimes>"+"(select avg(obj.loginTimes)from User as obj)").list();
printUserInfo(userSubQueryList);

log.info("=========通过顺序占位符'?'来填充参数,查询用户名中含有test,并且loginTimes大于2的记录========");
Query query1=session.createQuery("from User as user where user.username like ? and user.loginTimes > ? ");
query1.setParameter(0,"%test%");
query1.setParameter(1, new Integer(2));
List userlist = query1.list();
printUserInfo(userlist);


log.info("=========通过顺序占位符':'来填充参数,查询用户名中含有test,并且loginTimes大于2的记录========");
Query query2=session.createQuery("from User as user where user.username like :username and user.loginTimes > :loginTimes ");
query2.setParameter("username","%test%");
query2.setParameter("loginTimes", new Integer(2));
List userlist2 = query2.list();
printUserInfo(userlist2);

log.info("==========分页查询,查询两条记录=============");
Query query3=session.createQuery("from User user");
query3.setFirstResult(0);
query3.setMaxResults(2);
List userlist3 = query3.list();
printUserInfo(userlist3);

//关闭session
HibernateSessionFactory.closeSession();

}
public static void printUserInfo(List userList)throws Exception{
for(int i=0;i<userList.size();i++){
User user =(User)userList.get(i);
log.info("i="+i+",username="+user.getUsername()+",password="+user.getPassword()+",loginTimes="+user.getLoginTimes()+",dept="+user.getDept().getDeptName());
}

}


}



[b][size=large]二. 条件查询(Criteria Queries)[/size][/b]

实例需求:采用HQL查询语言进行查询时是,需要定义HQL查询语句,条件查询(Criteria Queries)提供了另一种查询方式,它直观而且具有可扩展性,它主要由Criteria接口、Criterion接口和Expression类组成

(1) 条件查询概述
Org.hibernate.Criteria 接口是条件查询的核心接口,它表示特定持久类的一个查询,其创建方法如下:
Criteria criteria = session.createCriteria(User.class);

若要限定查询条件,可使用Criterion添加查询限制。例如需要查询username中含有test,并且loginTimes大小于2的用户记录:

Criteria criteria2 = session.createCriteria(User.class);
//限定查询条件
Criterion criterion1 = Expression.like("username","%test%");
Criterion criterion2 = Expression.gt("loginTimes", new Integer(2));
criteria2.add(criterion1);
criteria2.add(criterion2);
List userList = criteria2.list();


Org.hibernate.criterion.Expression类定义了某些内置的Criterion类型的工厂方法,它提供等于(eq(…))、大于(gt(…))、模糊匹配(like(…))、或(or)、为空(isNull(…))等方法。


如果对结果集进行排序,可使用一个或多个addOrder(…)方法添加排序的列,例如若要首先按照loginTimes降序排列,而后按照creatTime升序排列

Criteria criteria3 = session.createCriteria(User.class);
criteria3.addOrder(Order.desc("loginTimes"));
criteria3.addOrder(Order.asc("createTime"));
List userList3 = criteria3.list();


Criteria接口提供了setFirstResult()方法来设置需要取和第一条记录,setMaxResults()方法用于设置最多取得的记录数,例如如下语句获得从第6条记录开始一10条记录


Criteria criteria4 = session.createCriteria(User.class);
criteria4.setFirstResult(5);
criteria4.setMaxResults(10);
List userList4 = criteria4.list();


(2) 编写条件查询测试类:CriteriaTest.java

 package amigo.hibernate.query.criteria;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;

import amigo.hibernate.query.HibernateSessionFactory;
import amigo.hibernate.query.User;

public class CriteriaTest {
private static Logger log = Logger.getLogger(CriteriaTest.class);

public static void main(String[] args) throws Exception{
Session session = HibernateSessionFactory.currentSession();

log.info("=========查询所有用户记录===========");
Criteria criteria1 = session.createCriteria(User.class);
List allUserList= criteria1.list();
printUserInfo(allUserList);

log.info("=========查询username中含有test,则loginTimes大于2的记录===========");
Criteria criteria2 = session.createCriteria(User.class);
//限定查询条件
Criterion criterion1 = Expression.like("username","%test%");
Criterion criterion2 = Expression.gt("loginTimes", new Integer(2));
criteria2.add(criterion1);
criteria2.add(criterion2);
List userList = criteria2.list();
printUserInfo(userList);

log.info("=========添加排序,首先按照loginTimes降序,然后按照createTime升序==========");
Criteria criteria3 = session.createCriteria(User.class);
criteria3.addOrder(Order.desc("loginTimes"));
criteria3.addOrder(Order.asc("createTime"));
List userList3 = criteria3.list();
printUserInfo(userList3);

log.info("==========分页查询,查出从2(第3条开始)的第2条数据=========");
Criteria criteria4 = session.createCriteria(User.class);
criteria4.setFirstResult(3);
criteria4.setMaxResults(2);
List userList4 = criteria4.list();
printUserInfo(userList4);

//关闭Session
HibernateSessionFactory.closeSession();
}

public static void printUserInfo(List userList) throws Exception{
for(int i=0;i<userList.size();i++){
User user = (User)userList.get(i);
log.info("i="+i+",username="+user.getUsername()+",password="+user.getPassword()+",loginTimes="+user.getLoginTimes());
}

}

}


[b][size=large]三. SQL查询[/size][/b]

采用HQL和条件查询(Criteria Queries)进行查询时,Hibernate会生成适用于各种数据库平台的标准的SQL查询语句,这两种检索方式是跨平台的,但是有些应用程序需要数据库底层的数据库方言来执行一些特的或复杂的SQL语句,对于此种情况,Hibernate的Sessiono接口提供了createSQLQuery()方法来执行本地的SQL语句。

[b]1. 相关的说明[/b]

Session接口的createSQLQuery()方法返回一个SQLQuery查询,该类继承org.hibernate.Query类,因此具有该类
setParamenter(String arg0,String arg1) 方法可设置占位符参数的信息,而使用该类的addEntity(String arg0,Class arg1)方法设置查询返回的实体

SqlTest.java代码如下:

package amigo.hibernate.query.sql;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.SQLQuery;
import org.hibernate.Session;

import amigo.hibernate.query.HibernateSessionFactory;
import amigo.hibernate.query.User;

public class SqlTest {
private static Logger log = Logger.getLogger(SqlTest.class);
public static void main(String[] args)throws Exception{
Session session = HibernateSessionFactory.currentSession();
log.info("==========查询所有记录==============");
SQLQuery query = session.createSQLQuery("select * from tbl_user as user");
query.addEntity("user",User.class);
List userList = query.list();
printUserInfo(userList);

log.info("==========查询username字段中包括test,且loginTimes大于2的记录==============");
SQLQuery query1=session.createSQLQuery("select * from tbl_user as user where username like :username and loginTimes>:loginTimes");
query1.setParameter("username","%test%");
query1.setParameter("loginTimes", new Integer(2));
query1.addEntity("user",User.class);
List userList1= query1.list();
printUserInfo(userList1);


log.info("==========查询username字段中包括test,且loginTimes大于2的记录 的另一种写法==============");
SQLQuery query2=session.createSQLQuery("select userid as {user.userid},username as {user.username} from tbl_user as user where username like :username and loginTimes>:loginTimes");
query2.setParameter("username","%test%");
query2.setParameter("loginTimes", new Integer(2));
query2.addEntity("user",User.class);
List userList2= query2.list();
printUserInfo(userList2);


log.info("===============分页查询,查询从第2条记录开始的5条记录========");
SQLQuery query3 = session.createSQLQuery("select * from tbl_user as user");
query3.setFirstResult(3);
query3.setMaxResults(5);
query3.addEntity("user",User.class);
List userList3 = query3.list();
printUserInfo(userList3);

//关闭session
HibernateSessionFactory.closeSession();

}

public static void printUserInfo(List userList) throws Exception{
for(int i=0;i<userList.size();i++){
User user = (User)userList.get(i);
log.info("i="+i+",username="+user.getUsername()+",password="+user.getPassword()+",loginTimes="+user.getLoginTimes());
}

}
}


[b][size=large]四. 连接查询[/size][/b]

[b]1. 检索策略说明[/b]
在进行关联时,Hibernate中有如下3种检索策略:
(1) 立即检索:立即加载和检索指定的对象关联的对象。
(2) 延迟检索:延迟加载和检索指定的对象关联的对象。
(3) 迫切左外连接检索:通过左外连接加载和检索指定对象关联的对象。

在存在关联的Hibernate映射文件中,可使用如下属性设定检索策略:

(4) lazy:值可为true或false,默认为false,用于是否使用延迟加载策略,为true表示使用延迟,为false,表示立即加载。
(5) outer-join:值可为outo,false,true.在<set/>元素中,默认值为false,在<one-to-one/>和<many-to-many/>元素中默认值为auto。true表示使用迫切左外连接检索,false表示不使用。
(6) batch-size:该属性用于设置批量检索的数量,默认值为1,参考的合理值为3-10

[b]2. 编写连接查询测试类:JoinTest.java[/b]

  package amigo.hibernate.query.join;

import org.apache.log4j.Logger;
import org.hibernate.Session;

import amigo.hibernate.query.Dept;
import amigo.hibernate.query.HibernateSessionFactory;
import amigo.hibernate.query.User;

/**
* 连接查询测试类.
*
*/
public class JoinTest {
private static Logger log = Logger.getLogger(JoinTest.class);

public static void main(String[] args) throws Exception {
Session session = HibernateSessionFactory.currentSession();

// 使用load()方法加载deptId为1的部门信息
// Dept dept = (Dept) session.load(Dept.class, new Integer(1));

User user = (User) session.get(User.class, new Integer(1));
// 关闭Session
HibernateSessionFactory.closeSession();
}
}


其中Dept.hbm.xml的代码如下:

<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="amigo.hibernate.query">
<class name="Dept" table="tbl_dept" lazy="false">
<id name="deptId" column="deptId" type="java.lang.Integer">
<generator class="native"/>
</id>
<property name="deptName" column="deptName" type="java.lang.String" not-null="true" />
<set name="users" cascade ="save-update" lazy="false" outer-join="true">
<key>
<column name="deptId" />
</key>
<one-to-many class="User" />
</set>
</class>
</hibernate-mapping>

(1) 在Dept.hbm.xml中的<class/>中,lazy完素设置为false,表示立即加载
(2) 在Dept.hbm.xml中的<set/>中设定outer-join=”true”,表示使用迫切左外连接检索。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值