35个Hibernate 注解:Hibernate架构设计与注解应用案例(必须收藏)

134 篇文章 0 订阅
14 篇文章 0 订阅

在这里插入图片描述

Hibernate 是 Java 持久化领域的核心框架,通过对象关系映射(ORM)技术,将 Java 对象与关系型数据库中的表相互映射。这种映射使得开发者能够使用面向对象的方法来处理数据,而不必编写复杂的 SQL 语句。Hibernate 提供了一系列注解,如 @Entity 用于标识实体类,@Table 用于指定实体与数据库表的映射,@Id 用于标记实体的主键字段,以及 @Column 用于定义实体属性与数据库表列的映射关系。
此外,@ManyToOne@OneToMany@ManyToMany 注解用于表达实体之间的关系,而 @JoinColumn 用于指定关系映射中的外键列。高级特性如 @Cache 注解用于配置

肖哥弹架构 跟大家“弹弹” 框架注解使用,需要代码关注

欢迎 点赞,关注,评论。

关注公号Solomon肖哥弹架构获取更多精彩内容

历史热点文章

hibernate 架构图

在这里插入图片描述

在这个图表中:

  • ORM 组包含了 Hibernate 框架的核心组件,如配置文件、数据源、事务管理和缓存。
  • Data Access 组描述了 Hibernate 会话、事务和持久化上下文,这些是进行数据访问和操作的主要接口。
  • Mapping 组展示了持久化类、实体、主键、属性、关联和表之间的映射关系。
  • Strategy 组包含了 Hibernate 的事务策略和缓存策略,这些定义了 Hibernate 的行为和性能优化。

1. 实体和表映射注解

@Entity
  • 注解作用介绍

用于标记一个类作为JPA实体。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
@Entity
public class User {
    // 实体类字段和方法
}
  • 注解使用效果: 使用@Entity后,MyBatis Plus和Hibernate会将该类识别为一个实体,可以进行数据库操作。
@Table
  • 注解作用介绍

用于指定实体与数据库表的映射。

  • 注解属性介绍
    • name: 指定实体对应的数据库表名。
  • 注解业务案例
@Entity
@Table(name = "user_table")
public class User {
    // 实体类字段和方法
}
  • 注解使用效果: 使用@Table后,MyBatis Plus和Hibernate会将该实体映射到指定的数据库表。

2. 主键和生成策略注解

@Id
  • 注解作用介绍

用于标记实体的主键字段。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
public class User {
    @Id
    private Long id;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Id后,MyBatis Plus和Hibernate会将该字段识别为实体的主键。
@GeneratedValue
  • 注解作用介绍

用于指定主键的生成策略。

  • 注解属性介绍
    • strategy: 指定生成策略,如GenerationType.AUTO
  • 注解业务案例
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // 其他字段和方法
}
  • 注解使用效果: 使用@GeneratedValue后,MyBatis Plus和Hibernate会根据指定的策略生成主键值。

3. 属性和列映射注解

@Column
  • 注解作用介绍

用于指定实体属性与数据库表列的映射。

  • 注解属性介绍
    • name: 指定数据库表的列名。
  • 注解业务案例
public class User {
    private Long id;
    @Column(name = "user_name")
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Column后,MyBatis Plus和Hibernate会将该字段映射到指定的数据库表列。
@Basic
  • 注解作用介绍

用于映射基本数据类型的属性。

  • 注解属性介绍
    • fetch: 指定加载策略,如FetchType.LAZY
  • 注解业务案例
public class User {
    private Long id;
    @Basic(fetch = FetchType.LAZY)
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Basic后,MyBatis Plus和Hibernate会根据指定的加载策略加载该字段。
@Enumerated
  • 注解作用介绍

用于映射枚举类型的属性。

  • 注解属性介绍
    • value: 指定枚举值的类型。
  • 注解业务案例
public enum Gender {
    MALE, FEMALE
}

public class User {
    private Long id;
    @Enumerated(EnumType.STRING)
    private Gender gender;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Enumerated后,MyBatis Plus和Hibernate会将枚举值映射为指定的类型。
@Transient
  • 注解作用介绍

用于标记非持久化字段。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
public class User {
    private Long id;
    @Transient
    private String temporaryData;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Transient后,MyBatis Plus和Hibernate不会将该字段持久化到数据库。
@Embedded
  • 注解作用介绍

用于将一个类嵌入到另一个实体中。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
public class Address {
    private String street;
    private String city;
}

public class User {
    private Long id;
    @Embedded
    private Address address;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Embedded后,MyBatis Plus和Hibernate会将嵌入的类作为实体的一部分进行持久化。

4. 关联和关系注解

@ManyToOne
  • 注解作用介绍

用于标记实体与另一个实体的多对一关系。

  • 注解属性介绍
    • targetEntity: 指定关联实体的类型。
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @ManyToOne
    private Department department;
    // 其他字段和方法
}
  • 注解使用效果: 使用@ManyToOne后,MyBatis Plus和Hibernate会将该字段识别为多对一关系,并进行相应的数据库操作。
@OneToMany
  • 注解作用介绍

用于标记实体与另一个实体的一对多关系。

  • 注解属性介绍
    • mappedBy: 指定对方实体中用于映射当前实体的属性名。
  • 注解业务案例
public class Department {
    @Id
    private Long id;
    @OneToMany(mappedBy = "department")
    private List<User> users;
    // 其他字段和方法
}
  • 注解使用效果: 使用@OneToMany后,MyBatis Plus和Hibernate会将该字段识别为一对多关系,并进行相应的数据库操作。
@ManyToOne
  • 注解作用介绍

用于标记实体与另一个实体的多对一关系。

  • 注解属性介绍
    • targetEntity: 指定关联实体的类型。
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @ManyToOne
    private Department department;
    // 其他字段和方法
}
  • 注解使用效果: 使用@ManyToOne后,MyBatis Plus和Hibernate会将该字段识别为多对一关系,并进行相应的数据库操作。
@ManyToMany
  • 注解作用介绍

用于标记实体与另一个实体的多对多关系。

  • 注解属性介绍
    • targetEntity: 指定关联实体的类型。
    • mappedBy: 指定对方实体中用于映射当前实体的属性名。
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @ManyToMany
    private List<Role> roles;
    // 其他字段和方法
}
  • 注解使用效果: 使用@ManyToMany后,MyBatis Plus和Hibernate会将该字段识别为多对多关系,并进行相应的数据库操作。
@JoinColumn
  • 注解作用介绍

用于指定关系映射中的外键列。

  • 注解属性介绍
    • name: 指定外键列的名称。
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
    // 其他字段和方法
}
  • 注解使用效果: 使用@JoinColumn后,MyBatis Plus和Hibernate会将该字段映射到指定的外键列。

5. 高级映射注解

@AttributeOverride
  • 注解作用介绍

用于覆盖继承实体中的属性映射。

  • 注解属性介绍
    • name: 指定要覆盖的属性名称。
    • column: 指定新的列映射。
  • 注解业务案例
public class BaseEntity {
    private Long id;
}

public class User extends BaseEntity {
    @AttributeOverride(name = "id", column = @Column(name = "user_id"))
    private Long id;
    // 其他字段和方法
}
  • 注解使用效果: 使用@AttributeOverride后,MyBatis Plus和Hibernate会使用指定的列映射覆盖继承实体中的属性。
@AssociationOverride
  • 注解作用介绍

用于覆盖继承实体中的关联属性映射。

  • 注解属性介绍
    • name: 指定要覆盖的关联属性名称。
    • joinColumns: 指定新的关联列映射。
  • 注解业务案例
public class BaseEntity {
    private Department department;
}

public class User extends BaseEntity {
    @AssociationOverride(name = "department", joinColumns = @JoinColumn(name = "user_department_id"))
    private Department department;
    // 其他字段和方法
}
  • 注解使用效果: 使用@AssociationOverride后,MyBatis Plus和Hibernate会使用指定的关联列映射覆盖继承实体中的关联属性。
@SecondaryTable
  • 注解作用介绍

用于映射实体到多个表。

  • 注解属性介绍
    • name: 指定第二个表的名称。
  • 注解业务案例
@Entity
@SecondaryTable(name = "user_details", pkJoinColumns = @PrimaryKeyJoinColumn(name = "user_id"))
public class User {
    @Id
    private Long id;
    // 其他字段和方法
}
  • 注解使用效果: 使用@SecondaryTable后,MyBatis Plus和Hibernate会将该实体映射到多个表。
@PrimaryKeyJoinColumn
  • 注解作用介绍

用于映射复合主键中的外键。

  • 注解属性介绍
    • name: 指定外键列的名称。
  • 注解业务案例
@Entity
@Table(name = "order_line")
@PrimaryKeyJoinColumns({
    @PrimaryKeyJoinColumn(name = "order_id", referencedColumnName = "id"),
    @PrimaryKeyJoinColumn(name = "line_id", referencedColumnName = "lineId")
})
public class OrderLine {
    // 实体类字段和方法
}
  • 注解使用效果: 使用@PrimaryKeyJoinColumn后,MyBatis Plus和Hibernate会将该字段映射为复合主键的一部分。

6. 查询和缓存注解

@Query
  • 注解作用介绍

用于定义命名查询。

  • 注解属性介绍
    • value: 指定查询的SQL语句。
  • 注解业务案例
public interface UserMapper {
    @Query("SELECT u FROM User u WHERE u.id = #{id}")
    User findUserById(@Param("id") Long id);
}
  • 注解使用效果: 使用@Query后,MyBatis Plus和Hibernate会执行指定的SQL查询。
@NamedQueries
  • 注解作用介绍

用于定义多个命名查询。

  • 注解属性介绍
    • value: 指定命名查询的数组。
  • 注解业务案例
@NamedQueries({
    @NamedQuery(name = "User.findAll", query = "SELECT u FROM User u"),
    @NamedQuery(name = "User.findByName", query = "SELECT u FROM User u WHERE u.name = #{name}")
})
public class User {
    // 实体类字段和方法
}
  • 注解使用效果: 使用@NamedQueries后,MyBatis Plus和Hibernate可以执行定义的多个命名查询。
@Cacheable
  • 注解作用介绍

用于指定实体的缓存策略。

  • 注解属性介绍
    • value: 指定缓存的名称。
  • 注解业务案例
public interface UserMapper {
    @Cacheable("userCache")
    User findUserById(@Param("id") Long id);
}
  • 注解使用效果: 使用@Cacheable后,MyBatis Plus和Hibernate会将查询结果缓存到指定的缓存中。

7. 动态SQL和结果集注解

@SqlResultSetMapping
  • 注解作用介绍

用于定义SQL结果集与实体类的映射。

  • 注解属性介绍
    • name: 指定结果集映射的名称。
  • 注解业务案例
public interface UserMapper {
    @SqlResultSetMapping(name = "userMapping")
    @Select("SELECT id, name, age FROM users WHERE id = #{id}")
    User findUserById(@Param("id") Long id);
}
  • 注解使用效果: 使用@SqlResultSetMapping后,MyBatis Plus和Hibernate会将SQL查询结果映射到指定的实体类。
@Where
  • 注解作用介绍

用于在实体类级别添加条件约束。

  • 注解属性介绍
    • clause: 指定条件表达式。
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @Where(clause = "status = 'ACTIVE'")
    private String status;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Where后,MyBatis Plus和Hibernate会在查询时自动应用指定的条件。

8. 继承和策略注解

@DiscriminatorColumn
  • 注解作用介绍

用于映射继承结构中的类标识符。

  • 注解属性介绍
    • name: 指定类标识符的列名。
  • 注解业务案例
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
public class BaseEntity {
    @Id
    private Long id;
    // 其他字段和方法
}
  • 注解使用效果: 使用@DiscriminatorColumn后,MyBatis Plus和Hibernate会在单表继承结构中使用指定的列作为类标识符。
@DiscriminatorValue
  • 注解作用介绍

用于指定实体在继承结构中的值。

  • 注解属性介绍
    • value: 指定实体的值。
  • 注解业务案例
@Entity
@DiscriminatorValue("USER")
public class User extends BaseEntity {
    // 实体类字段和方法
}
  • 注解使用效果: 使用@DiscriminatorValue后,MyBatis Plus和Hibernate会在继承结构中使用指定的值来区分实体。

9. 特殊功能注解

@Convert
  • 注解作用介绍

用于指定属性转换器。

  • 注解属性介绍
    • converter: 指定转换器的类。
  • 注解业务案例
public class User {
    @Convert(converter = CustomDateConverter.class)
    private Date birthDate;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Convert后,MyBatis Plus和Hibernate会在读写属性时使用指定的转换器。
@Access
  • 注解作用介绍

用于指定实体属性的访问策略。

  • 注解属性介绍
    • value: 指定访问策略,如AccessType.FIELD
  • 注解业务案例
public class User {
    @Id
    @Access(AccessType.FIELD)
    private Long id;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Access后,MyBatis Plus和Hibernate会根据指定的访问策略访问实体属性。
@BatchSize
  • 注解作用介绍

用于指定批量操作的批处理大小。

  • 注解属性介绍
    • size: 指定批处理的大小。
  • 注解业务案例
public interface UserMapper {
    @BatchSize(size = 100)
    int insertBatchSelective(List<User> users);
}
  • 注解使用效果: 使用@BatchSize后,MyBatis Plus和Hibernate会在执行批量操作时使用指定的批处理大小。

10. Hibernate特有注解

@NaturalId
  • 注解作用介绍

用于指定实体的自然标识符。

  • 注解属性介绍
    • mutable: 指定标识符是否可变。
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @NaturalId
    private String email;
    // 其他字段和方法
}
  • 注解使用效果: 使用@NaturalId后,Hibernate会将该字段识别为自然标识符,并提供优化的加载性能。
@Immutable
  • 注解作用介绍

用于标记实体为不可变。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
@Entity
@Immutable
public class User {
    @Id
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Immutable后,Hibernate会将该实体识别为不可变,优化性能。
@DynamicInsert
  • 注解作用介绍

用于动态生成INSERT语句。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
@Entity
@DynamicInsert
public class User {
    @Id
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@DynamicInsert后,Hibernate会动态生成INSERT语句,减少不必要的字段更新。
@DynamicUpdate
  • 注解作用介绍

用于动态生成UPDATE语句。

  • 注解属性介绍

无特定属性。

  • 注解业务案例
@Entity
@DynamicUpdate
public class User {
    @Id
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@DynamicUpdate后,Hibernate会动态生成UPDATE语句,减少不必要的字段更新。
@SelectBefore
  • 注解作用介绍

用于在更新或删除操作之前执行自定义的SQL查询。

  • 注解属性介绍
    • statement: 指定自定义的SQL查询语句。
  • 注解业务案例
@Entity
@SelectBefore(statement = "SELECT * FROM users WHERE id = #{id}")
public class User {
    @Id
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@SelectBefore后,Hibernate会在更新或删除操作之前执行指定的SQL查询。
@FilterDef
  • 注解作用介绍

用于定义动态过滤条件。

  • 注解属性介绍
    • name: 指定过滤器的名称。
  • 注解业务案例
@FilterDef(name = "activeUsers", defaultOverride = @FilterParam(name = "status", value = "active"))
public class User {
    @Id
    private Long id;
    private String name;
    private String status;
    // 其他字段和方法
}
  • 注解使用效果: 使用@FilterDef后,Hibernate会定义动态过滤条件,可以在查询时使用。
@Filter
  • 注解作用介绍

用于在实体类上应用动态过滤条件。

  • 注解属性介绍
    • name: 指定过滤器的名称。
  • 注解业务案例
@Entity
@Filter(name = "activeUsers")
public class User {
    @Id
    private Long id;
    private String name;
    private String status;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Filter后,Hibernate会在查询时应用指定的动态过滤条件。
@FilterJoinTable
  • 注解作用介绍

用于定义动态过滤条件的关联表。

  • 注解属性介绍
    • name: 指定关联表的名称。
  • 注解业务案例
@Entity
@FilterJoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"))
public class User {
    @Id
    private Long id;
    private String name;
    private String status;
    // 其他字段和方法
}
  • 注解使用效果: 使用@FilterJoinTable后,Hibernate会在查询时应用指定的关联表动态过滤条件。
@LazyCollection
  • 注解作用介绍

用于指定集合的懒加载策略。

  • 注解属性介绍
    • value: 指定懒加载的类型,如LazyCollectionOption.TRUE
  • 注解业务案例
public class User {
    @Id
    private Long id;
    @LazyCollection(value = LazyCollectionOption.EXTRA)
    private Set<Role> roles;
    // 其他字段和方法
}
  • 注解使用效果: 使用@LazyCollection后,Hibernate会根据指定的策略懒加载集合。
@Synchronize
  • 注解作用介绍

用于在分布式环境中同步数据。

  • 注解属性介绍
    • value: 指定同步的实体类。
  • 注解业务案例
@Entity
@Synchronize(value = "users")
public class User {
    @Id
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@Synchronize后,Hibernate会在分布式环境中同步指定的实体数据。
@TypeDef
  • 注解作用介绍

用于定义自定义的类型。

  • 注解属性介绍
    • typeClass: 指定自定义类型的类。
  • 注解业务案例
@Entity
@TypeDef(typeClass = CustomType.class)
public class User {
    @Id
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@TypeDef后,Hibernate会使用指定的自定义类型进行数据持久化。
@GenericGenerator
  • 注解作用介绍

用于指定自定义的生成策略。

  • 注解属性介绍
    • name: 指定生成器的名称。
    • strategy: 指定生成策略的类。
  • 注解业务案例
@Entity
@GenericGenerator(name = "customGenerator", strategy = "com.example.CustomGenerator")
public class User {
    @Id
    @GeneratedValue(generator = "customGenerator")
    private Long id;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@GenericGenerator后,Hibernate会使用指定的自定义生成策略生成主键值。
@CreationTimestamp
  • 注解作用介绍

用于自动设置创建时间戳。

  • 注解属性介绍
    • column: 指定存储时间戳的列名。
  • 注解业务案例
@Entity
public class User {
    @Id
    private Long id;
    @CreationTimestamp
    private LocalDateTime created;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@CreationTimestamp后,Hibernate会在实体创建时自动设置指定列的创建时间戳。
@UpdateTimestamp
  • 注解作用介绍

用于自动设置更新时间戳。

  • 注解属性介绍
    • column: 指定存储时间戳的列名。
  • 注解业务案例
@Entity
public class User {
    @Id
    private Long id;
    @UpdateTimestamp
    private LocalDateTime updated;
    private String name;
    // 其他字段和方法
}
  • 注解使用效果: 使用@UpdateTimestamp后,Hibernate会在实体更新时自动设置指定列的更新时间戳。

10. Hibernate综合性注解使用案例

表结构

首先,我们定义数据库中的表结构:

CREATE TABLE authors (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    bio TEXT
);

CREATE TABLE books (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    isbn VARCHAR(20),
    publication_date DATE,
    price DECIMAL(10, 2),
    author_id BIGINT,
    FOREIGN KEY (author_id) REFERENCES authors(id)
);

业务案例说明

在这个案例中,Author 实体代表书籍的作者,Book 实体代表书籍。AuthorBook 之间存在一对多关系,即一个作者可以有多本书,但每本书只能有一个作者。

  • 当创建一个新的作者时,@CreationTimestamp 注解会自动设置其创建时间。
  • 当书籍信息更新时,@UpdateTimestamp 注解会自动更新其最后修改时间。
  • 书籍的价格使用 @Type 注解来确保在数据库中正确存储和检索。

实体定义

接下来,我们定义Java实体和对应的Hibernate注解。

Author 实体
import javax.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "authors")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "bio")
    private String bio;

    @OneToMany(mappedBy = "author")
    private Set<Book> books;

    // Getters and setters
}
Book 实体
import javax.persistence.*;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

@Entity
@Table(name = "books")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "title", nullable = false)
    private String title;

    @Column(name = "isbn", unique = true)
    private String isbn;

    @Type(type = "org.hibernate.type.DateType")
    @Column(name = "publication_date")
    @CreationTimestamp
    private Date publicationDate;

    @Column(name = "price", precision = 10, scale = 2)
    private BigDecimal price;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id", nullable = false)
    private Author author;

    // Getters and setters
}

注解说明

  • @Entity: 标记类作为JPA实体。
  • @Table: 指定实体对应的数据库表名。
  • @Id: 标记实体的主键字段。
  • @GeneratedValue: 指定主键的生成策略。
  • @Column: 指定实体属性与数据库表列的映射。
  • @OneToMany: 标记一对多关系。
  • @ManyToOne: 标记多对一关系。
  • @JoinColumn: 指定关系映射中的外键列。
  • @Cache: 指定实体的缓存策略。
  • @CreationTimestamp: 自动设置实体的创建时间戳。
  • @UpdateTimestamp: 自动设置实体的更新时间戳。
  • @Type: 指定自定义的Hibernate类型。
  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Solomon_肖哥弹架构

你的欣赏就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值