JAEE學(xué)習(xí)筆記(28)Hibernate(1)

Hibernate

2017/6/6 23:55:09
內(nèi)容總結(jié):

  • Hibernate框架:

  • 就是一個持久層的ORM框架.

  • ORM:Object Relational Mapping

  • 常見持久層框架:

  • Hibernate入門:

  • 關(guān)鍵配置映射和核心配置.

  • 編寫測試程序.

  • Hibernate的CRUD:

  • Hibernate的配置:

  • 核心配置:
    屬性文件:
    XML文件:

  • 映射配置:

  • Hibernate的核心API:

  • Hibernate的持久化的類編寫:

  • 無參數(shù)構(gòu)造:

  • 屬性提供set/get方法

  • 屬性盡量使用包裝類

  • 類不要使用final

  • 提供唯一標(biāo)識OID

  • Hibernate主鍵生成策略:

1.2 Hibernate框架的概述:

1.2.1 什么是Hibernate:
框架:軟件的半成品,完成部分功能代碼.

Hibernate:Hibernate是一個開放源代碼的對象關(guān)系映射框架,它對JDBC進(jìn)行了非常輕量級的對象封裝,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數(shù)據(jù)庫。 Hibernate可以應(yīng)用在任何使用JDBC的場合,既可以在Java的客戶端程序使用,也可以在Servlet/JSP的Web應(yīng)用中使用,最具革命意義的是,Hibernate可以在應(yīng)用EJB的J2EE架構(gòu)中取代CMP,完成數(shù)據(jù)持久化的重任。

Hibernate是輕量級JavaEE應(yīng)用的持久層解決方案,是一個關(guān)系數(shù)據(jù)庫ORM框架.
* ORM:Object Relational Mapping.
* 傳統(tǒng)方式開發(fā):
* 持久層:
* 編寫SQL.執(zhí)行SQL. String sql = “insert into 表 values (?,?,?...)”;
* 開發(fā)語言Java:面向?qū)ο?
* 數(shù)據(jù)庫:MySQL(關(guān)系型的數(shù)據(jù)庫.)
* 將Java中的實體類與數(shù)據(jù)庫的關(guān)系表建立一個映射.就可以操作Java中對象,從而操作數(shù)據(jù)庫.

***** Hibernate就是一個持久層的ORM的框架.

-------------------------------------------------------------------------
常見的持久層框架:
* Hibernate :
* JPA       :JPA Java Persistence API.JPA通過JDK 5.0注解或XML描述對象-關(guān)系表的映射關(guān)系(只有接口規(guī)范)
* MyBatis   :前身Ibatis.
* 企業(yè)開發(fā)兩套架構(gòu):
* SSH:Struts2 + Spring + Hibernate
* SSI:SpringMVC + Spring + Ibatis
* DbUtils   :

1.2.2 為什么要學(xué)習(xí)Hibernate:
Hibernate對JDBC訪問數(shù)據(jù)庫的代碼做了封裝,大大簡化了數(shù)據(jù)訪問層繁瑣的重復(fù)性代碼
Hibernate是一個基于jdbc的主流持久化框架,是一個優(yōu)秀的orm實現(xiàn),它很大程度的簡化了dao層編碼工作
Hibernate使用java的反射機(jī)制,而不是字節(jié)碼增強(qiáng)程序類實現(xiàn)透明性
Hibernate的性能非常好,因為它是一個輕量級框架。映射的靈活性很出色。它支持很多關(guān)系型數(shù)據(jù)庫,從一對一到多對多的各種復(fù)雜關(guān)系.

1.2.3 Hibernate版本:
Hibernate3.x版本 和 Hibernate4.x
* 企業(yè)中常用的還是Hibernate3.x.

1.3 Hibernate的日志記錄:

日志:程序開發(fā)中的一些信息.

常用信息輸出:System.out.println(“”);
* 這種方式不好:
* 如果輸出內(nèi)容比較多,項目已經(jīng)開發(fā)完畢,不想使用輸出.需要打開每個類,將輸出的代碼注釋.

日志:Hibernate中使用slf4j技術(shù).
slf4j:SLF4J,即簡單日志門面(Simple Logging Facade for Java),不是具體的日志解決方案,它只服務(wù)于各種各樣的日志系統(tǒng)。
* 用于整合其他日志系統(tǒng).
在企業(yè)中常用的日志記錄:log4j
* 是具體的日志記錄方案.

   -------------------------------------------------------------------------

Log4J的日志級別:
* fatal(致命的)、error(普通錯誤)、warn(警告)、info(信息)、debug(調(diào)試)、trace(堆棧信息).
Logger.error(“錯誤信息”);  
* 通過配置文件的形式,顯示錯誤信息.
* 配置的級別是info.
   
  -------------------------------------------------------------------------

Log4J的三個組件:
記錄器(Loggers)
* 格式:記錄器 = 級別, 輸出源1 , 輸出源2
* log4j.rootLogger=info, stdout
輸出源(Appenders)
* log4j.appender.stdout=org.apache.log4j.ConsoleAppender    :控制臺進(jìn)行輸出.
* log4j.appender.file=org.apache.log4j.FileAppender         :向文件進(jìn)行輸出.
布局(Layouts) 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

1.4 Hibernate的入門:

1.4.1 Hibernate的入門:
第一步:下載Hibernate的開發(fā)包:
http://sourceforge.net/projects/hibernate/files/hibernate3
     
  -------------------------------------------------------------------------

第二步:Hibernate框架目錄結(jié)構(gòu):
documentation   :Hibernate文檔
lib             :Hibernate開發(fā)jar包
* bytecode  :操作字節(jié)碼jar包.
* jpa       :Hibernate的實現(xiàn)jpa規(guī)范.
* optional  :Hibernate的可選jar包.
* required  :Hibernate的必須的jar包.
project         :Hibernate提供的工程
     
  -------------------------------------------------------------------------

第三步:創(chuàng)建一個工程:(Java工程)
導(dǎo)入相應(yīng)jar包:
* hibernate3.jar
* HIBERNATE_HOME/lib/required/*.jar
* HIBERNATE_HOME/lib/jpa/hibernate-jpa-2.0-api-1.0.1.Final.jar
* 導(dǎo)入日志記錄的包:
* log4j-1.2.16.jar
* slf4j-log4j12-1.7.2.jar
* 導(dǎo)入數(shù)據(jù)庫驅(qū)動:
     
  -------------------------------------------------------------------------

第四步:創(chuàng)建表:(關(guān)系型數(shù)據(jù)庫)
create database hibernate3_day01;
use hibernate3_day01;
create table customer(
    id int primary key auto_increment,
    name varchar(20),
    age int
);
     
  -------------------------------------------------------------------------

第五步:創(chuàng)建一個實體類:(面向?qū)ο?
public class Customer {
    private int id;
    private String name;
    private int age;
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
     
  -------------------------------------------------------------------------

第六步:創(chuàng)建ORM的映射.
映射文件只要是一個XML格式文件就可以.名字任意.
* 通常情況下名稱規(guī)范:
* 實體類名稱.hbm.xml
引入約束:
* hibernate3.jar/org.hibernate.hibernate-mapping-3.0.dtd

<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <!-- 建立類與表的映射 -->
    <!-- class標(biāo)簽:用于映射類與表的關(guān)系 name :類的全路徑  table:表名稱 -->
    <class name="cn.itcast.hibernate3.demo1.Customer" table="customer">
        <!-- 建立類中屬性與表中的字段映射 -->
        <!-- 唯一標(biāo)識 -->
        <!-- 使用id的標(biāo)簽 配置唯一屬性 -->
        <!-- 在<id>標(biāo)簽中配置一個主鍵的生成策略. -->
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <!-- 普通屬性 -->
        <!-- property標(biāo)簽:映射類中的普通屬性 name:類中的屬性名稱, column:表中字段名稱 -->
        <!-- 
            type:三種寫法
                * Java類型        :java.lang.String
                * Hibernate類型   :string
                * SQL類型     :不能直接使用type屬性,需要子標(biāo)簽<column>
                    * <column name="name" sql-type="varchar(20)"/>
         -->
        <property name="name" column="name" type="string"/>
        <property name="age" column="age"/>
    </class>
</hibernate-mapping>
     
  -------------------------------------------------------------------------

第七步:創(chuàng)建一個Hibernate的核心配置文件.
通知Hibernate連接是哪個數(shù)據(jù)庫.
在src下創(chuàng)建一個hibernate.cfg.xml

<hibernate-configuration>
<session-factory>
    <!-- 必須去配置的屬性 -->
    <!-- 配置數(shù)據(jù)庫連接的基本信息: -->
    <property name="hibernate.connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <property name="hibernate.connection.url">
        jdbc:mysql:///hibernate3_day01
    </property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">123</property>
    <!-- Hibernate的方言 -->
    <!-- 生成底層SQL不同的 -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>

    <!-- 可選的屬性 -->
    <!-- 顯示SQL -->
    <property name="hibernate.show_sql">true</property>
    <!-- 格式化SQL -->
    <property name="hibernate.format_sql">true</property>
    <!-- hbm:映射 to DDL: create drop alter -->
    <property name="hibernate.hbm2ddl.auto">update</property>

    <!-- 通知Hibernate加載那些映射文件 ->
    <mapping resource="cn/itcast/hibernate3/demo1/Customer.hbm.xml" />

</session-factory>
</hibernate-configuration>
     
  -------------------------------------------------------------------------

第八步:編寫測試
向數(shù)據(jù)庫中插入一條記錄
@Test
    // 向數(shù)據(jù)庫中插入一條記錄
    public void demo1(){
        // 1.Hiberante框架加載核心配置文件(有數(shù)據(jù)庫連接信息)
        Configuration configuration = new Configuration().configure();
        // 2.創(chuàng)建一個SessionFactory.(獲得Session--相當(dāng)連接對象)
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        // 3.獲得Session對象.
        Session session = sessionFactory.openSession();
        // 4.默認(rèn)的情況下,事務(wù)是不自動提交.
        Transaction tx = session.beginTransaction();
        // 5.業(yè)務(wù)邏輯操作
        
        // 向數(shù)據(jù)庫中插入一條記錄:
        Customer customer = new Customer();
        customer.setName("任童");
        customer.setAge(28);
        
        session.save(customer);
        
        // 6.事務(wù)提交
        tx.commit();
        // 7.釋放資源
        session.close();
        sessionFactory.close();
    }
1.4.2 Hibernate的CRUD的操作
保存記錄:
* session.save(customer);

根據(jù)主鍵進(jìn)行查詢:
* Customer customer = (Customer)session.get(Customer.class ,1);
* Customer customer = (Customer)session.load(Customer.class,1);

***** get 和load的區(qū)別:(面試題)
* 1.發(fā)送SQL的時機(jī):
* load這個方法采用了一個技術(shù).lazy延遲加載(懶加載).真正使用這個對象的數(shù)據(jù)的時候.(對象的數(shù)據(jù)不包括主鍵).
* get這個方法是立即檢索.當(dāng)執(zhí)行session.get()方法的時候,馬上發(fā)送SQL語句查詢.

* 2.返回的對象:
* load方法返回的是代理對象.
* get方法返回的是真實的對象.

* 3.查詢一個不存在的數(shù)據(jù):
* load方法拋異常:ObjectNotFoundException.
* get方法拋異常:NullPointException.
     
  -------------------------------------------------------------------------

修改記錄
* session.update(customer);
修改有兩種方式 :
// 5.1手動創(chuàng)建對象的方式
        Customer customer = new Customer();
        customer.setId(2);
        customer.setName("蒼老師");
        
        session.update(customer);
***** 這種方式如果沒有設(shè)置的屬性,將這個屬性的默認(rèn)值存入了.(不好.)

// 5.2先查詢在修改的方式(推薦方式)
        Customer customer = (Customer) session.get(Customer.class, 1);
        customer.setName("鳳姐");
        
        session.update(customer);
     
  -------------------------------------------------------------------------

刪除記錄:
* session.delete(customer);
刪除記錄有兩種方式:
    // 5.1手動創(chuàng)建對象的方式
        Customer customer = new Customer();
        customer.setId(2);
        session.delete(customer);

// 5.2先查詢在刪除的方式
        Customer customer = (Customer)session.get(Customer.class, 1);
        session.delete(customer);
     
  -------------------------------------------------------------------------

查詢所有:
HQL:
HQL:Hibernate Query Language.
面向?qū)ο蟮膶懛?
Query query = session.createQuery("from Customer where name = ?");
query.setParameter(0, "蒼老師");
Query.list();
     
  -------------------------------------------------------------------------

QBC:
Query By Criteria.(條件查詢)

Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("name", "鳳姐"));
List<Customer> list = criteria.list();
SQL:
SQLQuery query = session.createSQLQuery("select * from customer");
List<Object[]> list = query.list();

SQLQuery query = session.createSQLQuery("select * from customer");
query.addEntity(Customer.class);
List<Customer> list = query.list();

1.5 Hibernate的常用的配置及核心API.

1.5.1 Hibernate的常見配置:
核心配置:
核心配置有兩種方式進(jìn)行配置:
* 屬性文件的配置:
* hibernate.properties
* 格式:
* key=value
* hibernate.connection.driver_class=com.mysql.jdbc.Driver
***** 注意:沒有辦法在核心配置文件中加載映射文件.(必須手動編碼的方式進(jìn)行加載.)

* XML格式文件配置:
* hibernate.cfg.xml
* 格式:
<property name="hibernate.connection.username">root</property>

核心配置中:
1.必須的配置:
* 連接數(shù)據(jù)庫4個基本參數(shù):
hibernate.connection.driver_class  連接數(shù)據(jù)庫驅(qū)動程序
hibernate.connection.url   連接數(shù)據(jù)庫URL
hibernate.connection.username  數(shù)據(jù)庫用戶名
hibernate.connection.password   數(shù)據(jù)庫密碼

* Hibernate的方言:
hibernate.dialect   操作數(shù)據(jù)庫方言
     
  -------------------------------------------------------------------------

2.可選的配置:
hibernate.show_sql  true 在控制臺上輸出SQL語句
hibernate.format_sql  true  格式化控制臺輸出的SQL語句
hibernate.connection.autocommit  true 事務(wù)是否自動提交
hibernate.hbm2ddl.auto  create/create-drop/update/validate
* create            :每次執(zhí)行的時候,創(chuàng)建一個新的表.(如果以前有該表,將該表刪除重新創(chuàng)建.) 一般測試的時候的使用.
* create-drop   :每次執(zhí)行的時候,創(chuàng)建一個新的表,程序執(zhí)行結(jié)束后將這個表,刪除掉了.  一般測試的時候使用.
* update            :如果數(shù)據(jù)庫中沒有表,創(chuàng)建一個新的表,如果有了,直接使用這個表.可以更新表的結(jié)構(gòu).
* validate      :會使用原有的表.完成校驗.校驗映射文件與表中配置的字段是否一致.不一致報錯.
     
  -------------------------------------------------------------------------

3.映射的配置:
* 在核心配置文件中加載映射文件:
* <mapping resource="cn/itcast/hibernate3/demo1/Customer.hbm.xml" />
* 使用手動編碼的方式進(jìn)行加載 :

映射文件的配置:
ORM:對象和關(guān)系映射.
* 配置Java對象與表映射.
* 配置類與表的映射:
* name:類的全路徑:
* table:表的名稱:(可以省略的.使用類的名稱作為表名.)
<class name="cn.itcast.hibernate3.demo1.Order" table=”orders”>

* 配置普通屬性與字段映射:
<property name="name" column="name" type="string" length=”20”/>
type:三種寫法
                * Java類型        :java.lang.String
                * Hibernate類型   :string
                * SQL類型     :不能直接使用type屬性,需要子標(biāo)簽<column>
                    * <column name="name" sql-type="varchar(20)"/>

* 配置唯一標(biāo)識與主鍵映射:
* 一個表中只有一個主鍵的形式:
<id name=”id” column=”id”>
* 生成策略:

* 一個表對應(yīng)多個主鍵形式:(復(fù)合主鍵:)---了解.
* <composite-id></composite-id>

* 關(guān)聯(lián)關(guān)系:
* 命名SQL:
    <query name="findAll">
        from Customer
    </query>
    
    <sql-query name="sqlFindAll">
        select * from customer
    </sql-query>

1.6 Hibernate的核心API:

1.6.1 Hibernate的核心API:
Configuration:負(fù)責(zé)管理 Hibernate 的配置信息
1.加載核心配置文件:
核心配置有兩種:
* hibernate.properties:
* 加載:
* Configuration configuration = new Configuration();
* hibernate.cfg.xml:
* 加載:
* Configuration configuration = new Configuration().configure();
     
  -------------------------------------------------------------------------

2.加載映射文件:
* 第一種寫法:
* configuration.addResource("cn/itcast/hibernate3/demo1/Customer.hbm.xml");
* 第二種寫法:(要求:映射文件名稱要規(guī)范,類與映射在同一個包下)
* configuration.addClass(Customer.class);

SessionFactory:Session工廠.
Configuration對象根據(jù)當(dāng)前的配置信息生成 SessionFactory對象
SessionFactory 對象中保存了當(dāng)前的數(shù)據(jù)庫配置信息和所有映射關(guān)系以及預(yù)定義的SQL語句
SessionFactory 對象是線程安全的
SessionFactory還負(fù)責(zé)維護(hù)Hibernate的二級緩存

SessionFactory對象根據(jù)數(shù)據(jù)庫信息,維護(hù)連接池,創(chuàng)建Session(相當(dāng)于Connection)對象.

抽取工具類:
public class HibernateUtils {
    private static Configuration configuration;
    private static SessionFactory sessionFactory;
    
    static{
        configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }
    
    public static Session openSession(){
        return sessionFactory.openSession();
    }
    
    public static void main(String[] args) {
        openSession();
    }
}
     
  -------------------------------------------------------------------------

在Hibernate中使用c3p0連接池:
* 引入c3p0的jar包
* 在核心配置中添加一段配置:
<!-- C3P0連接池設(shè)定-->
<!-- 使用c3po連接池  配置連接池提供的供應(yīng)商-->
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!--在連接池中可用的數(shù)據(jù)庫連接的最少數(shù)目 -->
<property name="c3p0.min_size">5</property>
<!--在連接池中所有數(shù)據(jù)庫連接的最大數(shù)目  -->
<property name="c3p0.max_size">20</property>
<!--設(shè)定數(shù)據(jù)庫連接的過期時間,以秒為單位,
如果連接池中的某個數(shù)據(jù)庫連接處于空閑狀態(tài)的時間超過了timeout時間,就會從連接池中清除 -->
<property name="c3p0.timeout">120</property>
 <!--每3000秒檢查所有連接池中的空閑連接 以秒為單位-->
<property name="c3p0.idle_test_period">3000</property>
     
  -------------------------------------------------------------------------

Session:
相當(dāng)于 JDBC的 Connection
Session 是應(yīng)用程序與數(shù)據(jù)庫之間交互操作的一個單線程對象,是 Hibernate 運作的中心
Session是線程不安全的
所有持久化對象必須在 session 的管理下才可以進(jìn)行持久化操作
Session 對象有一個一級緩存,顯式執(zhí)行 flush 之前,所有的持久化操作的數(shù)據(jù)都緩存在 session 對象處
持久化類與 Session 關(guān)聯(lián)起來后就具有了持久化的能力
Session維護(hù)了Hiberante一級緩存.

save()/persist()        :添加.
update()            :修改
saveOrUpdate()      :增加和修改對象
delete()            :刪除對象
get()/load()        :根據(jù)主鍵查詢
createQuery()       :創(chuàng)建一個Query接口,編寫HQL語句
createSQLQuery()    :創(chuàng)建一個SQLQuery接口,編寫SQL語句數(shù)據(jù)庫操作對象
createCriteria()    :返回一個Criteria接口.條件查詢
     
  -------------------------------------------------------------------------

Transaction:
獲得:
Transaction tx = session.beginTransaction();

常用方法:
commit()            :提交相關(guān)聯(lián)的session實例
rollback()      :撤銷事務(wù)操作
wasCommitted()  :檢查事務(wù)是否提交

***** 如果沒有開啟事務(wù),那么每個Session的操作,都相當(dāng)于一個獨立的事務(wù)
     
  -------------------------------------------------------------------------

Query
Query代表面向?qū)ο蟮囊粋€Hibernate查詢操作
session.createQuery 接受一個HQL語句
HQL是Hibernate Query Language縮寫, 語法很像SQL語法,但是完全面向?qū)ο蟮?
Criteria
Criteria條件查詢:

1.7 Hibernate中的持久化類:

持久化類:實體類 + 映射文件.

持久化類是有編寫規(guī)范:
* 提供一個無參數(shù) public訪問控制符的構(gòu)造器       :用到反射.
* 提供一個標(biāo)識屬性,映射數(shù)據(jù)表主鍵字段            :
* java區(qū)分兩個對象是否是同一個使用 地址.
* 數(shù)據(jù)庫區(qū)分兩條記錄是否一致:使用  主鍵.
* Hibernate中區(qū)分持久化對象是否是同一個,根據(jù)唯一標(biāo)識:
* 所有屬性提供public訪問控制符的 set  get 方法    :框架中存值和取值的時候使用.
* 標(biāo)識屬性應(yīng)盡量使用基本數(shù)據(jù)類型的包裝類型
* 使用基本數(shù)據(jù)類型:
* 成績表:
學(xué)號      姓名      成績
1       張三      null
* 持久化類盡量不要使用final進(jìn)行修飾                   :
* 用final修飾的類是不能被繼承.無法生成代理對象.(延遲加載的時候返回代理對象.延遲加載就失效.)

建表的時候:
* 自然主鍵和代理主鍵:
* 自然主鍵:
* 創(chuàng)建一個人員表.人員表中某條記錄唯一確定.人都有身份證號.我們可以使用身份證號作為主鍵.(身份證號本身就是人員的一個屬性.作為主鍵.)

* 代理主鍵:
* 創(chuàng)建一個人員表.人員表中某條記錄唯一確定.但是沒有使用身份證號作為主鍵,新建字段(用新建的字段作為主鍵.只是一個標(biāo)識作用.)

* 盡量要Hibernate自己去維護(hù)主鍵:
* 主鍵的生成策略:
* increment :自動增長.適合 short int long...不是使用數(shù)據(jù)庫的自動增長機(jī)制.使用Hibernate框架提供的自動增長方式.
* select max(id) from 表; 在最大值的基礎(chǔ)上+1.(多線程的問題.)在集群下不要使用

* identity      :自動增長.適合 short int long...采用數(shù)據(jù)庫的自動增長機(jī)制.不適合于Oracle數(shù)據(jù)庫.
* sequence  :序列.適用于 short int long ... 應(yīng)用在Oracle上 .
* uuid      :適用于字符串類型的主鍵.采用隨機(jī)的字符串作為主鍵.
* native        :本地策略.底層數(shù)據(jù)庫不同.自動選擇適用identity 還是 sequence.
* assigned      :Hibernate框架不維護(hù)主鍵,主鍵由程序自動生成.
* foreign       :主鍵的外來的.(應(yīng)用在多表一對一的關(guān)系.)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容