H I B E R N A T E 关联/继承/复合主键配置

  rel="File-List" href="file:///C:%5CDOCUME%7E1%5Cchenyiwu%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"> rel="Edit-Time-Data" href="file:///C:%5CDOCUME%7E1%5Cchenyiwu%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_editdata.mso"> rel="OLE-Object-Data" href="file:///C:%5CDOCUME%7E1%5Cchenyiwu%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_oledata.mso">

优化知识:

Ø         映射对象实体可以序列化,可以通过实现Serializable接口。序列化意味着我们可以在HttpSession中保存实体对象,或者将其通过RMI传输。

Ø         对于实体类最好不要用final修饰,这将导致Hibernate代理机制难以进行,而代理机制则是Hibernate提高性能的主要途径之一。

一、            一对一引用外键设置

1.  主表(StockWrhBusinessBillDO

<one-to-one name="stockPutWrhBillDO" class="relate.model.StockPutWrhBillDO" cascade="all" property-ref="stockWrhBusinessBillDO"/>

 

说明:

property-ref="stockWrhBusinessBillDO" property-ref(可选)被关联从表类中的

对应属性的名字,若没指定,使用被关联类的主键.

Cascade:只在父方设置,有alldeleteupdatenone;表示父方做了操作,子方跟着做同样的操作

所谓父子关系,是指由父方子方的持久化生命周期,子方对象必须和一个父方对象关联;如果删除父方对象,应该级联删除所有的关联的子方对象。如果子方对象不再和一个父方对象关联,应该把这个子方对象删除。

2.从表(StockPutWrhBillDO

<many-to-one name="stockWrhBusinessBillDO"

            class="relate.model.StockWrhBusinessBillDO"

            column="WRH_BUSINESS_BILL_ID"

            insert="true"

            update="true"/>

说明:

Column引用父表的主键字段

Insertupdate如你更新数据(xx,yy),正好数据库有条记录(xx,zz).如果你设置update=true,她就会忽略xx,只更新yy,否则,一并更新,因为做为从表,一般都根据主表的根据主表的更新而一道更新,一般将update设置为true

注意:

因为many-to-one设置了WRH_BUSINESS_BILL_ID的映射,如果在从表映射文件(.hbm.xml文件)中有个字段设置了WRH_BUSINESS_BILL_ID属性,应该把他注释掉或者去掉。如下:

<!-- property name="WRH_BUSINESS_BILL_ID" type="integer">

                <column name="WRH_BUSINESS_BILL_ID">

                     <comment></comment>

                </column>

</property-->

 

二、一对多关联

1.主表(StockWrhBusinessBillDO

<set name="stockWrhBusinessBillDetailDOs"

             table="stock_wrh_business_bill_detail"

             cascade="all"

             inverse="true"

             lazy="false">

 

             <key column="WRH_BUSINESS_BILL_ID"></key>

<one-to-many class="relate.model.StockWrhBusinessBillDetailDO"/>

</set>

说明:

Inverse用于控制反转,将从表被控方转为主控表,当inverse设置为false时,当执行完插入语句,需要对从表附加操作update操作。

Key:key元素的column属性对应从表中,关联的字段

One-to-many对应从表映射的类

2.从表(StockWrhBusinessBillDetailDO

<many-to-one name="stockWrhBusinessBillDO"

              class="relate.model.StockWrhBusinessBillDO"

              column="WRH_BUSINESS_BILL_ID"

              insert="true"

              update="true"/>

说明:

Column引用父表的主键字段

三、hibernate设置 dynamic-updatedynamic-insert

Hibernate允许我们在映射文件里控制insertupdate语句的内容.比如在映射文件中<property 元素中的update属性设置成为false,那么这个字段,将不被包括在基本的update语句中,修改的时候,将不包括这个字段了.insert同理.dynamic动态SQL语句的配置也是很常用的.下面介绍配置SQL语句的具体属性:

 1)<property>元素 insert属性:设置为false,insert语句中不包含这个字段,表示永远不会被插入,默认true

 2)<property>元素 update属性:设置为false,update语句中不包含这个字段,表示永远不会被修改,默认true

 3)<class>元素 mutable属性:设置为false就是把所有的<property>元素的update属性设置为了false,说明这个对象不会被更新,默认true

4)<property>元素 dynamic-insert属性:设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认false

5)<property>元素 dynamic-update属性,设置为true,表示update对象的时候,生成动态的update语句,如果这个字段的值是null就不会被加入到update语句中,默认false

6)<class>元素 dynamic-insert属性:设置为true,表示把所有的<property>元素的dynamic-insert属性设置为true,默认false

7)<class>元素 dynamic-update属性:设置为true,表示把所有的<property>元素的dynamic-update属性设置为true,默认false

 

说明: Hibernate生成动态SQL语句的消耗的系统资源(比如CPU,内存等)是很小的,所以不会影响到系统的性能,如果表中包含N多字段,建议把dynamic-update属性和insert属性设置为true,这样在插入和修改数据的时候,语句中只包括要插入或者修改的字段.可以节省SQL语句的执行时间,提高程序的运行效率.

 

注意:今天做了一个测试,发现Hibernatedynamic-update只在两种条件下生效:

1.  同一session内,对已经persisit的对象进行update,这里的已经persist”是指update之前先进行了create或者load调用。代码示例:

Session session = openSession();
User user = (User)session.load(User.class,new Long(12));
user.setAddress(null);
session.update(user);
session.flush();

hibernate配置成show_sql=true,可以看到update产生的sql语句。

2.   不同session之间,update传入的对象是另一个session中的persist对象(对该对象调用了create或者load方法)。代码示例:

Session session1 = openSession();
User user = (User)session1.load(User.class,new Long(12));

Session session2 = openSession();
user.setAddress(null);
session2.merge(user);
session2.flush();

如果将session2.merge(..)改成update,则会更新所有可更新的属性。

四、复合主键

1.映射文件(.hbm.xml文件)中复合主键配置:

 

2. 建立主键类(TUserPK

 

 

说明:复合主键的主键类必须实现Serializable接口,实现其两个方法equals(),hashCode(),如下所示:

 

3. Java 类中调用:

 

五、继承 + 一对多关联

              (参见工程:ConnectExtends  

配置文件:ConnectExtends/resource/modules/Animal/hibernate-conf/Animal.hbm.xml)

       

CatDog继承类Animal,对应三个数据表cat,dog,animal。表cat中的id字段既是主键也是外键,对应于animal表的id字段。类Animaldetail对应数据表animaldetail,其中animalid是外键,映射animal 表的id 字段。

 

映射文件配置如下:

1.  Animal.hbm.xml配置如下:

<set name="animaldetailDOs"

               table="animaldetail"

               inverse="true"

               cascade="all">

 

               <key column="animalid"/>

 

<one-to-many class="animaldetail.model.AnimaldetailDO"/>

</set>

 

 

<joined-subclass name="animal.model.CatDO" table="cat">

<key column="id" />

<property name="catagory" column="catagory" type="java.lang.String"/>

</joined-subclass>

 

<joined-subclass name="animal.model.DogDO" table="dog">

     <key column="id" />

<property name="furcolor" column="furcolor" type="java.lang.String"/>

</joined-subclass>

 

注意:<set><joined-subclass>前后数序不能颠倒

 

            Animaldetail.hbm.xml配置如下:

<many-to-one name="animalDO"

                            class="animal.model.AnimalDO"

                   column="animalid"/> 

 

调用操作如下:

            CatDO catDO = new CatDO();

            catDO.setName("CatA");

            catDO.setCatagory("BoSi");

            catDO.setRun("用爬的,BaseAnimal属性");

           

           

            AnimaldetailDO animaldetialDO = new AnimaldetailDO();

            animaldetialDO.setDetailname("动物细节一");

           

            catDO.getAnimaldetailDOs().add(animaldetialDO);

            animaldetialDO.setAnimalDO(catDO);

           

  catDao.doSave(catDO);

               

六、分层结构一张表 子类另外一张表混合继承实现

参见工程:ConnectExtendsfood

配置文件:ConnectExtends/resource/modules/Food/hibernate-conf/Food.hbm.xml)

 

FoodDO有两个子类ProduceFoodDOColorFoodDO,ProduceFoodDO有一个子类PricedetailDO

(该例的另外一种实现方式如下例“继承 + 一对以混合使用”所示)

1. .hbm.xml文件配置如下:

<class name="food.model.FoodDO" table="food" lazy="true">

            <comment></comment>

            <id name="id" column="id" type="integer">

                <generator class="increment"></generator>

            </id>

 

            <discriminator column="type" type="java.lang.String"/>

            ……

<subclass name="food.model.ProduceFoodDO" discriminator-value="produce" lazy="false">

<property name="producingarea" column="producingarea" type="java.lang.String" />

 

<!-- discriminator-value 是数据的分组条件,查询时作为过滤条件使用,一旦设置了,就不要修改值 -->

<subclass name="food.model.PricedetailDO" discriminator-value="produce-detail" lazy="false">

                             <join table="pricedetail">

                                <key column="id"></key>

<property name="detaila" column="detaila" type="java.lang.String"></property>

                            </join>

                        </subclass>

            </subclass>

 

<subclass name="food.model.ColorFoodDO" discriminator-value="color" lazy="false">

                <property name="color" column="color" type="java.lang.String"/>

            </subclass>

</class>

 

2. 调用如下:

PricedetailDO pricedetailDO = new PricedetailDO();

        pricedetailDO.setDetaila("粳米uu");

       

        pricedetailDO.setName("大米uu");

        pricedetailDO.setStyle("细长uu");

        pricedetailDO.setProducingarea("江西uu");

           

foodService.save(pricedetailDO);

          

注意: foodservice 提供的方法参数类型是父类类型,参数值为子类对象 (saveFoodDO(FoodDO DO)),在相当大程度提供操作的灵活性,这样你也可以做如下操作:

ColorFoodDO colorFoodDO = new ColorFoodDO();

                   

                    colorFoodDO.setColor("红色");

                    colorFoodDO.setName("胡箩卜");

                    colorFoodDO.setStyle("长条");

                   

    foodService.save(colorFoodDO);

七、继承 一对一混合应用

(参见工程:Subclass&amp;one2one

      

FoodDO有两个子类ColorFoodDOProduceFoodDO,子类ProduceFoodDOPricedtailDO是一对一关联关系

(本例和上例“ 分层结构一张表 子类另外一张表混合继承实现”是同一业务的不同实现方式)

 

1. 配置文件 Food.hbm.xml如下:

<class name="food.model.FoodDO" table="food" lazy="true">

                <comment></comment>

                <id name="id" column="id" type="integer">

                    <generator class="increment"></generator>

                </id>

               

                <discriminator column="type" type="java.lang.String"/>

                ……

<subclass name="food.model.ProduceFoodDO" discriminator-value="produce">

<property name="producingarea" column="producingarea" type="java.lang.String"/>

 

                    <one-to-one name="pricedetailDO"

                            class="food.model.PricedetailDO"

                            cascade="all"/>

                </subclass>

 

<subclass name="food.model.ColorFoodDO" discriminator-value="color">

<property name="color" column="color" type="java.lang.String"></property>

                </subclass>

</class>

 

2. 配置文件Pricedetail.hbm.xml如下:

<class name="food.model.PricedetailDO" table="pricedetail" lazy="true">

                <comment></comment>

 

                <id name="id" column="id">

                    <generator class="foreign">

                        <param name="property">produceFoodDO</param>

                    </generator>

                </id>

                ……

<one-to-one name="produceFoodDO" class="food.model.ProduceFoodDO" constrained="true"/>

       </class>

3. 应用操作如下:

            ProduceFoodDO produceFoodDO = new ProduceFoodDO();

           PricedetailDO pricedetailDO = new PricedetailDO();

          

           produceFoodDO.setName("one-to-one 名称");

           produceFoodDO.setProducingarea("中企动力");

           pricedetailDO.setDetaila("one-to-one 细节");

          

           produceFoodDO.setPricedetailDO(pricedetailDO);

           pricedetailDO.setProduceFoodDO(produceFoodDO);

          

foodService.saveFood(produceFoodDO);

   

八、独表继承(union-subclass

              (参见工程:unionclass

BaseUserDO有两个子类UserDOUserHistoryDOUserDO对应数据表是usersUserhistoryDO对应数据表userhistory

 

usersidnameaddresslastlogin

userhistoryidnameaddresslastmodified

两个表前面三个字段都一样,各自拥有一个特性字段。

 

             

 

1BaseUser.hbm.xml配置文件如下:

                     <class name="subclass.model.BaseUserDO">

                <comment></comment>

                <id name="id" column="id" type="java.lang.Integer">

 

<!—-这里使用了hilo标识生成器,则在数据库建立对应数据表my_unique_key 表中字段为next_hi ,数据表必须赋予一段数据-->

                    <generator class=" hilo ">

                        <param name="table">my_unique_key</param>

                        <param name="column">next_hi</param>

                    </generator>

                </id>

                <property name="name" type="java.lang.String">

                    <column name="name">

                        <comment></comment>

                    </column>

                </property>

                <property name="address" type="java.lang.String">

                    <column name="address">

                        <comment></comment>

                    </column>

                </property>

               

               

                <union-subclass name="subclass.model.UserDO" table="users">

<property name="lastlogin" column="lastlogin" type="java.lang.String"/>

                </union-subclass>

               

<union-subclass name="subclass.model.UserhistoryDO" table="userhistory">

<property name="lastmodified" column="lastmodified" type="java.lang.String"/>

                </union-subclass>

    </class>

2. 应用操作如下:

            UserDO userDO = new UserDO();

          

           userDO.setName("admin");

           userDO.setAddress("广州大道");

           userDO.setLastlogin(" 2008-07-17 ");

 

    userService.saveBaseUser(userDO);

 

九、自定义类型(继承UserType)

                (对应工程:UserEmails

Ø         实现目标:有一个用户,对应拥有多个email地址,多个email之间用“;”隔开组装成字符串类型保存在数据表中email字段,在java代码中以List类型展示。

1. UseremailsDO email字段设置如下:

                   private List emails = null;

                           public List getEmails() {

                return emails;

            }

            public void setEmails(List emails) {

               this.emails = emails;

        }

说明:email 类型为 List

         2.  .hbm.xml映射文件如下:

<class name="emails.model.UseremailsDO" table="useremails">

                    ……

                <property name="emails" type="emails.model.UEmailList">

                    <column name="emails">

                        <comment></comment>

                    </column>

                </property>

            </class>

           说明:<property name="emails" type="emails.model.UEmailList">

                  Type为自定义的hibernate类型,它实现了

org.hibernate.usertype.UserType,在下面第四点,我们将介绍它的实现方式。

3.  应用操作如下:

    a)保存操作

            List<String> emailList = new ArrayList<String>();

            UseremailsDO userEmailDO = new UseremailsDO();

 

            emailList.add("d@myce.net");

            emailList.add("e@myce.net");

            emailList.add("f@myce.net");

            userEmailDO.setUsername("wang liu ");

            userEmailDO.setEmails(emailList);

 

            useremailService.saveEmails(userEmailDO);

 

            b) 查询操作

            List list = useremailService.selectEmails();

 

            for(int i=0;i<list.size();i++){

                UseremailsDO userEmailDO = (UseremailsDO)list.get(i);

                System.out.println("UserName:" + userEmailDO.getUsername());

                                             System.out.println("======================================");

                for(int j=0;j<userEmailDO.getEmails().size();j++){

System.out.println("Email[" + j + "]:" + (String)(userEmailDO.getEmails().get(j)));

                }

                System.out.println("");

            }

 

         4. 自定义Hibernate类型(实现UserType接口)

public class UEmailList implements UserType{

 

    private List emailList = null;

    private static final char SPLITTER = ';';

    private static final int[] TYPES = new int[]{Types.VARCHAR};

               

    ……

    //工程UserEmails包含详细实现方式

}

 

十、懒加载

懒加载简单说就是对数据的延迟加载,比如数据的级联操作,下面将介绍如何进行懒加载应用配置。(下面是一个一对多的例子)

 

1.映射文件配置如下(将属性lazy设置为true

a)         animal.hbm.xml映射配置文件(主要配置部分)

 

<set name="animaldetailDOs"

               table="animaldetail"

               inverse="true"

               cascade="all"

               lazy="true">

 

           <key column="animalid"/>

 

           <one-to-many class="animaldetail.model.AnimaldetailDO"/>

   </set>

                  

b)          animaldetail.hbm.xml映射配置文件(主要配置部分)

<many-to-one name="animalDO"

                                   class="animal.model.AnimalDO"

                   column="animalid"/>

2.操作应用如下:

 

            CatDO catDO = new CatDO();

            catDO = (CatDO)getSession().load(CatDO.class,id);

         3. web.xml 设置过滤器

            <filter>

                <filter-name>hibernateFilter</filter-name>

                <filter-class>         

org.springframework.orm.hibernate3.

support.OpenSessionInViewFilter

                </filter-class>

            </filter>

 

            <filter-mapping>

                <filter-name>hibernateFilter</filter-name>

                <url-pattern>*.do</url-pattern>

            </filter-mapping>

           

  说明:因为过滤器是对url过滤映射处理,所有在测试(TestCase)过程中,懒加载机制不起左右

十一、附件资料

一) 继承

<subclass>:继承的双方子类、父类都在同一张数据表

<joined-subclass>:……子类、父类在不同数据表

<union-subclass>每个具体类一张表,独表中的某些属性是所有子表所共有

1. <subclass>配置如下:

a) 每个类分层结构一张表

<class name="Payment" table="PAYMENT">

    <id name="id" type="long" column="PAYMENT_ID">

        <generator class="native"/>

    </id>

    <discriminator olumn="PAYMENT_TYPE" type="string"/>

    <property name="amount" column="AMOUNT"/>

    ...

   <subclass name="CreditCardPayment" discriminator-value="CREDIT">

        <property name="creditCardType" column="CCTYPE"/>

        ...

    </subclass>

    <subclass name="CashPayment" discriminator-value="CASH">

        ...

    </subclass>

    <subclass name="ChequePayment" discriminator-value="CHEQUE">

        ...

    </subclass>

</class>

采用这种策略只需要一张表即可。它有一个很大的限制:要求那些由子类定义的字段, 如CCTYPE,不能有非空(NOT NULL)约束。

b) 每个子类一张表,使用辨别标志(Discriminator)

对“每个子类一张表”的映射策略,你可以结合使用<subclass> <join>,如下所示:

<class name="Payment" table="PAYMENT">

    <id name="id" type="long" column="PAYMENT_ID">

        <generator class="native"/>

    </id>

    <discriminator column="PAYMENT_TYPE" type="string"/>

    <property name="amount" column="AMOUNT"/>

    ...

    <subclass name="CreditCardPayment" discriminator-value="CREDIT">

        <join table="CREDIT_PAYMENT">

            <property name="creditCardType" column="CCTYPE"/>

            ...

        </join>

    </subclass>

    <subclass name="CashPayment" discriminator-value="CASH">

        <join table="CASH_PAYMENT">

            ...

        </join>

    </subclass>

    <subclass name="ChequePayment" discriminator-value="CHEQUE">

        <join table="CHEQUE_PAYMENT" fetch="select">

            ...

        </join>

    </subclass>

</class>

可选的声明fetch="select",是用来告诉Hibernate,在查询超类时, 不要使用外部连接(outer join)来抓取子类ChequePayment的数据。

C 混合使用“每个类分层结构一张表”和“每个子类一张表”

                   <class name="Payment" table="PAYMENT">

                            <id name="id" type="long" column="PAYMENT_ID">

                               <generator class="native"/>

                             </id>

                            <discriminator column="PAYMENT_TYPE" type="string"/>

                             <property name="amount" column="AMOUNT"/>

                           

                            <subclass name="CreditCardPayment" discriminator-value="CREDIT">

                                   <join table="CREDIT_PAYMENT">

                                          <property name="creditCardType" column="CCTYPE"/>

                                   </join>

                            </subclass>

<subclass name="CashPayment" discriminator-value="CASH">

……

                            </subclass>

                            <subclass name="ChequePayment" discriminator-value="CHEQUE">

                                     ………

                            </subclass>

</class>

2. <joined-subclass>配置如下

<class name="Payment" table="PAYMENT">

    <id name="id" type="long" column="PAYMENT_ID">

        <generator class="native"/>

    </id>

    <property name="amount" column="AMOUNT"/>

    ...

    <joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">

        <key column="PAYMENT_ID"/>

        ...

    </joined-subclass>

    <joined-subclass name="CashPayment" table="CASH_PAYMENT">

        <key column="PAYMENT_ID"/>

        <property name="creditCardType" column="CCTYPE"/>

        ...

    </joined-subclass>

    <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">

        <key column="PAYMENT_ID"/>

        ...

    </joined-subclass>

</class>

需要四张表。三个子类表通过主键关联到超类表(因而关系模型实际上是一对一关联)

3. <union-subclass>配置如下:

<class name="Payment">

    <id name="id" type="long" column="PAYMENT_ID">

        <generator class="sequence"/>

    </id>

    <property name="amount" column="AMOUNT"/>

    ...

    <union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">

        <property name="creditCardType" column="CCTYPE"/>

        ...

    </union-subclass>

    <union-subclass name="CashPayment" table="CASH_PAYMENT">

        ...

    </union-subclass>

    <union-subclass name="ChequePayment" table="CHEQUE_PAYMENT">

        ...

    </union-subclass>

</class>

 

这里涉及三张表。每张表为对应类的所有属性(包括从超类继承的属性)定义相应字段。 这种方式的局限在于,如果一个属性在超类中做了映射,其字段名必须与所有子类 表中定义的相同。(我们可能会在Hibernate的后续发布版本中放宽此限制。) 不允许在联合子类(union subclass)的继承层次中使用标识生成器策略(identity generator strategy), 实际上, 主键的种子(primary key seed)不得不为同一继承层次中的全部被联合子类所共用.

4. 隐式多态如下(在同一个映射文件中,映射多个class)

<class name="CreditCardPayment" table="CREDIT_PAYMENT">

    <id name="id" type="long" column="CREDIT_PAYMENT_ID">

        <generator class="native"/>

    </id>

    <property name="amount" column="CREDIT_AMOUNT"/>

    ...

</class>

 

<class name="CashPayment" table="CASH_PAYMENT">

    <id name="id" type="long" column="CASH_PAYMENT_ID">

        <generator class="native"/>

    </id>

    <property name="amount" column="CASH_AMOUNT"/>

    ...

</class>

 

<class name="ChequePayment" table="CHEQUE_PAYMENT">

    <id name="id" type="long" column="CHEQUE_PAYMENT_ID">

        <generator class="native"/>

    </id>

    <property name="amount" column="CHEQUE_AMOUNT"/>

    ...

</class>

说明:我们没有在任何地方明确的提及接口Payment。同时注意 Payment的属性在每个子类中都进行了映射。如果你想避免重复, 可以考虑使用XML实体(例如:位于DOCTYPE声明内的 [ <!ENTITY allproperties SYSTEM "allproperties.xml"> ] 和映射中的&allproperties;)

这种方法的缺陷在于,在Hibernate执行多态查询时(polymorphic queries)无法生成带 UNIONSQL语句。

对于这种映射策略而言,通常用<any>来实现到 Payment的多态关联映射。

<any name="payment" meta-type="string" id-type="long">

    <meta-value value="CREDIT" class="CreditCardPayment"/>

    <meta-value value="CASH" class="CashPayment"/>

    <meta-value value="CHEQUE" class="ChequePayment"/>

    <column name="PAYMENT_CLASS"/>

    <column name="PAYMENT_ID"/>

</any>

            <any>元素中子元素和属性补充说明:

           name: 是持久类中属性名称。

meta-type: 是下面meta-value元素中value的类型,如"string","character"等。

          id-type: 是引用类的主键类型。

meta-value元素中value: 该值将保存到数据库表中,用来标识其后的class,即引用的持久类。请参考下面的数据。

meta-value元素中class: 引用持久类的类全称。

          第一个column: 保存上面value值的字段。

第二个column: 保存引用持久类的主键值的字段,他的类型是id-type对应到数据库中的字段类型。

二) 一对多

    1. 单向一对多关联

       

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值