Spring Boot整合Spring Data JPA

本文介绍了如何在Spring Boot 2.2.6.RELEASE中使用Spring Data JPA进行数据操作。内容涵盖配置数据库连接、创建实体类和数据交互层接口,以及讲解了Repository、CrudRepository、PagingAndSortingRepository、JpaRepository和JpaSpecificationExecutor等核心接口的使用,包括命名查询、自定义查询和多条件分页查询。同时,文章还详细阐述了如何建立双向一对一、一对多和多对多的关系映射。
摘要由CSDN通过智能技术生成

首先说明一下,这里使用的是Springboot2.2.6.RELEASE版本,由于Springboot迭代很快,所以要注意版本问题。

1、Spring Data是Spring提供的帮助操作数据的框架,Spring Data中的一个模块叫做Spring Data JPA,Spring Data JPA只是Spring Data框架下的一个基于JPA标准操作数据的模块,Spring Data JPA底层默认的使用的是Hibernate来做的JPA实现。Spring Data JPA核心能力就是基于JPA的标准对数据进行操作,极大简化了代码的编写,简化操作持久层的代码,直接编写接口就可以了。

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5     <parent>
 6         <groupId>org.springframework.boot</groupId>
 7         <artifactId>spring-boot-starter-parent</artifactId>
 8         <version>2.2.6.RELEASE</version>
 9         <relativePath/> <!-- lookup parent from repository -->
10     </parent>
11     <groupId>com.bie</groupId>
12     <artifactId>springboot-jpa</artifactId>
13     <version>0.0.1-SNAPSHOT</version>
14     <name>springboot-jpa</name>
15     <description>Demo project for Spring Boot</description>
16 
17     <properties>
18         <java.version>1.8</java.version>
19     </properties>
20 
21     <dependencies>
22         <!-- springBoot 的启动器 -->
23         <dependency>
24             <groupId>org.springframework.boot</groupId>
25             <artifactId>spring-boot-starter-web</artifactId>
26         </dependency>
27         <!-- thymeleaf 的启动器 -->
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter-thymeleaf</artifactId>
31         </dependency>
32         <!-- springBoot测试的启动器 -->
33         <dependency>
34             <groupId>org.springframework.boot</groupId>
35             <artifactId>spring-boot-starter-test</artifactId>
36             <scope>test</scope>
37             <!--<exclusions>
38                 <exclusion>
39                     <groupId>org.junit.vintage</groupId>
40                     <artifactId>junit-vintage-engine</artifactId>
41                 </exclusion>
42             </exclusions>-->
43         </dependency>
44 
45         <!-- Spring Data JPA 的启动器 -->
46         <dependency>
47             <groupId>org.springframework.boot</groupId>
48             <artifactId>spring-boot-starter-data-jpa</artifactId>
49         </dependency>
50 
51         <!-- mysql驱动包 -->
52         <dependency>
53             <groupId>mysql</groupId>
54             <artifactId>mysql-connector-java</artifactId>
55         </dependency>
56 
57         <!-- druid连接池 -->
58         <dependency>
59             <groupId>com.alibaba</groupId>
60             <artifactId>druid</artifactId>
61             <version>1.1.10</version>
62         </dependency>
63     </dependencies>
64 
65     <build>
66         <plugins>
67             <plugin>
68                 <groupId>org.springframework.boot</groupId>
69                 <artifactId>spring-boot-maven-plugin</artifactId>
70             </plugin>
71         </plugins>
72     </build>
73 
74 </project>

在application.properties配置文件中配置数据库链接信息、数据库链接池、Spring Data JPA开启正向工程、在控制台打印sql语句。

 1 # mysql的数据库驱动
 2 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 3 # mysql的链接
 4 spring.datasource.url=jdbc:mysql://localhost:3306/ssm
 5 # mysql的账号
 6 spring.datasource.username=root
 7 # mysql的密码
 8 spring.datasource.password=123456
 9 
10 # druid连接池的配置
11 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
12 
13 # Spring Data JPA,此配置可以在实体类中使用注解来创建数据表,开启正向工程
14 spring.jpa.hibernate.ddl-auto=update
15 # 在控制台打印sql语句
16 spring.jpa.show-sql=true

创建实体类Users。

 1 package com.bie.springboot.po;
 2 
 3 import javax.persistence.*;
 4 
 5 @Entity // 表示该类是实体类
 6 @Table(name = "tb_users") // 表示该实体类和数据表进行映射,name表示实体类和数据表进行映射
 7 // 如果使用的是正向工程的话,name属性的值表示的是数据表的表名称。
 8 public class Users {
 9 
10     @Id // 表示该字段是主键
11     @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键的生成策略
12     @Column(name = "id") // 表示实体类的字段和数据表的字段进行映射的关系,如果是正向工程的话,name的值就是数据表的字段名称
13     private Integer id;// 用户编号
14 
15     @Column(name = "name")
16     private String name;// 用户姓名
17 
18     @Column(name = "age")
19     private Integer age;// 用户年龄
20 
21     @Column(name = "address")
22     private String address;// 用户地址
23 
24     // alt + insert来生成构造器、setter\getter等等方法
25     public Integer getId() {
26         return id;
27     }
28 
29     public void setId(Integer id) {
30         this.id = id;
31     }
32 
33     public String getName() {
34         return name;
35     }
36 
37     public void setName(String name) {
38         this.name = name;
39     }
40 
41     public Integer getAge() {
42         return age;
43     }
44 
45     public void setAge(Integer age) {
46         this.age = age;
47     }
48 
49     public String getAddress() {
50         return address;
51     }
52 
53     public void setAddress(String address) {
54         this.address = address;
55     }
56 
57     @Override
58     public String toString() {
59         return "Users{
   " +
60                 "id=" + id +
61                 ", name='" + name + '\'' +
62                 ", age=" + age +
63                 ", address='" + address + '\'' +
64                 '}';
65     }
66 
67     public Users(String name, Integer age, String address) {
68         this.name = name;
69         this.age = age;
70         this.address = address;
71     }
72 
73     public Users() {
74     }
75 }

创建数据交互层接口继承JpaRepository<T,ID>。

泛型参数1,T表示的是当前需要映射的实体类类型,当前需要映射的实体。

泛型参数2,ID表示需要映射的实体中的主键的类型,当前映射的实体中的OID的类型。

 1 package com.bie.springboot.dao;
 2 
 3 import com.bie.springboot.po.Users;
 4 import org.springframework.data.jpa.repository.JpaRepository;
 5 
 6 /**
 7  * JpaRepository<T,ID>
 8  * 泛型参数1,T表示的是当前需要映射的实体类类型,当前需要映射的实体。
 9  * 泛型参数2,ID表示需要映射的实体中的主键的类型,当前映射的实体中的OID的类型。
10  */
11 public interface UsersDao extends JpaRepository<Users, Integer> {
12 
13 }

开始测试,测试代码,如下所示:

 1 package com.bie.springboot;
 2 
 3 import com.bie.springboot.dao.UsersDao;
 4 import com.bie.springboot.po.Users;
 5 import org.junit.jupiter.api.Test;
 6 import org.junit.runner.RunWith;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.boot.test.context.SpringBootTest;
 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 
11 @RunWith(SpringJUnit4ClassRunner.class)
12 @SpringBootTest(classes = SpringbootJpaApplication.class) // 启动器,将测试类和启动器整合在一起
13 class SpringbootJpaApplicationTests {
14 
15     @Autowired
16     private UsersDao usersDao;
17 
18     @Test
19     public void testSave() {
20         Users users = new Users();
21         users.setAddress("北京市海淀");
22         users.setAge(20);
23         users.setName("张三");
24         this.usersDao.save(users);
25     }
26 
27 }

如果下面报错,就在数据库链接URL后面根据下面所示的内容即可。

?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC

 1   .   ____          _            __ _ _
 2  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
 3 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 4  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
 5   '  |____| .__|_| |_|_| |_\__, | / / / /
 6  =========|_|==============|___/=/_/_/_/
 7  :: Spring Boot ::        (v2.2.6.RELEASE)
 8 
 9 2020-05-20 13:40:41.734  INFO 14492 --- [           main] c.b.s.SpringbootJpaApplicationTests      : Starting SpringbootJpaApplicationTests on DESKTOP-V37QSSE with PID 14492 (started by biehl in D:\program\idea\IntelliJ IDEA 2019.1.3\workspace_idea\springboot-jpa)
10 2020-05-20 13:40:41.736  INFO 14492 --- [           main] c.b.s.SpringbootJpaApplicationTests      : No active profile set, falling back to default profiles: default
11 2020-05-20 13:40:43.891  INFO 14492 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
12 2020-05-20 13:40:44.000  INFO 14492 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 96ms. Found 1 JPA repository interfaces.
13 2020-05-20 13:40:45.245  INFO 14492 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
14 2020-05-20 13:40:45.451  INFO 14492 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.12.Final
15 2020-05-20 13:40:45.813  INFO 14492 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {
   5.1.0.Final}
16 Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
17 2020-05-20 13:40:47.129  INFO 14492 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
18 2020-05-20 13:40:47.326 ERROR 14492 --- [reate-173197870] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, url: jdbc:mysql://127.0.0.1:3306/biehl?useUnicode=true&characterEncoding=utf8, errorCode 0, state 01S00
19 
20 java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support.
21     at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.19.jar:8.0.19]
22     at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.19.jar:8.0.19]
23     at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) ~[mysql-connector-java-8.0.19.jar:8.0.19]
24     at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) ~[mysql-connector-java-8.0.19.jar:8.0.19]
25     at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) ~[mysql-connector-java-8.0.19.jar:8.0.19]
26     at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76) ~[mysql-connector-java-8.0.19.jar:8.0.19]
27     at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836) ~[mysql-connector-java-8.0.19.jar:8.0.19]
28     at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456) ~[mysql-connector-java-8.0.19.jar:8.0.19]
29     at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246) ~[mysql-connector-java-8.0.19.jar:8.0.19]
30     at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:197) ~[mysql-connector-java-8.0.19.jar:8.0.19]
31     at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1558) ~[druid-1.1.10.jar:1.1.10]
32     at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1623) ~[druid-1.1.10.jar:1.1.10]
33     at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2468) ~[druid-1.1.10.jar:1.1.10]
34 Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support.
35     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_191]
36     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_191]
37     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_191]
38     at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_191]
39     at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.19.jar:8.0.19]
40     at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:85) ~[mysql-connector-java-8.0.19.jar:8.0.19]
41     at com.mysql.cj.util.TimeUtil.getCanonicalTimezone(TimeUtil.java:132) ~[mysql-connector-java-8.0.19.jar:8.0.19]
42     at com.mysql.cj.protocol.a.NativeProtocol.configureTimezone(NativeProtocol.java:2118) ~[mysql-connector-java-8.0.19.jar:8.0.19]
43     at com.mysql.cj.protocol.a.NativeProtocol.initServerSession(NativeProtocol.java:2142) ~[mysql-connector-java-8.0.19.jar:8.0.19]
44     at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:1310) ~[mysql-connector-java-8.0.19.jar:8.0.19]
45     at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:967) ~[mysql-connector-java-8.0.19.jar:8.0.19]
46     at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826) ~[mysql-connector-java-8.0.19.jar:8.0.19]
47     ... 6 common frames omitted
48 
49 2020-05-20 13:40:47.330 ERROR 14492 --- [reate-173197870] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, url: jdbc:mysql://127.0.0.1:3306/biehl?useUnicode=true&characterEncoding=utf8, errorCode 0, state 01S00

 

2、Spring Data JPA提供的核心接口。

2.1)、Repository接口,提供了方法名称命名查询方式。

 1 package com.bie.springboot.dao;
 2 
 3 import com.bie.springboot.po.Users;
 4 import org.springframework.data.repository.Repository;
 5 
 6 import java.util.List;
 7 
 8 /**
 9  * Repository接口的方法名称命名查询。
10  */
11 public interface UsersRepositoryByName extends Repository<Users, Integer> {
12 
13     /**
14      * 方法命名必须以findBy开头的,后面跟的是属性的名称,属性的名称必须大写,遵循驼峰式写法。
15      * findBy开头的,后面跟的就是查询条件。
16      * <p>
17      * 方法的名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母要大写)+查询条件(首字母大写)。
18      * 查询条件默认是等于。
19      * <p>
20      * 只要遵循findBy规则,有很多可以进行查询的条件。
21      *
22      * @param name
23      * @return
24      */
25     public List<Users> findByName(String name);
26 
27     /**
28      * @param name
29      * @return
30      */
31     public List<Users> findByNameEquals(String name);
32 
33     /**
34      * 根据姓名和年龄进行查询
35      *
36      * @param name
37      * @param age
38      * @return
39      */
40     public List<Users> findByNameAndAge(String name, Integer age);
41 
42     /**
43      * 根据姓名模糊查询
44      *
45      * @param name
46      * @return
47      */
48     public List<Users> findByNameLike(String name);
49 }

测试代码,如下所示:

 1 package com.bie.springboot;
 2 
 3 import com.bie.springboot.dao.UsersDao;
 4 import com.bie.springboot.dao.UsersRepositoryByName;
 5 import com.bie.springboot.po.Users;
 6 import org.junit.jupiter.api.Test;
 7 import org.junit.runner.RunWith;
 8 import org.springframework.beans.factory.annotation.Autowired;
 9 import org.springframework.boot.test.context.SpringBootTest;
10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 
12 import java.util.List;
13 
14 @RunWith(SpringJUnit4ClassRunner.class)
15 @SpringBootTest(classes = SpringbootJpaApplication.class)
16         // 启动器,将测试类和启动器整合在一起
17 class SpringbootJpaApplicationTests {
18 
19     @Autowired
20     private UsersRepositoryByName usersRepositoryByName;
21 
22 
23     @Test
24     public void testFindByName() {
25         List<Users> byName = this.usersRepositoryByName.findByName("张三");
26         System.out.println("Name: " + byName);
27     }
28 
29 
30     @Test
31     public void testFindByNameEquals() {
32         List<Users> byName = this.usersRepositoryByName.findByNameEquals("张三");
33         System.out.println("Name: " + byName);
34     }
35 
36 
37     @Test
38     public void testFindByNameAndAge() {
39         List<Users> byName = this.usersRepositoryByName.findByNameAndAge("张三", 20);
40         System.out.println("Name: " + byName);
41     }
42 
43     @Test
44     public void testFindByNameLike() {
45         List<Users> byName = this.usersRepositoryByName.findByNameLike("张%");
46         System.out.println("Name: " + byName);
47     }
48 
49 }

Repository接口,提供了基于@Query注解的查询与更新方式。

 1 package com.bie.springboot.dao;
 2 
 3 import com.bie.springboot.po.Users;
 4 import org.springframework.data.jpa.repository.Modifying;
 5 import org.springframework.data.jpa.repository.Query;
 6 import org.springframework.data.repository.Repository;
 7 
 8 import javax.transaction.Transactional;
 9 import java.util.List;
10 
11 /**
12  * Repository接口,提供了基于@Query注解的查询与更新方式。
13  */
14 public interface UsersRepositoryQueryAnnotation extends Repository<Users, Integer> {
15 
16     /**
17      * 默认支持的是HQL语句,不是标准的sql语句,底层需要进行转换,转换为标准的sql语句
18      *
19      * @param name
20      * @return
21      */
22     @Query(value = "from Users where name = :name")
23     public List<Users> queryByNameUseHQL(String name);
24 
25     /**
26      * 如果是SQL语句需要,nativeQuery = true表示的就是底层不需要进行sql语句的转换
27      *
28      * @param name
29      * @return
30      */
31     @Query(value = "select * from tb_users where name = ?", nativeQuery = true)
32     public List<Users> queryByNameUseSQL(String name);
33 
34     /**
35      * 更新操作,注意update后面是实体类的名称
36      *
37      * @param name
38      * @param id
39      */
40     @Query(value = "update Users set name = :name where id = :id")
41     @Modifying // 该注解表示需要执行一个更新操作。注意此方法调用需要开通事务的
42     @Transactional // 开启事务
43     public void updateUsersNameById(String name, Integer id);
44 }

测试代码,如下所示:

 1 package com.bie.springboot;
 2 
 3 import com.bie.springboot.dao.UsersRepositoryQueryAnnotation;
 4 import com.bie.springboot.po.Users;
 5 import org.junit.jupiter.api.Test;
 6 import org.junit.runner.RunWith;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.boot.test.context.SpringBootTest;
 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 
11 import java.util.List;
12 
13 @RunWith(SpringJUnit4ClassRunner.class)
14 @SpringBootTest(classes = SpringbootJpaApplication.class)
15         // 启动器,将测试类和启动器整合在一起
16 class SpringbootJpaApplicationTests {
17 
18     @Autowired
19     private UsersRepositoryQueryAnnotation usersRepositoryQueryAnnotation;
20 
21     @Test
22     public void testFindByNameUsrHQL() {
23         List<Users> byName = this.usersRepositoryQueryAnnotation.queryByNameUseHQL("张三");
24         System.out.println("Name: " + byName);
25     }
26 
27     @Test
28     public void testFindByNameUseSQL() {
29         List<Users> byName = this.usersRepositoryQueryAnnotation.queryByNameUseSQL("张三");
30         System.out.println("Name: " + byName);
31     }
32 
33     @Test
34     // @Transactional // 此方法调用需要添加事务,如果@Transactional注解和@Test注解配合使用,事务自动回滚
35     // @Rollback(value = false) // 取消自动回滚
36     public void testUpdateUsersNameById() {
37         this.usersRepositoryQueryAnnotation.updateUsersNameById("张飒飒2号", 1);
38     }
39 
40 }

如果报如下所示的错误,需要将@Query(value = "from Users where name = ?")修改为@Query(value = "from Users where name = :name")。

  1  .   ____          _            __ _ _
  2  /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
  3 ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
  4  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  5   '  |____| .__|_| |_|_| |_\__, | / / / /
  6  =========|_|==============|___/=/_/_/_/
  7  :: Spring Boot ::        (v2.2.6.RELEASE)
  8 
  9 2020-05-20 15:40:24.270  INFO 3352 --- [           main] c.b.s.SpringbootJpaApplicationTests      : Starting SpringbootJpaApplicationTests on DESKTOP-V37QSSE with PID 3352 (started by biehl in D:\program\idea\IntelliJ IDEA 2019.1.3\workspace_idea\springboot-jpa)
 10 2020-05-20 15:40:24.273  INFO 3352 --- [           main] c.b.s.SpringbootJpaApplicationTests      : No active profile set, falling back to default profiles: default
 11 2020-05-20 15:40:25.690  INFO 3352 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
 12 2020-05-20 15:40:25.786  INFO 3352 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spri
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值