MybatisStudy

Mybatis学习

1、第一个Mybatis项目

1.1搭建数据库环境

1.2创建项目

1、新建普通maven项目
2、删除src
3、导入依赖
<dependencies>
    <!--mysql驱动-->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
    </dependency>

    <!--mybatis-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
    </dependency>

    <!--junit-->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
    <scope>test</scope>
    </dependency>
    </dependencies>

2、 创建一个模块

2.1、创建核心配置文件

<!--核心配置-->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" 	value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306
                /mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

2.2、编写mybatis工具类

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //获取SqlSessionFactory对象
            String resource = "mabatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

2.3、编写代码

  • 实体类

    package com.ngk.pojo;
    
    public class User {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
  • Dao接口

    public interface UserMapper {
        List<User> getUserList();
    }
  • 接口实现类由原来的UserImpl转变为一个Mapper配置文件

<!--命名空间绑定一个对应的MApper接口-->
<mapper namespace="com.ngk.mapper.UserMapper">
    <!--sql查询语句-->
    <select id="getUserList" resultType="com.ngk.pojo.User">
        select * from mybatis.user
    </select>
</mapper>

2.4 测试

@Test
public void test(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //2.执行SQL
    //方式1
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userMapper.getUserList();

    for (User user : userList) {
        System.out.println(user);
    }

    //关闭Session
    sqlSession.close();
}
    

2.5 注意点

2.5.1 每个xml需要在核心文件注册

<mappers>
    <mapper resource="com/ngk/mapper/UserMapper.xml"></mapper>
</mappers>

2.5.2 需要在pom文件配置build

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

3、mybatis的增删改查

3.1、查询操作

//根据id查询
User getUserById(int id);
<!--根据id查用户-->
<select id="getUserById" parameterType="int" resultType="com.ngk.pojo.User">
    select * from mybatis.user where id=#{id}
</select>
@Test
public void testFindUserById(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    try {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(1);
        System.out.println(user);
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        sqlSession.close();
    }
}

3.2、增加操作

//增加操作
int addUser(User user);
<!--添加一个用户-->
<insert id="addUser" parameterType="com.ngk.pojo.User" >
    insert into mybatis.user(id, name, pwd) VALUE (#{id}, #{name}, #{pwd})
</insert>
//添加一个用户
@Test
public void testAddUser(){
    SqlSession sqlSession = Mybati
    UserMapper userMapper = sqlSes
    User user = new User(4, "luhan
    int status = userMapper.addUse
    System.out.println(status);
    //提交事务
    sqlSession.commit();
    //关闭Session
    sqlSession.close();
}

3.3、修改操作

//修改操作
int updateUser(User user);
<!--修改用户-->
<update id="updateUser" parameterType="com.ngk.pojo.User" >
    update mybatis.user  set name=#{name}, pwd=#{pwd} where id=#{id};
</update>
//更改用户信息
@Test
public void updateUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    int status = userMapper.updateUser(new User(2, "ngk", "123456"));
    if(status>0) System.out.println("更改成功!");
    //提交事务
    sqlSession.commit();
    //关闭事务
    sqlSession.close();
}

3.4、删除操作

//删除操作
int deleteUser(int id);
<!--删除用户-->
<delete id="deleteUser" parameterType="int">
    delete from mybatis.user where id= #{id};
</delete>
//删除用户信息
@Test
public void deleteUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    int status = userMapper.deleteUser(4);
    if(status>0) System.out.println("更改成功!");
    //提交事务
    sqlSession.commit();
    //关闭事务
    sqlSession.close();
}

4、万能Map

  • 如果参数过多,或者数据库中的表,字段过多或者参数过多,应当考虑使用Map
  • Map传递参数,直接在Sql中取出key即可!【parameterType=“map”】
  • 对象传递参数,直接在Sql中取出对象即可!【parameterType=“Object”】
  • 多个参数用Map或者注解

4.1map的插入操作

<!--用map添加一个用户-->
<insert id="addUser2" parameterType="map" >
    insert into mybatis.user(id, name, pwd) VALUE (#{userId}, #{userName}, #{userPwd});
</insert>
 @Test
 //用map添加用户
 public void AddUser2(){
     SqlSession sqlSession = MybatisUtils.getSqlSession();
     UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
     Map<String, Object> map = new HashMap<String, Object>();
     map.put("userId", 5);
     map.put("userName", "luhan");
     map.put("userPwd", "123321");
     int status = userMapper.addUser2(map);
     if(status>0) System.out.println("插入成功!");
     sqlSession.commit();
     sqlSession.close();
 }

5、模糊查询

模糊查询怎么写

  • 在java代码执行的时候使用通配符

  • List<User> users = userMapper.getUserLike("%小%");
  • 在sql拼接中使用通配符

  •  select * from mybatis.user where name like "%"#{value}"%";
<!--模糊查询-->
<select id="getUserLike" resultType="com.ngk.pojo.User">
    select * from mybatis.user where name like #{value};
</select>
//模糊查询
@Test
public void TestGetUserLike(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    try {
        //2.执行SQL
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.getUserLike("%小%");
        for (User user : users) {
            System.out.println(user);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        sqlSession.close();
    }
}

6、配置解析

6.1 配置

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
  • mybatis可以配置多个环境,但每个SessionFactory实例只能选择一个
  • 学会配置多套运行环境
  • Mybatis默认事务管理器为JDBC,连接池:POOLED

6.2、属性(properties)

编写一个配置文件:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username=root
password=123456

引入外部配置文件

<!--引入外部配置文件-->
<properties resource="db.properties"></properties>

配置

<environments default="text">
    <environment id="text">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>
  • 可以引入外部文件
  • 可以在其中增加属性配置
  • 如果两个文件有同一字段,优先使用外部配置文件

6.3 类型别名(typeAliases)

  • 减少类完全限定名的冗余
<!--给实体类起别名-->
<typeAliases>
    <typeAlias type="com.ngk.pojo.User" alias="User"></typeAlias>
</typeAliases>
<select id="getUserList" resultType="User">
    select * from mybatis.user
</select>
  • 也可指定一个包名,Mybatis会在包名下搜索需要的JavaBean
  • 默认别名为这个类的类名,类名首字母小写
<!--给实体类起别名-->
<typeAliases>
    <package name="com.ngk.pojo"></package>
</typeAliases>
<select id="getUserList" resultType="user">
    select * from mybatis.user
</select>
  • 实体类少用第一种,实体类多用第二种
  • 第一种可以DIY别名,第二种不行,非要改,需要在实体类上增加注解

7、映射器(mapper)

  • 方式一:
 <mappers>
     <mapper resource="com/ngk/mapper/UserMapper.xml"></mapper>
 </mappers>
  • 方式二:
 <mappers>
     <mapper class="com.ngk.mapper.UserMapper"></mapper>
 </mappers>

注意点:

  • 接口和配置文件必须同名!

  • 接口和Mapper配置文件必须在同一个包下

  • 方式三:使用扫描包进行注入绑定

<mappers>
   <package name="com.ngk.mapper"></package>
</mappers>

注意点:

  • 接口和配置文件必须同名!
  • 接口和Mapper配置文件必须在同一个包下

8、解决属性名和字段名不一致的问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPsuvOlv-1596036691950)(D:\tool\MarkDown\pictures\plugins4.png)]

解决方法

8.1起别名

<!--sql查询语句-->
<select id="getUserById" resultType="user" parameterType="int">
    select id, pwd as password from mybatis.user where id = #{id};
</select>

8.2 resultMap结果集映射

<!--column数据库中的字段 property实体类中的字段-->
<resultMap id="userMap" type="User">
    <result column="id" property="id"></result>
    <result column="name" property="name"></result>
    <result column="pwd" property="password"></result>
</resultMap>
<select id="getUserById" resultMap="userMap">
    select * from mybatis.user where id = #{id};
</select>
  • 如果数据中的字段 和实体类中的字段相同可省略
<resultMap id="userMap" type="User">
    <result column="pwd" property="password"></result>
</resultMap>

9、日志工厂

9.1Log4j

9.1.1 导入jar包
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.13.2</version>
</dependency>
9.1.2 配置properties
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
9.1.3配置log4j输出
<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>

9.2 STDOUT_LOGGING 标准日志输出

<!--设置日志输出格式-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

10、分页

为什么要分页? 减少数据处理量

10.1 mybatis实现分页,核心SQL

10.1.1 接口
//分页查询
List<User> getUserByLimit(Map map);
10.1.2 Mapper.xml
<!---结果集映射-->
<resultMap id="UserMap" type="user">
    <result column="pwd" property="password"></result>
</resultMap>
    
<!--分页查询-->
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
    select * from mybatis.user limit #{startIndex}, #{pageSize};
</select>
10.1.3 测试
@Test
public void testGetUserByLimit(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    try {
        //2.执行SQL
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex", 0);
        map.put("pageSize", 4);
        List<User> userByLimit = userMapper.getUserByLimit(map);
        for (User user : userByLimit) {
            System.out.println(user);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        sqlSession.close();
    }
}

10.2 RowBounds 实现分页

11、使用注解开发

11.1使用注解开发

1.注解在接口上实现
 @Select("select * from user")
 List<User> getUsers();
2.在核心配置文件中绑定接口
<mappers>
  <mapper class="com.ngk.mapper.UserMapper"></mapper>
</mappers>
3.测试
 @Test
 public void test(){
     //1.获取SqlSession对象
     SqlSession sqlSession = MybatisUtils.getSqlSession();
     try {
         //2.执行SQL
         UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
         List<User> users = userMapper.getUsers();
         for (User user : users) {
             System.out.println(user);
         }
     }catch (Exception e){
         e.printStackTrace();
     }finally {
         sqlSession.close();
     }
 }

11.2 注解CRUD

 //有参查询
 @Select("select * from user where id = #{id}")
 User getUserById(@Param("id") int id);
 //增
 @Insert("insert into user(id, name, pwd) value(#{id}, #{name}, #{password})")
 int addUser(User user);
 //删
 @Delete("delete from user where id = #{uid}")
 int deleteUser(@Param("uid") int id);
 //改
 @Update("update user set name=#{userName}, pwd=#{userPwd} where id = #{userId}" )
 int updateUser(Map map);

11.3关于@Param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型,可以忽略,建议都加上
  • 在SQL中引用的就是这里得到@Param()中设定的属性名

12、Lombok

12.1 使用步骤

1、在IDEA安装Lombok插件
2、在项目中导入Lombok 的jar包
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
3、在实体类上加注解
@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data 
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows
@val
@var
experimental @var
@UtilityClass
Lombok config system
@Data:无参构造、get、set、toString、hashcode、equals
@AllArgsConstructor 有参构造
@NoArgsConstructor 无参构造

13、多对一

13.1 测试环境搭建

1.导入lombok
2.新建两个实体类Teacher、Student
3.建立mapper接口
4.建立mapper.xml
5.在核心配置文件中绑定注册mapper接口或者文件
6.测试查询是否成功

13.2按照查询嵌套处理

<!--
    思路:
        1、查询所有学生信息
        2、根据学生查出来的tid,寻找对应的老师!
-->
<!--查学生-->
<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
    <result property="id" column="id"></result>
    <result property="name" column="name"></result>
    
    <!--复杂属性,需要单独处理-->
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"></association>
</resultMap>
<!--查老师-->
<select id="getTeacher" resultType="Teacher">
    select * from teacher where id = #{id}
</select>

13.3 按照结果嵌套处理

 <!--按照结果嵌套处理-->
 <select id="getStudent2" resultMap="StudentTeacher2">
     select s.id sid, s.name sname, t.name tname
       from student s, teacher t
         where s.tid = t.id;
 </select>
 <resultMap id="StudentTeacher2" type="Student">
     <result property="id" column="sid"></result>
     <result property="name" column="sname"></result>
     <association property="teacher" javaType="Teacher">
         <result property="name" column="tname"></result>
     </association>
 </resultMap>

13.4回顾Mysql多对一查询方式

  • 子查询
  • 连表查询

14、一对多

14.1 环境搭建

@Data
public class Teacher {
    private int id;
    private String name;
    //一个老师多个学生
    private List<Student> student;
}

14.2 按结果连表查询

 <select id="getTeacher1" resultMap="StudentTeacher">
     select s.id sid, s.name sname, t.id tid, t.name tname
       from student s, teacher t
         where s.tid = t.id;
 </select>
 <!--按结果嵌套查询-->
 <resultMap id="StudentTeacher" type="Teacher">
     <result property="id" column="tid"></result>
     <result property="name" column="tname"></result>
     <!--复杂属性,需要单独处理, 对象association 集合:collection
         javaType=""指定属性类型
         集合中的泛型信息,使用ofType获取
     -->
     <collection property="student" ofType="com.ngk.pojo.Student">
         <result property="id" column="sid"></result>
         <result property="name" column="sname"></result>
     </collection>
 </resultMap>

14.3 子查询

 <select id="getTeacher2" resultMap="StudentTeacher1">
     select * from mybatis.teacher where id = #{tid};
 </select>
 <resultMap id="StudentTeacher1" type="Teacher">
     <collection property="student" ofType="com.ngk.pojo.Student" javaType="ArrayList" select="getStudent1" column="id"></collection>
 </resultMap>
 <select id="getStudent1" resultType="com.ngk.pojo.Student">
     select * from mybatis.student where tid = #{tid};
 </select>

15、动态SQL

15.1 if语句

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE state = ‘ACTIVE’ 
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

15.2 choose, when, otherwise

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

15.3 trim, where, set

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
  • where 元素知道只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。

15.4 foreach

  • 动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候
  • foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

16、缓存

16.1 一级缓存

  • 一级缓存是默认开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个阶段
  • 一级缓存相当于一个Map

16.2 二级缓存

  • 基于namespace,一个命名空间,对应一个二级缓存
  • 测试:需要将实体类序列化,否则报错

16.3 缓存原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oJkWG2D1-1596036691955)(D:\tool\MarkDown\pictures\缓存原理.png)]

ActiveBlogLike"
resultType=“Blog”>
SELECT * FROM BLOG


state = #{state}


AND title like #{title}


AND author_name like #{author.name}



* where 元素知道只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。

### 15.4 foreach

* 动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候
* foreach 元素的功能是非常强大的,它允许你指定一个集合,声明可以用在元素体内的集合项和索引变量

~~~ java
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

16、缓存

16.1 一级缓存

  • 一级缓存是默认开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个阶段
  • 一级缓存相当于一个Map

16.2 二级缓存

  • 基于namespace,一个命名空间,对应一个二级缓存
  • 测试:需要将实体类序列化,否则报错

16.3 缓存原理

[外链图片转存中…(img-oJkWG2D1-1596036691955)]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值