JPA按照实体类的字段顺序生成表

JPA中查询任意表的任意字段转实体类Dto的Util方法 //转换实体类 public static List castEntity(List list, Class clazz) throws Exception { List returnList = new ArrayList(); Object[] co = list.get(0); Class[] c2 = new Class[co 阅读详情

为什么hibernate在生成表字段的时候是无序的?因为其内部实现使用的TreeMap,看下源码就知道了:
在这里插入图片描述
我们只需要将此类复制出来,在我们自己的项目里写一个同样的类,并且包名完全一致,再将此类中所有的TreeMap换成LinkedHashMap就可以了:
在这里插入图片描述

import java.util.*;
import javax.persistence.Access;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.Any;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.cfg.AccessType;
import org.hibernate.cfg.annotations.HCANNHelper;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.jboss.logging.Logger;

class PropertyContainer {
    private static final CoreMessageLogger LOG = (CoreMessageLogger)Logger.getMessageLogger(CoreMessageLogger.class, PropertyContainer.class.getName());
    private final XClass xClass;
    private final XClass entityAtStake;
    private final AccessType classLevelAccessType;
    private final LinkedHashMap<String, XProperty> persistentAttributeMap;

    PropertyContainer(XClass clazz, XClass entityAtStake, AccessType defaultClassLevelAccessType) {
        this.xClass = clazz;
        this.entityAtStake = entityAtStake;
        if (defaultClassLevelAccessType == AccessType.DEFAULT) {
            defaultClassLevelAccessType = AccessType.PROPERTY;
        }

        AccessType localClassLevelAccessType = this.determineLocalClassDefinedAccessStrategy();

        assert localClassLevelAccessType != null;

        this.classLevelAccessType = localClassLevelAccessType != AccessType.DEFAULT ? localClassLevelAccessType : defaultClassLevelAccessType;

        assert this.classLevelAccessType == AccessType.FIELD || this.classLevelAccessType == AccessType.PROPERTY;

        this.persistentAttributeMap = new LinkedHashMap();
        List<XProperty> fields = this.xClass.getDeclaredProperties(AccessType.FIELD.getType());
        List<XProperty> getters = this.xClass.getDeclaredProperties(AccessType.PROPERTY.getType());
        this.preFilter(fields, getters);
        Map<String, XProperty> persistentAttributesFromGetters = new HashMap();
        this.collectPersistentAttributesUsingLocalAccessType(this.persistentAttributeMap, persistentAttributesFromGetters, fields, getters);
        this.collectPersistentAttributesUsingClassLevelAccessType(this.persistentAttributeMap, persistentAttributesFromGetters, fields, getters);
    }

    private void preFilter(List<XProperty> fields, List<XProperty> getters) {
        Iterator propertyIterator = fields.iterator();

        XProperty property;
        while(propertyIterator.hasNext()) {
            property = (XProperty)propertyIterator.next();
            if (mustBeSkipped(property)) {
                propertyIterator.remove();
            }
        }

        propertyIterator = getters.iterator();

        while(propertyIterator.hasNext()) {
            property = (XProperty)propertyIterator.next();
            if (mustBeSkipped(property)) {
                propertyIterator.remove();
            }
        }

    }

    private void collectPersistentAttributesUsingLocalAccessType(LinkedHashMap<String, XProperty> persistentAttributeMap, Map<String, XProperty> persistentAttributesFromGetters, List<XProperty> fields, List<XProperty> getters) {
        Iterator propertyIterator = fields.iterator();

        XProperty xProperty;
        Access localAccessAnnotation;
        while(propertyIterator.hasNext()) {
            xProperty = (XProperty)propertyIterator.next();
            localAccessAnnotation = (Access)xProperty.getAnnotation(Access.class);
            if (localAccessAnnotation != null && localAccessAnnotation.value() == javax.persistence.AccessType.FIELD) {
                propertyIterator.remove();
                persistentAttributeMap.put(xProperty.getName(), xProperty);
            }
        }

        propertyIterator = getters.iterator();

        while(propertyIterator.hasNext()) {
            xProperty = (XProperty)propertyIterator.next();
            localAccessAnnotation = (Access)xProperty.getAnnotation(Access.class);
            if (localAccessAnnotation != null && localAccessAnnotation.value() == javax.persistence.AccessType.PROPERTY) {
                propertyIterator.remove();
                String name = xProperty.getName();
                XProperty previous = (XProperty)persistentAttributesFromGetters.get(name);
                if (previous != null) {
                    throw new MappingException(LOG.ambiguousPropertyMethods(this.xClass.getName(), HCANNHelper.annotatedElementSignature(previous), HCANNHelper.annotatedElementSignature(xProperty)), new Origin(SourceType.ANNOTATION, this.xClass.getName()));
                }

                persistentAttributeMap.put(name, xProperty);
                persistentAttributesFromGetters.put(name, xProperty);
            }
        }

    }

    private void collectPersistentAttributesUsingClassLevelAccessType(LinkedHashMap<String, XProperty> persistentAttributeMap, Map<String, XProperty> persistentAttributesFromGetters, List<XProperty> fields, List<XProperty> getters) {
        Iterator var5;
        XProperty getter;
        if (this.classLevelAccessType == AccessType.FIELD) {
            var5 = fields.iterator();

            while(var5.hasNext()) {
                getter = (XProperty)var5.next();
                if (!persistentAttributeMap.containsKey(getter.getName())) {
                    persistentAttributeMap.put(getter.getName(), getter);
                }
            }
        } else {
            var5 = getters.iterator();

            while(var5.hasNext()) {
                getter = (XProperty)var5.next();
                String name = getter.getName();
                XProperty previous = (XProperty)persistentAttributesFromGetters.get(name);
                if (previous != null) {
                    throw new MappingException(LOG.ambiguousPropertyMethods(this.xClass.getName(), HCANNHelper.annotatedElementSignature(previous), HCANNHelper.annotatedElementSignature(getter)), new Origin(SourceType.ANNOTATION, this.xClass.getName()));
                }

                if (!persistentAttributeMap.containsKey(name)) {
                    persistentAttributeMap.put(getter.getName(), getter);
                    persistentAttributesFromGetters.put(name, getter);
                }
            }
        }

    }

    public XClass getEntityAtStake() {
        return this.entityAtStake;
    }

    public XClass getDeclaringClass() {
        return this.xClass;
    }

    public AccessType getClassLevelAccessType() {
        return this.classLevelAccessType;
    }

    public Collection<XProperty> getProperties() {
        this.assertTypesAreResolvable();
        return Collections.unmodifiableCollection(this.persistentAttributeMap.values());
    }

    private void assertTypesAreResolvable() {
        Iterator var1 = this.persistentAttributeMap.values().iterator();

        XProperty xProperty;
        do {
            if (!var1.hasNext()) {
                return;
            }

            xProperty = (XProperty)var1.next();
        } while(xProperty.isTypeResolved() || discoverTypeWithoutReflection(xProperty));

        String msg = "Property " + StringHelper.qualify(this.xClass.getName(), xProperty.getName()) + " has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type";
        throw new AnnotationException(msg);
    }

    private AccessType determineLocalClassDefinedAccessStrategy() {
        AccessType hibernateDefinedAccessType = AccessType.DEFAULT;
        AccessType jpaDefinedAccessType = AccessType.DEFAULT;
        org.hibernate.annotations.AccessType accessType = (org.hibernate.annotations.AccessType)this.xClass.getAnnotation(org.hibernate.annotations.AccessType.class);
        if (accessType != null) {
            hibernateDefinedAccessType = AccessType.getAccessStrategy(accessType.value());
        }

        Access access = (Access)this.xClass.getAnnotation(Access.class);
        if (access != null) {
            jpaDefinedAccessType = AccessType.getAccessStrategy(access.value());
        }

        if (hibernateDefinedAccessType != AccessType.DEFAULT && jpaDefinedAccessType != AccessType.DEFAULT && hibernateDefinedAccessType != jpaDefinedAccessType) {
            throw new org.hibernate.MappingException("@AccessType and @Access specified with contradicting values. Use of @Access only is recommended. ");
        } else {
            AccessType classDefinedAccessType;
            if (hibernateDefinedAccessType != AccessType.DEFAULT) {
                classDefinedAccessType = hibernateDefinedAccessType;
            } else {
                classDefinedAccessType = jpaDefinedAccessType;
            }

            return classDefinedAccessType;
        }
    }

    private static boolean discoverTypeWithoutReflection(XProperty p) {
        if (p.isAnnotationPresent(OneToOne.class) && !((OneToOne)p.getAnnotation(OneToOne.class)).targetEntity().equals(Void.TYPE)) {
            return true;
        } else if (p.isAnnotationPresent(OneToMany.class) && !((OneToMany)p.getAnnotation(OneToMany.class)).targetEntity().equals(Void.TYPE)) {
            return true;
        } else if (p.isAnnotationPresent(ManyToOne.class) && !((ManyToOne)p.getAnnotation(ManyToOne.class)).targetEntity().equals(Void.TYPE)) {
            return true;
        } else if (p.isAnnotationPresent(ManyToMany.class) && !((ManyToMany)p.getAnnotation(ManyToMany.class)).targetEntity().equals(Void.TYPE)) {
            return true;
        } else if (p.isAnnotationPresent(Any.class)) {
            return true;
        } else if (p.isAnnotationPresent(ManyToAny.class)) {
            if (!p.isCollection() && !p.isArray()) {
                throw new AnnotationException("@ManyToAny used on a non collection non array property: " + p.getName());
            } else {
                return true;
            }
        } else if (p.isAnnotationPresent(Type.class)) {
            return true;
        } else {
            return p.isAnnotationPresent(Target.class);
        }
    }

    private static boolean mustBeSkipped(XProperty property) {
        return property.isAnnotationPresent(Transient.class) || "net.sf.cglib.transform.impl.InterceptFieldCallback".equals(property.getType().getName()) || "org.hibernate.bytecode.internal.javassist.FieldHandler".equals(property.getType().getName());
    }
}

我们再尝试生成表,发现字段的顺序和实体类中定义的字段一致了。

解决 Springboot Jpa 自动创建表 和字段乱序问题[凤凰小哥哥] 产生原因:因为使用 jpa 自动创建表的时候,采用的是TreeMap的,我们要变成LinkedHashMap 的结构。 解决方案:在项目下java文件夹下创建包名为: org.hibernate.cfg  ,创建类: PropertyContainer [包名,类名一定要相同哦] 立即下载

相关推荐

【清华大学软院】15-19年推免试题历年整理

整理的题目为清软预推免机试(外校)硕士机考题目。 年代 题目1 题目2 题目3 2019 质因数分解 二叉搜索树 区间DP(折叠字符串) 2018 日期转换 高精度模拟 区间DP(戳气球) 2017 进制素数 被遗漏的数字 DP(收集苹果) 2016 大数运算 DP DFS 2015 进制素数: http://acm.hdu.edu.cn/showproblem.php?pid=1230 2017年题目(这个是找的最准确的题目): 1题见【链接】 2题见【链接】

云端筑梦师 2254

最简单解决jpa自动生成表后字段乱序问题

首先为什么会出现乱序,因为其源码中使用了TreeMap俩存储实体类字段,而TreeMap是无序的,所以出现了乱序问题 所以通过修改源码就可以解决问题了 在包结构src/main/java 下 创建一个和源码一样的报名和类 然后把对应类的源码复制过来,用替换功能 把全部的 TreeMap 替换成 LinkedHashMap,这样 再生成表,字段就变成有序了 ...

qq_43060570的博客 1358

【库卡机器人】接线步骤

准备X11插头接线,X11插头可以接入机器人外部安全回路接线,其中外部使能信号线也接在此接口上,如果机器人系统没有配置外部使能装置,那个此接口上的外部使能信号端须短接,短接规则为:20-21、23-22、31-30、33-32。持续按住使能键,保持使能上电状态,分别按住示教器右侧每个轴对应的+或-按键,测试机器人每一个轴是否能正常运行,如果一切正常,说明机器人控制正常,机器人可以正常使用。将一根黄绿色等电位线接入其中的一个接地端,并与机器人的接地端相连,使得控制柜与机器人等电位。

qq_45161762的博客 9439

[JavaWeb] SpringBoot Jpa 自动创建表 字段乱序 解决方案

[JavaWeb] SpringBoot Jpa 自动创建表 字段乱序 解决方案

weixin_46020146的博客 252

PADS VX2.7学习记录05-PADS Layout设计文件Gerber等输出整理

在“PDF Document”栏中,依次选中除REF-TOP和REF-BOT之外的文件,单击图标,将其余PDF Document文件进行删除,如图所示。然后单击【生成PDF】按钮,即可创建一份PDF格式的位号图。

tianpu2320959696的博客 1023

Orin+ GMSL (Ser 9295+Des 9296)流程分析(1)

orin gmsl

乐于分享 2652

JPA 使用过程中问题汇总(持续更新...)

JPA save数据时,如果数据没有赋值,即使数据库层面设置了default值,但仍然会插入null 增加表中一个字段时的sql如下: ALTER TABLE account ADD status tinyint(1) DEFAULT b'1' COMMENT '是否加入黑名单'; 调用jpa的save方法时,并没有build实体类中status,即没有给该字段赋值,导致入库的值是空值,而不是预想中的1。 所以,修改为save时传true。sql保证的是原生sql insert时会设置默认值,使用JPA时

Willow的博客 3390

ABAP 后台作业里的消息机制:把 MESSAGE 写对,避免作业莫名取消

SAP后台作业消息处理机制解析 本文深入剖析了SAP系统中后台作业的消息处理机制,揭示了前台与后台执行环境的关键差异。核心发现包括: 后台作业对消息的处理规则: 所有消息写入Job log而不显示 根据消息类型决定是否继续执行 W警告在列表处理阶段会被自动转为E错误 关键异常处理: 通过error_message可捕获E/A类型消息 A类型消息会触发隐式数据库回滚 未被捕获的E/A消息将导致作业中断 实用解决方案: 将业务提示改为S或I类型 使用DISPLAY LIKE保持前台体验 通过error_mess

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2216

Java jpa自动建表 危害,SpringDataJPA自动建表字段顺序优化

JPA 自动建表字段顺序优化1、表字段顺序和实体类定义字段顺序一致原理:复制一个 hibernate 包下的 PropertyContainer 类,修改其中 persistentAttributeMap 的类型,TreeMap 修改为有序的 LinkedHashMap,在下次类加载时,会优先加载我们定义的类。2、自定义继承类字段顺序原理同上就不说了。一般我们的实体类会继承一个父类,父类中有 id...

weixin_32801895的博客 1063

26、多级快速多极子算法(MLFMA)在大规模电磁问题中的应用

本文探讨了多级快速多极子算法(MLFMA)在大规模电磁问题中的高效应用。通过分层分区策略,MLFMA在分布式内存架构上实现了高效并行化,能够求解包含数亿未知数的复杂电磁问题。文章分析了介质球体、半球透镜、周期性结构和损耗介质阵列等典型案例,验证了MLFMA的高精度与广泛适用性。同时,MLFMA被应用于实际场景如隐身目标Flamme的外部共振分析和含分裂环谐振器的超材料设计,展示了其在航空航天、超材料和生物医学等领域的广阔前景。未来发展方向包括算法优化、多物理场耦合和实时计算,进一步拓展其应用潜力。

t8u9v0w1x的博客 117

优化dalsa相机检测界面

上节实现了使用qt结合dalsa相机显示检测到缺陷的画面,由于窗口过于简陋,本节将进行一个界面优化。

A1983Z的博客 986

Hibernate(JPA)中实体类变量与表中字段顺序不一致问题

在使用JPA的过程,当使用spring.jpa.hibernate.ddl-auto=update属性时,我们是能在数据库中创建实体类所对应的表,但是却发现表中字段的顺序和实体类中变量的顺序不一致。作为一名爱思考(装b)的程序猿,我觉得是时候展现我真正的实力了。作为一名爱读源码的程序猿,我先打开了hibernate的源码包位置,如图: 接下来,就开始思考(Google),这么多我读个锤子哦。...

cauchy6317的博客 3743

【2.12】基于FPGA的Gardner环开发5——闭环反馈,获得完整gardner环

本文介绍了Gardner定时恢复算法在FPGA上的实现过程。首先回顾MATLAB程序中Gardner环的闭环反馈机制,重点分析了环路滤波器输出变量w的处理流程。随后详细阐述了FPGA实现的Verilog设计步骤,包括三个核心模块:1)y_temp=q0-w计算模块,实现反馈变量处理;2)uk=2*q0计算模块,生成插值系数;3)插值计算模块,根据使能信号执行线性插值运算。设计通过引入使能信号控制插值更新时机,采用定点数运算处理数据,并包含负数保护机制确保计算稳定性。文章提供了完整的Verilog代码实现,展

fpga/matlab/simulink算法仿真工程 135

Springboot Jpa按照顺序生成数据库表字段

用JPA自动生成数据库表后,字段为乱序,非Entity实体类中的顺序,原因:官方hibernate为TreeMap,乱序排列 解决策略:在main包下新建org.hibernate.cfg包,包下复制以下代码(只将TreeMap改为LinkedHashMap),运行后即可生成的表字段既是顺序排列的字段 package org.hibernate.cfg; import java.util.*; import javax.persistence.Access; import javax.pe...

KimballYue的博客 2728

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

jpa 不自动建表_解决SpringDataJpa实体类中属性顺序与数据库生成字段顺序不一致

一、在application.yml配置中添加数据库根据实体类自动创建数据库表的配置(这里数据库采用MySQL数据库)jpa: database: MYSQL show-sql: true #Hibernate ddl auto (validate|create|create-drop|update) hibernate: ddl-auto: update ...

weixin_39713538的博客 610

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

spring jpa 自动建表 字段乱序 字段 顺序

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34321753的博客 6636

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Hribernate(JPA) 生成表列顺序与实体类字段声明顺序不一致解决方案

本文介绍了Hibernate框架中由于Java反射API不保证字段顺序,导致数据库表列顺序与实体类声明不一致的问题。解决方案是通过覆盖Hibernate核心类PropertyContainer,将其内部使用的TreeMap替换为LinkedHashMap来保持字段顺序。具体步骤包括:确定Hibernate版本、定位源码路径、创建同名类文件并修改关键数据结构,利用类加载机制实现覆盖。该方法通过改变集合遍历顺序,最终影响DDL语句生成顺序。涉及的关键技术点包括Java类加载机制(双亲委派原则)、TreeMap与

JulyDragon的博客 321

jpa多表关联条件查询实现

通过实体类映射实现多表关联条件查询 jpa对于多表关联可以在实体类中进行关联映射,一对一用@OneToOne,一对多用@OneToMany,多对多用@ManyToMany,多对一用@ManyToOne,具体实体类配置就不多说了,然后对于条件查询采用Specification对象进行封装,如下 Specification<A> specification = new Specification<A>() { @Override public Predic

weixin_37783650的博客 8574

JPA原生sql返回值转自定义实体类

有两个月没更新过优快云了,裸辞了,半个月前刚入职了新下家,这里适应下新公司的项目技术。 持久层用的是之前没用过的jpa,还好平时多多少少也有学过,上手也快。 用jpa写原生sql的时候,真的想骂人,各种问题。可是jsql又不支持sql的一些函数,只能写原生sql。 这里就先记录第一个坑,用jpa注解查询完之后发现无法用以往的实体类直接映射接收,百度谷歌无果... 这里实...

954L 7805

jpa生成字段顺序和实体类保持一致

已经新建生成的字段顺序不会被改变!!! 在java目录下新建一个包:org.hibernate.cfg 上代码,复制进去就能用: package org.hibernate.cfg; import org.hibernate.AnnotationException; import org.hibernate.MappingException; import org.hibernate.annotations.ManyToAny; import org.hibernate.annotations.Targ

weixin_43826336的博客 857

JPA原生查询部分字段映射

最近在写一个定时删除文件的需求,文件的路径是在数据表中,于是撸起袖子就直接获取数据库中的数据,然后拿到路径就直接可以去做删除操作了了。但是写完后发现有些问题,在使用JPA查询符合条件的数据的时候,直接把表中的所有字段的值都拿出来了,但是对于我这个需求来说,似乎只是用到了file_path和image_path字段,于是想弄个实体类,只保存这两个字段就好了。(由于hibernate不是很熟悉,所以目前都是用原生sql解决一些查询问题) 查阅资料和网上一些大佬的博客后,总结了两种方法 (为了方便,测试的代码写在

qq_33693776的博客 2904

JPA注解介绍

JPA 注解的几个要点  1.设置Pojo为实体 @Entity //标识这个pojo是一个jpa实体 public class Users implements Serializable{ }  2.设置表名 @Entity @Table (name= users ) //指定表名为users public class Users implements Serializable{ }  3

一个人的博客 1万+

SpringDataJpa实体类中属性顺序与数据库中生成字段顺序不一致的问题

于是就一步步跟踪下去,终于在一个地方发现了一个问题:org.hibernate.cfg包下的PropertyContainer类在取fields的时候是使用TreeMap来保存的,于是试着改了下,将这个里面的所有TreeMap改成了LinkedHashMap,编译通过,打包,测试。翻了翻源码发现,很多地方都是使用LinkedHashMap或者是List来传输Entity里面的fields,于是感觉Hibernate应该是考虑到使用Entity里面定义的fields的顺序来实现建表语句里的表字段顺序的。

weixin_41800760的博客 318

hibernate 自动生成数据库表和java类 字段顺序不一致 这导致添加数据库数据时 异常

【代码】hibernate 自动生成数据库表和java类 字段顺序不一致 这导致添加数据库数据时 异常。

- 467

解决jpa自动建表字段乱序问题

工程下新建如图文件 package org.hibernate.cfg; import org.hibernate.AnnotationException; import org.hibernate.annotations.Any; import org.hibernate.annotations.ManyToAny; import org.hibernate.annotations.T...

MadCode2222222222222的博客 1724

JPA实体类中的注解

JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。  JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它不囿于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范.  JPA的总体思想和现有hibernate、TopLin

take_OO的博客 1028
上一篇: java线上问题排查:进程假死或者oom killed
下一篇: JPA分页模糊查询
程序员青戈
程序员青戈 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄10年 3万+粉丝 250原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

程序员青戈

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值