java临时对象持久对象_Java对象持久性:联盟状态

java临时对象持久对象

在这个虚拟小组中,InfoQ.com(Floyd Marinescu)和ODBMS.org(Roberto V. Zicari)的编辑询问了一组领先的持久性解决方案架构师,以他们对Java社区中持久性联盟的当前状态的看法。

小组成员:
  • Mike Keith :JPA 1.0联合规范负责人,架构师,Oracle TopLink和Java持久性技术
  • Ted Neward :独立顾问,经常撰写有关ORM和持久性主题的博客
  • 卡尔·罗森伯格(Carl Rosenberger) :db4objects(开放源代码可嵌入对象数据库)的首席架构师
  • Craig Russell :Java数据对象(JDO)JSR的规范负责人,在Glassfish之前,Sun的应用服务器中的实体bean引擎的架构师。
问题:
  1. 我们还有“阻抗失配问题”吗?
  2. 就您在该行业中使用的内容而言,您将如何定位可用于新项目持久性的各种选项?
  3. 您认为这些现有解决方案的优缺点是什么?
  4. 您是否相信对象关系映射器是解决“对象持久性”问题的合适解决方案? 如果是,为什么? 如果没有,为什么?
  5. 您是否相信关系数据库系统是解决“对象持久性”问题的合适解决方案? 如果是,为什么? 如果没有,为什么?
  6. 您是否相信对象数据库系统是解决“对象持久性”问题的合适解决方案? 如果是,为什么? 如果没有,为什么?
  7. 在接下来的12个月中,您希望在对象持久性领域进行一项新的研究/开发吗?
  8. 如果你们全都强大并且可以在过去10年中影响技术的采用,那么今天的典型项目将用作持久性机制,为什么?
  9. 关于这个话题还有别的话吗?

Q1:我们还有“阻抗不匹配问题”吗?

迈克·基思(Mike Keith) :只要使用对象模型来读取和写入关系数据模型,那么阻抗失配就会存在。 当没有策略,技术或工具可帮助克服失配时,或者当失配导致复杂的设计或极差的性能时,这将成为一个问题。 仅由于不匹配的性质,总会有一些情况导致这种情况。 技术和工具可以提供很大的帮助,并且可以满足绝大多数应用程序的需求,但是它们不能将水变成酒。

泰德·纽亚德(Ted Neward) :好的。 只要我们对瞬态和持久性形式的数据具有不同的“形状”,例如当前的困境,我们试图以对象的形式获取瞬态数据并将其存储到关系持久性数据存储中,那么我们将具有阻抗不匹配问题。 对象到关系,对象到层次/ XML,层次到关系,它们都是阻抗不匹配的问题,并且最终都面临着相同的基本问题:将圆形物体打成正方形或三角形的Kong。 一种解决方案是将这些不同的“形状”整合到我们的工具中,例如将集合作为一流的概念添加到我们的编程语言中,以使其更易于在数据存储中使用集合,但是即使如此,我们也只能这样做。远。

卡尔·罗森伯格(Carl Rosenberger) :不,除非您对关系数据库有所了解,让我们从使用两种特定语言Java和SQL的角度来看一下:

在Java中,通过编写易于理解的小型,简单而简洁的方法,可以提高工作效率。 在关系数据库中,没有导航的概念,您必须深刻了解表架构才能从数据库中获取任何信息。 假设您想找出一名员工老板的薪水。 使用具有自动完成功能的Java和IDE,您可以在几秒钟内编写如下代码:

employee.department().manager().salary();

使用SQL,可能要花几分钟的时间才能找出同一任务SQL语句...

SELECT e2.salary FROM
employee e1, employee e2, department,
WHERE
e1.id = current_employee_id
AND
e1.department = department.id
AND
department.manager = e2.id

...并且您确定语法正确并且没有混淆对employee表的两个引用吗?

当您必须同时使用Java和SQL编写应用程序时,您会浪费两种截然不同的语言之间的接口的开发时间,质量,效率和性能。

维护两个截然不同的代码库的开销使所需工作增加了一倍以上,并且抑制了重构和敏捷过程。

如果您通过使用对象数据库完全采用对象技术,则不会出现阻抗不匹配的情况。

Craig Russell :这取决于您的业务领域和您的语言。 如果您使用C ++进行工作并利用多重继承来为您的域建模,那么将域对象存储在关系数据库中的工作仍然很多。

最重要的因素是您是要使用Java域对象来表示数据库中已经存在的内容,还是要使用数据库来存储Java域对象。 在前一种情况下,大多数关系模式可以用Java域对象很好地表示。 如果您试图将Java域对象存储在关系数据库中,则不匹配的可能性更大。

在这种情况下,仍然存在一些阻抗不匹配的区域。 例如,对集合建模 在关系模式中很难。 在ODMG中,我们对Bag建模,它与Java Collection在逻辑上等效。 在Java Collection Framework中,没有具体的类具有正确的Bag语义。 最接近的是ArrayList,但是在保留此类型时,必须人为创建额外的信息(处理重复项意味着在数据库中引入人为的列或使用没有主键的表)。

阻抗不匹配的另一个方面是继承。 关系模式与Java概念并不完全匹配,尽管实际上许多关系模式都包含一个区分符列,用于区分一个子类型的行和另一个子类型的行。 该技术早于现在存在的许多对象关系映射解决方案。

问题2:就您所看到的行业使用而言,您将如何定位可用于新项目持久性的各种选项?

迈克·基思(Mike Keith) :如果您从一个假设开始,即绝大多数项目都需要数据存储作为关系数据库,那么人们的持久性需求通常最终会落入3类中的1类。 总是有一些极端的情况和一些微小的变体,但是这3个类别几乎包含了持久化Java对象的主流应用程序:

  1. JDBC-由于各种原因,许多开发人员仍依赖JDBC。 也许他们不需要或不需要映射层,或者他们的雇主根本不允许这样做。 无论出于何种原因,JDBC仍然是可行的选择,并且以适当的方式(正确的原因)使用JDBC可能适合某些应用程序。
  2. 轻量级和自定义框架 -有时需要手工编写SQL的人发现,如果在其上放置一个薄层,则可以提高代码的可读性和可维护性。 对于这些应用程序,一个简单的JDBC框架或适合该应用程序的开发和编码实践的本地解决方案就可以满足要求。
  3. ORM-对象关系映射工具包括一个映射元数据模型,用于指示对象状态如何存储到数据库中以及如何从数据库中查询。 有很多人对ORM技术感到满意,并使用它来满足他们的需求。 Java Persistence API(JPA)是Java EE和非企业Java环境中的标准ORM API。

随着SOA的普及,仅需要将Java对象发送到XML接收器的一类应用程序。 接收器可能最终采用Web服务端口,BPEL流程或队列的形式供以后处理。 将对象映射到XML的能力已由JAXB和SDO之类的标准解决,并且有诸如Eclipse Persistence Services之类的项目实现了所有这些标准,此外还添加了更多功能。

泰德·纽亚德(Ted Neward) :显然有多种选择,每种选择都有其优点和缺点。 Mike在总结三个核心选项方面做得很好,我还要添加几个:

  1. 存储过程,我们将所有存储和检索逻辑(有时还需要以数据为中心的业务逻辑)放入数据库内部的可执行代码中,任何应用程序(以Java,C ++,C#或Ruby编写)都将受到该存储过程的约束相同的集中式逻辑。 这通常与直接的JDBC /调用级别接口方法或O / RM结合使用,以简化调用sproc和获取结果的过程。
  2. 对象数据库(OODBMS),将实际对象本身存储到数据库中,卡尔对此进行了详细介绍。

自然地,有多种混合方法可以实现上述目的,但这通常是它的拆分方式。

卡尔·罗森伯格(Carl Rosenberger) :当人们谈论数据库时,它们通常是指为许多不同的用户,应用程序和编程语言提供服务的企业数据库。 对于这些旧数据库,SQL将存在很长一段时间。

在不久的将来,我们将拥有50亿部手机和20亿台PC。 设备上的应用程序(和设备上的数据库!)市场将超过PC的市场。

对于设备上的数据库,通常:

  • 他们只提供一种编程语言
  • 没有DBA可以调整访问权限,
  • 用户不会手动在其设备中键入即席查询。

如果设备上的应用程序是用面向对象的语言编写的,那么是否有任何单一的理由使用关系数据库或SQL?

我不这么认为。

微软在LINQ上发表了非常有力的声明:它们不再使用SQL,而是使数据库访问成为编程语言不可或缺的概念。

这是新项目的未来,仅因为这是开发和维护代码的最有效方法。

随着LINQ的采用,功能语言概念将成为查询数据库的公认主流标准。

我自己参与了对象数据库的开发,对此我感到非常高兴。 对我们来说有趣的部分:LINQ允许在查询中使用普通的C#方法调用:您可以进行导航。 由于对象数据库在物理上存储的对象与其在RAM中的表示非常相似,因此对象数据库可以比关系数据库更好地优化LINQ。 在对象数据库可以使用直接指针进行导航的情况下,关系数据库需要维护和查找两个索引,以便能够通过联接进行查询。

LINQ是对象数据库供应商的梦想。 突然之间就有了查询对象数据库的标准,而到目前为止,它比任何关系系统都要好。

我们希望看到像LINQ for Java这样的标准。 使用本机查询,我们提供了一种非常相似的方法:我们可以使用100%纯Java来制定数据库查询。

在我们看到我们的产品具有强大吸引力的领域中,我可以最好地判断行业的需求:

  • 资源受限的设备的应用程序,其中高性能必须伴随着低内存消耗,
  • 具有许多属性和/或深层继承层次结构的复杂类的应用程序,
  • 经常重构类,维护关系数据库和映射的应用程序将是一场噩梦,
  • 需要很快上市的应用程序,
  • 富客户端应用程序,使用诸如Eclipse RCP,JavaFX或Silverlight之类的技术编写。

由于我们似乎在这些领域拥有最幸福的用户,因此我得出结论,这就是当今对象数据库最能发挥其优势的地方。

Craig Russell :Java和SQL的最低抽象层是无处不在的JDBC编程模型。 它提供了最佳的控制级别,并允许您利用驱动程序和数据库的所有功能。 但这也是最难解决的问题,并且不适合抽象。

许多程序员发现使用库来实现池化资源可以提高性能而不必编写更多代码,但这是正确使用SQL的难点。 处理准备好的语句和结果集仍然是一个挑战。

在诸如iBATIS之类的工具中找到了更高的层次,它消除了处理准备好的语句和结果集的繁琐工作,但是仍然需要编写SQL,SQL高度依赖数据库,并且仍然需要使用映射的域对象的工作。

在对象关系映射解决方案(例如企业Java Beans容器管理的持久性,JPOX,OpenJPA,Hibernate,TopLink和Cayenne)中找到了我在Java中了解的最高级别的工具。 Java Persistence API和JDO是由许多这些解决方案实现的JCP标准。 这些工具具有很高的自动化水平,并且既可以从数据库模式创建Java域类,也可以从Java域对象创建数据库模式。

如果您不使用Java语言,则Grails和Ruby on Rails之类的工具将提供非常高的功能,并且还提供了Web框架实现,使程序员摆脱了手工编写往返于Web服务器的每次调用的繁琐工作。

问题3:您认为这些现有解决方案的优缺点是什么?

迈克·基思(Mike Keith) :这是一本关于大书的问题,一本可以无限期地讨论何时以及在何处使用一本相对于另一本。 简短的版本是我相信它们都有自己的位置,并且没有一种解决方案会成为所有应用程序的最佳选择。 我唯一的希望是,人们在选择计划花费多达30%的应用程序资源的解决方案之前会做一些功课。

泰德·纽德(Ted Neward) :这是一个很长的答案,比我在这里所说的要容易得多。

Carl Rosenberger :面向对象实践的主要优势之一是它们减少了长期维护的成本。 如果使用对象数据库,则可以将此优势扩展到数据模型(您的类,其他什么)以及与之交互的所有代码。

使用对象数据库,所有代码都可以用一种编程语言编写。 使用现代IDE,重构可以完全自动化。

对象数据库允许100%的代码在编译时检查,其中包括与数据库交互的所有代码。

由于对象数据库可以以与虚拟机在RAM中使用虚拟机完全相同的方式来处理对象引用(使用单向指针,而不是索引元组),因此对象数据库比关系数据库要快得多。

与应用程序在同一VM中运行的本机嵌入式对象数据库允许对数据库中的瓶颈用例进行概要分析和调整。 这使得它们成为手机和手持设备上嵌入式应用的理想选择,因为这些设备的机器性能和内存有限。

SQL是众所周知的。 有悠久的历史的成熟SQL数据库可供选择,并且有许多成熟的工具可帮助编写,调整和查询SQL系统。

对于临时查询和临时聚合数据,SQL是可接受的标准。

Craig Russell :通常,您的抽象级别越高,编写和部署应用程序的速度就越快。

但是,要想从数据库投资中获得最大的性能收益,某些应用程序将需要直接使用SQL。

因此,您无法完全理解数据库提供程序接受的特定SQL方言。 但是,大多数工具都允许您在较高的抽象水平上完成大部分工作,只需要深入研究SQL中的极端情况即可。

Q4:您是否认为对象关系映射器是解决“对象持久性”问题的合适解决方案? 如果是,为什么? 如果没有,为什么?

Mike Keith :在当今世界中,绝大多数公司数据都生活在关系数据库中,而面向对象的编程范例已成为应用程序开发的规范,对象关系映射技术既是现实也是必需品。 由于这个现实,问题实际上并不是解决对象持久性问题的方法,而是如何解决大约97%的应用程序开发场景中存在的问题,在这些场景中,应用程序是用Java编写的,并且必须从Java中检索和存储其数据。关系型数据库。 到目前为止,对象关系映射是出现的最灵活,最实用的解决方案。 合适吗 当然,这是针对成功使用它的数十个人的。 普遍来说,这是最好的解决方案吗? 我很确定,如果您问了足够多的人,您会对此有所不同。

Ted Neward :我认为他们为那些愿意将生产力和易于开发性放在性能和关系可访问性之上的开发人员工作。 不幸的是,一个项目常常发现放弃性能或可靠的关系模型和可访问性并不像开发人员所认为的那样可接受,并且到那时,通常现在就来不及用更“关系友好”的东西轻松替换O / RM了。主要的重构和重写。

Carl Rosenberger :OR映射器是一种解决方法。 在某种程度上,它们有助于减少手工编写SQL的工作。

没有任何解决方法都是免费的。 这是OR映射工具比理想情况差的三个方面:

  • 性能
    OR映射工具使应用程序变慢。 需要将对象完全加载到内存中才能运行面向对象的业务逻辑。
  • 复杂
    OR映射器通过缓存和传输对象的方式引入了自己的副作用。 开发人员会花一些时间来了解其OR映射工具在并发方案中的行为。
  • 设计约束
    没有任何OR映射工具可以处理OO编程语言提供的所有构造,这仅仅是因为在关系世界中并非所有构造都具有相同的含义。 在设计应用程序类模型以使其与OR映射工具配合使用时,始终必须权衡取舍。

解决方法永远不能解决问题。 在找到真正的解决方案之前,它们只是中间步骤。

Craig Russell :对于许多应用程序,ORM是一个非常好的工具,它可以平衡开发人员的需求和管理数据库数据中心资源的需求。 在仔细控制和管理数据库架构的地方,这一点最为明显。 在另一个极端,当应用程序程序员通过编写Java类并从中生成Java模式来控制数据库模式时,一个很大的危险是应用程序将无法正常运行,并且重新设计域类以生成正确的模式可能很困难。 ,然后数据迁移成为一个问题。

问题5:您是否认为关系数据库系统是解决“对象持久性”问题的合适解决方案? 如果是,为什么? 如果没有,为什么?

Mike Keith :同样,关系数据库通常不是答案,而是问题。 除非您是开发绿色应用程序的全新公司,否则该应用程序将不得不从关系数据库中获取其数据。 实际上,由于技术的成熟以及可伸缩性和可靠性的记录,大多数全新的应用程序甚至将关系数据库用于存储。 问题是如何访问该关系数据库中的数据,又如何以诸如Java之类的面向对象语言编写业务逻辑?

Ted Neward :我认为它们是否合适,正是由于各种原因,现代IT基础架构期望并需要将企业范围的数据存储在关系数据库中的要点,开发人员需要找到获取对象的方法到这些数据中。 但是,通常不需要直接从用户界面执行此操作,然后以批量或定期方式更新关系存储的中间对象数据库可以大大提高开发过程中的生产率。

Carl Rosenberger :否。阻抗不匹配是问题,而不是解决方案。

Craig Russell :是的,与任何Java to DB工具一起使用。

Q6:您是否认为对象数据库系统是解决“对象持久性”问题的合适解决方案? 如果是,为什么? 如果没有,为什么?

Mike Keith :对象数据库就像20世纪的betamax。 他们做得很好,但是没有赶上。 它们之所以被边缘化,并不是因为它们确实可怕,不易使用或速度慢(尽管确实确实是其中的全部),而是因为它们无法满足公司的不同应用需求。 尽管IT应用程序在功能和用于构建它们的技术方面不断变化,但它们访问的数据几乎保持不变。 必须从所有技术和应用程序中轻松访问数据,这是关系数据库必须满足的要求,但对象数据库却不能做到。

Ted Neward :当然,只要非对象技术不需要直接访问OODBMS中存储的数据即可。 这仍然是OODBMS的最大缺点。

卡尔·罗森伯格 :当然。 哪个问题? 使用对象数据库,您只需一行代码即可存储任何对象。 没有其他维护表和映射的工作。 查询是编程语言的组成部分。 像所有其他代码一样,与数据库交互的代码是类型安全的,经过编译时检查且可自动重构的。

Craig Russell :对象数据库市场更多地与应用程序领域有关,而不是与用于访问它的编程模型有关。 对象数据库的许多基本原理是具有特定域模型和工作负载的系统性能。 对于极其苛刻的应用程序,对象数据库的性能要比关系系统好几个数量级。 在这些情况下,挑战往往是围绕对象数据库的工具,例如查询和报告生成工具,事件传播,与其他数据库的同步以及故障保护操作。

问题7:您希望在接下来的12个月中在对象持久性领域进行一项新的研究/开发吗?

Mike Keith :数据可以生存多长时间真是令人惊讶。 数据生存的问题之一是,发明的专有存储方案(仍然是在关系数据库流行之前就创建的)必须仍然用于访问数据。 询问系统集成商他们要处理什么,您可能会得到比讨价还价更长的讨论时间。

此外,XML已成为一种全球数据语言,因此事实证明,这个时代的面向服务的对象需要定期将形状从对象变为XML到关系记录,甚至是时髦的自定义数据存储中的记录。 明年或更长时间的研究将必须以一种使开发人员满意的方式来解决该问题。 统治所有的持久性将不是一个持久性,而是希望有一套统一的持久性解决方案,这些解决方案是一致的,集成的并提供每个级别所需的。

Ted Neward :将关系和集合论概念集成到编程语言中。

卡尔·罗森伯格

(1)合并面向对象和功能语言

我喜欢函数式编程语言,因为它们的功能强大的概念可以与列表推导的集合对抗。 我仍然相信对象是表示状态的最好方法。

对于合并功能概念和面向对象的编程语言,我看到了光明的未来。 Scala和LINQ都是朝着正确方向迈出的重要一步。

分析列表推导并针对数据库索引运行列表推论并不是火箭科学。 从概念上讲,这与db4o本机查询非常相似。 我希望我们可以通过Scala列表理解来尝试....如果没有,我确定我们社区中的某个人会这样做。

(2)新的并发概念

走向多核的硬件开发趋势将需要新的编程语言概念来处理并发性。

软件事务存储和参与者是主流编程语言中可能会采用的两种很棒的方法。 两种方法都应考虑如何将它们与数据库处理最佳集成。

(3)管理状态

在面向对象的世界中,我们在客户端和分布式系统上都有状态:对象。

我惊奇地看到很少有数据库研究关于如何使客户机上的对象与服务器上的提交状态保持同步的问题。

关系数据库提供了隔离读取和锁定的概念,但它们不能解决真正的问题。 它们就像在客户端上没有任何状态一样工作。 这是阻抗失配的另一方面。

在并发世界中,我不相信锁定。

我认为,可以通过将更改推送给客户端或使用在特定时间点上一致的对象版本来更好地解决问题的根源。

以经验方式测试这两种方法以找到一种或另一种方法效果更好的标准以及原因所在将非常有趣。

Craig Russell :工具和应用程序的生成,尤其是与前端脚本代码生成的集成,仍然是对象持久性的弱点。

问题8:如果你们都强大,并且可以在过去10年中影响技术的采用,那么今天的典型项目将用作持久性机制,为什么?

Mike Keith :我本来应该将EJB变成POJO模型,并且使世界摆脱了8年的痛苦。 我也可以在Smalltalk中使用它。 ;-)

泰德·纽亚德(Ted Neward) :我永远不会对一个项目提出解决方案。 “从每种技术,根据其能力,到每个项目,根据其需求。”

Carl Rosenberger :让我们看看未来,而不是过去:为db4objects工作我希望能在以后的10年中有所影响的幸福状态。 今天的新手机和设备项目(Android!)应该使用对象数据库技术(如果尚未这样做的话)。

我不是大型企业数据库的专家,但我怀疑网格数据库的效率几乎无法达到预期。 由于当今大多数成熟的大型数据库引擎都是用C或C ++编写的,并且由于这些语言未提供用于分发和并发的高级概念,因此,我认为这些系统的维护和改进必须非常繁琐且效率低下。

对于一些聪明的人来说,以合理的努力编写世界上最快的大型分布式数据库仍然很可能会很快获得回报。 如果我功能强大,那么我想在某个阶段尝试一下该项目。 也许等到最新出现的并发概念进一步成熟起来才有意义。

关系没有定义:

  • 一致性开始和结束的地方
  • 拥有元组的主副本的人
  • 数据如何在集群中分布
  • 预取如何有意义
  • 数据如何物理群集

原则上,我看到了一些概念的优点,这些概念吸收了编程语言中存在的所有知识并将其转移到数据库中。

从理论上讲,如果所有访问数据库的企业应用程序均以兼容的面向对象语言编写,那么即使对于大型企业数据库,最终采用对象数据库也可能有意义。

理想情况下,将有一个通用的面向对象的域模型,可以在全球所有企业应用程序之间共享。

实际上,我十多年前就考虑过这一点。 如果我功能强大,那么每个人今天都会使用这样的模型。 ...然后毫无疑问,对象数据库是所有应用程序最自然的持久性解决方案。

Craig Russell :今天的典型项目将使用世界一流的IDE以及用于对象持久层的插件,这些插件可以使用关系数据库或对象数据库进行对象存储。

IDE可以生成完整的Web框架代码,包括用于高度交互呈现和用户界面的javascript工件。

Java VM将允许类的通用检测,专门用于更改跟踪和避免供应商特定的字节码转换。 运行时性能工具将动态调整应用程序,而无需人工干预。

Q9:关于此主题有什么别的话吗?

迈克·基思(Mike Keith) :关于对象持久性的有趣之处在于人们对它的热情。 仅仅提到持久性,人们似乎就会振作起来,拔剑,而社区论坛只需要发表一些批判性的观点,就可以在原本静止的时间里获得无休止的评论。

可能是因为持久性对应用程序的性能有如此巨大的影响,或者可能仅仅是因为持久性是如此令人着迷,但是经过18年的研究和在持久性领域中的工作,我仍然觉得值得花时间上。 似乎每个人都同意的一件事是,不注意应用程序持久性方面的开发人员这样做会带来危险。

感谢您的邀请参加。

泰德·纽亚德(Ted Neward) :感谢您的光临

卡尔·罗森伯格(Carl Rosenberger) :我相信仿生学:我们可以从自然界如何解决问题中学到很多东西。 让我们看一下自然是如何组织知识的:它使用许多缓慢的冗余系统(人类),并不断改进高效的通信技术。 任何节点都可以与任何节点通信,并且可以调整连接的方向和强度以匹配当前的需求。

如果我们以此为模型,那么采用并从错误中吸取教训的智能网格计算将是数据库的未来。

现在,这与我上面描述的公共领域模型如何匹配? 我认为很好。 人类有一个共同的面向对象的领域模型,该模型随着时间的推移相对稳定:自然语言。

因为使用了自然语言,所以我们仍然可以阅读和理解几千年前编写的文本。

我们很幸运,古希腊文字未使用OR映射器编写。 进化是一个缓慢而连续的过程。 最终,最好的概念获胜。

感谢您的邀请参加。

Craig Russell :感谢您的邀请参加。

翻译自: https://www.infoq.com/articles/java-object-persistence-panel/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

java临时对象持久对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值