Java項目中使用Hibernate處理資料

來源:互聯網
上載者:User
資料|項目

  對象-關係映射(O/R映射)是許多軟體開發項目的常見需求。資料持久化過程中所涉及到的活動是非常乏味且易於出錯的。如果考慮到不可避免的需求變化,我們就面臨很大的麻煩:資料存放區結構必須與原始碼保持同步。再加上移植性問題,事情就變得非常複雜。

  而Hibernate可以協助我們輕鬆地在非揮發性儲存體介質中儲存資料,而不需要在選擇儲存、安裝或配置類型方面浪費太多精力。Hibernate允許我們儲存任何類型的對象,因此,應用程式不需要知道其資料將使用Hibernate進行持久化。當然,這裡提到的任何事情都可以逆嚮應用:現在從儲存空間擷取已經準備好的對象是很平常的事情。更新和刪除資料也是如此。

  開始之前

  在開始之前,您需要Hibernate的發行版,可以在Hibernate web網站(www.hibernate.org)上找到它。我們將使用2.0.3版本。對於資料庫,我們將使用Hypersonic SQL 1.7.1版本,它可以在hsqldb.sourceforge.net上找到。 Hibernate還支援許多開源或商務資料庫,例如MySQL、PostgreSQL、Oracle、DB2等。對於受支援的任何資料庫,安裝這個教程都很簡單。完整列表參見官方文檔。

  注意:如果您不希望類被持久化在資料庫中(比如說,您只希望進行序列化),那麼Hibernate API為您提供了net.sf.hibernate.persister.EntityPersister類和net.sf.hibernate.persister.ClassPersister介面。通過編寫子類或實現它們,您可以編寫自己的持久化類,並根據需要使用它們。

   下載了所有必要安裝包後,我們必須設定測試環境。基本上,我們所需做的就是把下載的.jar檔案放到CLASSPATH中。這包括Hibernate發行版中的hibernate2.jar和Hypersonic的lib/ 目錄下的hsqldb.jar。Hibernate還需要其他的幾個庫,這些庫都可以在<hibernate-dist>/lib目錄中找到。並不是該目錄下的所有.jars檔案都需要,但是如果您使用所有檔案,也沒有什麼壞處。在我們開始研究Hibernate之前,我們將首先定義我們的問題域。

   注意:Hibernate使用Apache的commons-logging。它是一個智慧型工具,如果找到log4j,它就會預設地使用它。Log4j是一個出色的日誌記錄庫,我們將在這個教程中使用它。如果您還沒有這個軟體(您真的應該安裝這個軟體!),可以從Log4j homepage下載,並將它添加到CLASSPATH中。使用Hibernate團隊所提供的樣本log4j.properties,它可以在<hibernate-dist>/src目錄下找到。

  問題引入

  每個開發人員都至少執行過一次類似的任務:建立一個訂單,把一些產品放在其中,它就變成訂單項,然後儲存該訂單。
我們使用這些簡單的SQL命令來設定資料庫:

CREATE TABLE ORDERS(         ID VARCHAR NOT NULL PRIMARY KEY,         ORDER_DATE TIMESTAMP NOT NULL,         PRICE_TOTAL DOUBLE NOT NULL) CREATE TABLE PRODUCTS(         ID VARCHAR NOT NULL PRIMARY KEY,         NAME VARCHAR NOT NULL,         PRICE DOUBLE NOT NULL,         AMOUNT INTEGER NOT NULL) CREATE TABLE ORDER_ITEMS(         ID VARCHAR NOT NULL PRIMARY KEY,         ORDER_ID VARCHAR NOT NULL,         PRODUCT_ID VARCHAR NOT NULL,         AMOUNT INTEGER NOT NULL,         PRICE DOUBLE NOT NULL) 

  這個資料模型非常簡單。對於一個實際的“生產品質”資料模型,我們會需要外鍵、索引、額外的欄位等等。對於本教程,上面的資料模型就可以了。

   Java代碼

  儘管這些業務需求簡單且易於理解,但是編寫一堆準備好的語句的傳統方法將很快令人厭煩。而Hibernate將會把我們解放出來。我們所需的只是一組簡單的對應檔。但首先我們需要編寫Java類。

   注意:我們將把所有將要持久化的類放到test.hibernate包中,把所有輔助類放到test包中。

   Product

  這個簡單的類只定義了必要的欄位:ID、產品名稱、產品價格和這種產品的當前庫存量。由於Hibernate使用無格式的簡單JavaBeans,我們需要做的只是為每個重要欄位(在我們的樣本中,所有欄位都是重要欄位)建立getter和setter方法,以及預設的建構函式。

package test.hibernate; public class Product {     private String id;     private String name;     private double price;     private int amount;          public String getId() {         return id;     }     public void setId(String string) {         id = string;     }     // 預設的建構函式及其他      // 為了簡潔起見,getter/setter方法沒有顯示     // ... } 

  我們還需要重寫toString()方法。這將協助我們使用簡單的System.out.println(obj)調用來跟蹤應用程式流程:

public String toString() {     return       "[Product] " + name + "(" + id +      ") price=" + price + " amount=" + amount; } 

  這就是全部的product類代碼。但Product沒有實現任何介面,也沒有繼承任何類,Hibernate又如何知道持久化該類型的對象呢?答案很簡單:Hibernate可以處理任何類型的Java對象,只要它能夠遵循JavaBeans約定。

  Order

  我們需要建立的下一個類是Order,它甚至比Product更簡單:它只包含ID、建立日期、總價格和該Order所包括的OrderItems的Set。當然,還需要建立getter和setter方法以及預設的建構函式。

package test.hibernate; import java.util.Date; import java.util.HashSet; import java.util.Set; public class Order {     private String id;     private Date date;     private double priceTotal;     private Set orderItems = new HashSet();          // 自動化佈建該Order的建立時間     public Order() {         this.date = new Date();     }     public String getId() {         return id;     }     public void setId(String string) {         id = string;     }     // 為了簡潔起見,其他getter/setter方法沒有顯示     // ... } 

  同樣也要重寫toString()方法。不要忘記對orderItems執行迴圈!

   OrderItem

  這個類稍微複雜一些,但仍然很易懂。我們的業務需求決定我們需要一定量的產品,我們將會把它們放到一個訂單中。那些產品將自動變成訂單項。這時就需要自訂建構函式了。

package test.hibernate; public class OrderItem {     /**     * 建立有效訂單項。自動化佈建訂單項的價格,並更正產品的庫存可用量     *      * @param order 該訂單項屬於的訂單     * @param product 該訂單項為哪種產品而建立     * @param amount      */     public OrderItem(Order order,                       Product product,                       int amount) {                               this.order = order;         this.product = product;         this.amount = amount;         product.setAmount(product.getAmount() - amount);         this.price = product.getPrice() * amount;             }     // 還需要預設的建構函式來保證Hibernate工作     /**     * 空建構函式遵循JavaBeans約定      *     */     public OrderItem() {         // 空的預設建構函式     }     // 欄位     private String id;     private Product product;     private Order order;     private String productId;     private String orderId;     private double price;     private int amount;          public String getId() {         return id;     }     public String getProductId() {         return product.getId();     }     public String getOrderId() {         return order.getId();     }     // 其他getter/setter方法沒有顯示     // ...     file://顯示該訂單項的方便方式     public String toString() {         return            "[OrderItem] id=" + id + " amount=" +            amount + " price=" + price + "(" +            product + ")";     } } 

  現在我們有了反映資料庫結構的所有類。餘下的唯一一件沒有解釋的事情就是如何把產品放到一個訂單中。只需把下面的方法添加到Order類中:

/** * 添加一項產品到訂單中。產品自動成為一個訂單項。  * priceTotal被自動更新。 *  * @param p 添加到該訂單的產品 * @param amount 添加的產品量 */ public void addProduct(Product p,                         int amount) {    OrderItem orderItem = new OrderItem(this,                           p, amount);                              this.priceTotal = this.priceTotal                       + p.getPrice() * amount;                          this.orderItems.add(orderItem); } 

   啟動Hibernate

  在我們假想的應用程式中,基本的使用模式非常簡單:我們將建立一個Product,然後將其持久化(或者換句話說,儲存它);我們將搜尋並載入一個已經持久化的Product,並確保其可以使用;我們將會更新和刪除Product。

  建立和持久化Product

  現在我們終於用到Hibernate了。使用的情境非常簡單:

  1. 建立一個有效Product。
  2. 在應用程式啟動時使用net.sf.hibernate.cfg.Configuration擷取net.sf.hibernate.SessionFactory。
  3. 通過調用SessionFactory#openSession(),開啟net.sf.hibernate.Session。
  4. 儲存Product,關閉Session。


  正如我們所看到的,這裡沒有提到JDBC、SQL或任何類似的東西。非常令人振奮!下面的樣本遵循了上面提到的步驟:

package test; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.Transaction; import net.sf.hibernate.cfg.Configuration; import test.hibernate.Product; // 用法: // java test.InsertProduct name amount price public class InsertProduct {     public static void main(String[] args)                          throws Exception {         // 1. 建立Product對象         Product p = new Product();         p.setName(args[0]);         p.setAmount(Integer.parseInt(args[1]));         p.setPrice(Double.parseDouble(args[2]));         // 2. 啟動Hibernate         Configuration cfg = new Configuration()                          .addClass(Product.class);         SessionFactory sf = cfg.buildSessionFactory();         // 3. 開啟Session         Session sess = sf.openSession();         // 4. 儲存Product,關閉Session         Transaction t = sess.beginTransaction();         sess.save(p);         t.commit();         sess.close();     } } 

  讓我們來運行它!通過運行java test.InsertProduct Milk 100 1.99命令,插入價格為1.99的100瓶牛奶。我們會得到如下的輸出日誌:

Nov 23, 2003 9:05:50 AM net.sf.hibernate.cfg.Environment <clinit> INFO: Hibernate 2.0.3 Nov 23, 2003 9:05:50 AM net.sf.hibernate.cfg.Environment <clinit> INFO: hibernate.properties not found Nov 23, 2003 9:05:50 AM net.sf.hibernate.cfg.Environment <clinit> INFO: using CGLIB reflection optimizer Nov 23, 2003 9:05:50 AM net.sf.hibernate.cfg.Environment <clinit> INFO: JVM proxy support: true Nov 23, 2003 9:05:50 AM net.sf.hibernate.cfg.Configuration addClass INFO: Mapping resource: test/hibernate/Product.hbm.xml Exception in thread "main" net.sf.hibernate.MappingException:  Resource: test/hibernate/Product.hbm.xml not found     at net.sf.hibernate.cfg.Configuration.addClass(Configuration.java:285)     at test.FindProductByName.main(FindProductByName.java:24) 

  它無法工作。其中有兩行尤其讓人感興趣:

INFO: hibernate.properties not found and Resource: test/hibernate/Product.hbm.xml not found.

   當然,INFO行指出我們需要一個hibernate.properties設定檔。在這個檔案中,我們配置要使用的資料庫、使用者名稱和密碼以及其他選項。使用下面提供的這個樣本來串連前面提到的Hypersonic資料庫:

hibernate.connection.username=sa hibernate.connection.password= hibernate.connection.url=jdbc:hsqldb:/home/davor/hibernate/orders hibernate.connection.driver_class=org.hsqldb.jdbcDriver hibernate.dialect=net.sf.hibernate.dialect.HSQLDialect 

  適當地進行修改(例如,可能需要修改hibernate.connection.url),並儲存到classpath中。

  這很容易,但那個test/hibernate/Product.hbm.xml資源是什麼呢?它是一個XML檔案,定義了Java對象如何被持久化(映射)到一個資料庫。在該檔案中,我們定義資料存放區到哪個資料庫表中,哪個欄位對應到資料庫表的哪個列,不同的對象如何互相關聯,等等。讓我們來看一下Product.hbm.xml。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping     PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"     "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">      <hibernate-mapping>     <class name="test.hibernate.Product"             table="products">                        <id name="id" type="string"              unsaved-value="null">             <column name="id" sql-type="char(32)"                      not-null="true"/>             <generator class="uuid.hex"/>         </id>         <property name="name">             <column name="name" sql-type="char(255)"                      not-null="true"/>         </property>         <property name="price">             <column name="price" sql-type="double"                      not-null="true"/>         </property>         <property name="amount">             <column name="amount" sql-type="integer"                      not-null="true"/>         </property>             </class> </hibernate-mapping> 

  它非常簡單且易於理解。幾個細節特別令人感興趣:

  • <class name="test.hibernate.Product" table="products">,指出正在映射一個名為test.hibernate.Product的類到表products。
  • <id>元素及其子項目,定義Java類與資料庫之間的串連。
  • <property>元素,定義每個欄位儲存到哪個列及其類型、名稱等。


  <generator class="uuid.hex"/>元素乍一看不太好理解。但是知道了它是<id>的一個子項目後,它的作用就很明顯了:由於應用程式不知道它的資料如何被持久化(我們一直這麼說),我們需要一個沒有任何業務含義的代理鍵協助Hibernate操縱對象。新建立的Products沒有那個id,Hibernate將為我們建立它們。我們選擇使用UUID字串,但它提供了許多ID產生器(順序的、限定範圍的,甚至是使用者指派的,等等),而且還可以編寫自己的ID產生器。

   現在,建立(複製、粘貼)Product.hbm.xml的內容,並把檔案和test.hibernate.Product類放到同一個包內(例如,放置Product.java檔案的目錄),重新運行java test.InsertProduct Milk 100 1.99命令。現在我們看到更多的日誌以及...沒有其他東西了!它運行正常嗎?在Session sess = sf.openSession(); 前和sess.close()後添加System.out.println(p),看一看Produc出了什麼問題。重新運行程式。您將看到類似於如下內容的日誌輸出(ID數字肯定會不同的):

[Product] Milk(null) price=1.99 amount=100 [Product] Milk(40288081f907f42900f907f448460001) price=1.99 amount=100 


  Hibernate為我們建立了Product的id!讓我們看一下Product是否儲存到了資料庫中。執行select * from products,資料庫返回類似於以下內容的輸出:

ID                              |NAME  |PRICE |AMOUNT | 40288081f907f42900f907f448460001|Milk  |1.99  |100    | 

  Product資訊被成功地插入到了資料庫中,我們甚至都還沒有編寫一行SQL語句!

  插入一些其他產品,例如麵包、咖啡、啤酒等,這樣就可以繼續學習下面的教程。

  尋找和載入產品

  尋找和載入已經持久化的對象在Hibernate中非常簡單。使用它的查詢語言,我們可以很容易地通過ID、名稱或其他屬性擷取一個對象(或對象集)。我們能夠擷取完整的對象或它的一部分屬性。Hibernate將處理餘下的工作,最後,我們將擁有相當有用的對象層次體系。我們來看一下test.FindProductByName類。

package test; import java.util.List; import net.sf.hibernate.Hibernate; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.cfg.Configuration; import test.hibernate.Product; // 用法: // java test.FindProductByName name public class FindProductByName {     public static void main(String[] args) throws Exception {         // 執行的查詢         String query =             "select product from product "             + "in class test.hibernate.Product "             + "where product.name=:name";         // 搜尋的內容         String name = args[0];         // 初始化         Configuration cfg = new Configuration()                            .addClass(Product.class);         SessionFactory sf = cfg.buildSessionFactory();         // 開啟會話         Session sess = sf.openSession();                  // 搜尋並返回         List list = sess.find(query, name,                                Hibernate.STRING);         if (list.size() == 0) {             System.out.println("No products named "                                 + name);             System.exit(0);         }         Product p = (Product) list.get(0);         sess.close();         System.out.println("Found product: " + p);     } }

  在FindProductByName中有幾點值得注意:

  • 有一個具有where子句的query字串,這與標準SQL語句很相似。
  • 初始化Hibernate的方法與第一個樣本中一樣。這一次,我們有設定檔和對應檔。
  • sess.find()執行查詢,並將提供的產品名稱設定為類型Hibernate.STRING的搜尋參數。
  • 作為結果,我們得到一個包含所找到的Product的java.util.List。
  • 使用Product p = (Product) list.get(0); 我們用通常的類型轉換方法擷取找到的對象。


  執行java test.FindProductByName Milk,查看顯示在控制台中的內容。

  注意:查詢是區分大小寫,所以搜尋小寫milk將不會返回任何結果。使用lower()或upper()SQL函數來啟用不區分大小寫搜尋。在這種情況下,我們會在查詢字串中使用where lower(product.name)=lower(:name)。關於查詢的詳細內容,請參見文檔。此外,如果不希望顯示所有的INFO日誌資訊,可以修改log4j.properties檔案,將日誌等級設定為warn。

  更新和刪除產品

  到現在為止,您應該對Hibernate的工作方式有了一個基本的瞭解,因此我們將縮短冗長的樣本,只顯示重要的部分。

  為了在單個事務中將所有產品的價格提高10%,我們可以編寫如下的內容:

double percentage = Double.parseDouble(args[0])/100; sess = sf.openSession(); Transaction t = sess.beginTransaction(); // 列表包含產品 Iterator iter = list.iterator(); while (iter.hasNext()) {     Product p = (Product) iter.next();                 p.setPrice(p.getPrice() * (1 + percentage));     sess.saveOrUpdate(p);       } t.commit(); sess.close(); 

  最後,要刪除Product,當然要調用sess.delete(product)。如果資料庫關閉了autocommit,不要忘記調用commit()提交Transaction。

   現在,我們已經完成了針對單個對象的所有基本操作——建立、讀取、更新和刪除。看上去相當有趣,但我們可以做得更好。現在我們來學習如何操縱對象集而不需要編寫SQL語句。所有的魔法都通過對應檔實現。

  Orders,OrderItems

  有時一個一個地操縱對象確實可行,但是我們希望能夠級聯載入和更新。現在我們來看如何做到這一點。

   我們需要同時檢查Order和OrderItem。就如前面所提到的,我們添加一項Product到一個Order中,它將變成一個OrderItem。Order在內部儲存一個OrderItem集。我們希望儲存Order,讓Hibernate來做其他工作:儲存OrderItem和更新所添加的Product的可用庫存(數量)。聽起來很複雜,但實際上非常簡單。Hibernate知道如何處理一對一、一對多、多對一和多對多方式中的相關對象。我們將從對應檔開始。

  Order.hbm.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping     PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"     "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping>     <class name="test.hibernate.Order" table="orders">         <id name="id" type="string" unsaved-value="null" >             <column name="id" sql-type="char(32)" not-null="true"/>             <generator class="uuid.hex"/>         </id>         <property name="date">          <column name="order_date"                   sql-type="datetime" not-null="true"/>         </property>         <property name="priceTotal">         <column name="price_total"                  sql-type="double" not-null="true"/>         </property>                  <set name="orderItems" table="order_items" inverse="true"  cascade="all">             <key column="order_id" />             <one-to-many class="test.hibernate.OrderItem" />         </set>              </class> </hibernate-mapping> 

  這個對應檔非常易於理解,除了最後一個元素<set>。它表示了不同類之間的串連,在我們的例子中,這些類是Order和OrderItem。屬性和子項目很容易理解:一個Set類型的欄位,名為orderItems(參見上面的Order原始碼),它包含類型為test.hibernate.OrderItem的對象,正如<one-to-many>子項目所解釋的那樣。這些對象被持久化在表order_items中,order_id列包含OrderItem類型的對象的鍵。

   cascade="all"是一個非常重要的屬性。它解釋了在操縱串連到的對象時,Hibernate如何動作。在我們的例子中,當建立一個Order時,我們無疑希望它所有的OrderItem也被建立;當然,當一個Order被刪除時,我們也希望它所有的OrderItem也被刪除。Cascade屬性還有另外三個選項(none、save-update和delete),我們將在下面的樣本中看一下如何使用它們。

   OrderItem.hbm.xml

  這個對象比較有意思。它的執行個體自動在Order中建立,基本上不會存在於其外。然而,由於它們在建立Order時代表Product,所以我們需要它們。如果一項產品的價格改變了,我們無疑不希望所有相關的OrderItem以及Order的價格被改變。我們需要的只是在OrderItem建立時更新Product的可用庫存。最後,當一項Order被刪除時,其OrderItem也被刪除,但我們不能改變Product!聽上去很複雜,特別是要編寫所有這些SQL語句的話。但Hibernate把它們壓縮成了對應檔中的兩行!

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping     PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"     "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping>     <class name="test.hibernate.OrderItem"               table="order_items">         <id name="id" type="string" unsaved-value="null" >             <column name="id" sql-type="char(32)"                         not-null="true"/>             <generator class="uuid.hex"/>         </id>         <property name="orderId" insert="false"                       update="false">             <column name="order_id" sql-type="char(32)"                         not-null="true"/>         </property>         <property name="productId" insert="false"                       update="false">             <column name="product_id" sql-type="char(32)"                         not-null="true"/>         </property>         <property name="amount">             <column name="amount" sql-type="int"                         not-null="true"/>         </property>         <property name="price">             <column name="price" sql-type="double"                         not-null="true"/>         </property>         <many-to-one name="order"                   class="test.hibernate.Order"                   column="order_id" />         <many-to-one name="product"                   class="test.hibernate.Product"                   cascade="save-update"                   column="product_id"/>     </class> </hibernate-mapping> 

  到目前為止,我們瞭解了關於<id>和<property>元素的一切,但<many-to-one>是一個新元素。這個元素非常簡單。第一個<many-to-one>元素指出OrderItem的名為order的欄位是test.hibernate.Order類型,並且通過表order_items的order_id列來引用(參見class元素的table屬性)。第二個many-to-one元素類似於第一個,除了它具有cascade="save-update"屬性。它在定義的內容之前進行解釋。在這個例子中,我們假設Hibernate只在儲存(建立)或更新(更改)OrderItem時傳遞Product的更改,而在刪除時不傳遞更改。因此,上述的複雜SQL語句就被壓縮為單個屬性!現在這個問題解決了!

  用法樣本

  建立一個訂單。在該樣本中,我們建立並持久化一個訂單。反覆運行這個樣本,查看產品數量在每次成功建立訂單後如何變化。

// ... Configuration cfg = new Configuration()                     .addClass(Product.class)                     .addClass(Order.class)                     .addClass(OrderItem.class); // ... Order order = new Order(); order.addProduct(milk, 3); order.addProduct(coffee, 5); // ... sess = sf.openSession(); Transaction t = sess.beginTransaction(); sess.save(order); t.commit(); sess.close(); System.out.println(order); // ... 

   按照價格範圍尋找訂單。在該樣本中,我們將展示如何使用一個帶有兩個參數的查詢。Hibernate正確地載入具有適當訂單項和產品的訂單。

// ... String query = "select o from o "     + "in class test.hibernate.Order "     + "where o.priceTotal > :priceTotalLower "     + "and o.priceTotal < :priceTotalUpper"; // ...                 Query q = sess.createQuery(query); q.setDouble("priceTotalLower",               Double.parseDouble(args[0])); q.setDouble("priceTotalUpper",               Double.parseDouble(args[1])); List list = q.list(); // ... sess.close(); // ... 

   刪除一定價格範圍內的訂單。這是一個重要的樣本。這裡我們會看到Hibernate是一個多麼智能的工具。正如前面所提到的,當刪除一個訂單時,其訂單項也需要被刪除,但不能改變產品。在運行該樣本後,檢查資料庫,確認產品沒有變化。

// ... String query = "select o from o "     + "in class test.hibernate.Order "     + "where o.priceTotal > :priceTotalLower "     + "and o.priceTotal < :priceTotalUpper"; Transaction tx = sess.beginTransaction(); sess.delete(query,      new Object[]{new Double(args[0]),                   new Double(args[1])},      new Type[]{Hibernate.DOUBLE,                 Hibernate.DOUBLE}            );        tx.commit(); sess.close(); 

   結束語

  本文展示了Hibernate有多麼強大。您已經瞭解到可以多麼輕鬆地持久化任何類型的Java對象、操縱對象階層、處理集合、使用事務。但Hibernate的功能不止於此。它可以處理使用提交和復原的完整事務、繼承、幾種類型的集合,並提供非常強大的物件導向查詢語言HQL,HQL支援關聯和連接、多態、子查詢等。接下來您可以閱讀Hibernate參考文檔,並著手在日常工作中使用Hibernate。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.