2012-01-15 77 views
0

我的域類如下:排序集合中的休眠

package org.hibernate.auction.model; 

import java.util.SortedMap; 
import java.util.TreeMap; 

import org.hibernate.auction.util.ReverseStringComparator; 

public class Item { 

    private Long id; 
    private String name; 
    private SortedMap<String,String> images = new TreeMap<String,String>(new ReverseStringComparator()); 
    public Long getId() { 
     return id; 
    } 
    public void setId(Long id) { 
     this.id = id; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    public SortedMap<String,String> getImages() { 
     return images; 
    } 
    public void setImages(SortedMap<String,String> images) { 
     this.images = images; 
    } 

    public void addImage(String imageName,String fileName){ 
     images.put(imageName, fileName); 

    } 

} 

相應的映射文件Item.hbm.xml是:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<!-- Generated Jan 14, 2012 10:34:00 PM by Hibernate Tools 3.4.0.CR1 --> 
<hibernate-mapping> 
    <class name="org.hibernate.auction.model.Item" table="ITEM"> 
     <id name="id" type="java.lang.Long"> 
      <column name="ITEM_ID" /> 
      <generator class="native" /> 
     </id> 
     <property name="name" type="java.lang.String"> 
      <column name="NAME" /> 
     </property> 
     <map name="images" table="ITEM_IMAGE" sort="org.hibernate.auction.util.ReverseStringComparator"> 
      <key column="ITEM_ID"/> 
      <map-key type="java.lang.String" column="IMAGENAME"></map-key> 
      <element type="java.lang.String" column="FILENAME" not-null="true"/>   
     </map> 
    </class> 
</hibernate-mapping> 

比較如下:

package org.hibernate.auction.util; 

import java.util.Comparator; 

public class ReverseStringComparator implements Comparator<String> { 

    public int compare(String strA, String strB){ 
     // Compare strB to strA, rather than strA to strB. 
     return strB.compareTo(strA); 
    } 

} 

配置hibernate.cfg.xml如下:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
             "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
<session-factory> 
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 
    <property name="hibernate.connection.password">mysql123</property> 
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jpwh_ch6_1_6</property> 
    <property name="hibernate.connection.username">root</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
    <property name="hibernate.show_sql">true</property> 
    <property name="hibernate.use_sql_comments">true</property> 
    <property name="hibernate.format_sql">true</property> 
    <property name="hibernate.hbm2ddl.auto">update</property> 
    <mapping resource="org/hibernate/auction/model/Item.hbm.xml"/> 
</session-factory> 
</hibernate-configuration> 

Java應用程序,以測試如下:

package org.hibernate.auction.model; 

import org.hibernate.Session; 
import org.hibernate.Transaction; 
import persistence.HibernateUtil; 
    public class JpwhCh6_1_6Main { 
     public static void main(String[] args) { 
      Session session = HibernateUtil.getSessionFactory().openSession(); 
      Transaction tx = session.beginTransaction(); 
      Item item1 = new Item(); 
      item1.setName("Foo"); 
      item1.addImage("Image One", "fooimage1.jpg"); 
      item1.addImage("Image Two", "fooimage2.jpg"); 
      item1.addImage("Image Three", "fooimage3.jpg"); 
      System.out.println(item1.getImages()); 


      Item item2 = new Item(); 
      item2.setName("Bar"); 

      Item item3 = new Item(); 
      item3.setName("Baz"); 
      session.save(item1); 
      session.save(item2); 
      session.save(item3); 
      tx.commit(); 

      session.close(); 
      HibernateUtil.shutdown(); 

     } 

    } 

的HibernateUtil是這樣的:

package persistence; 

import org.hibernate.SessionFactory; 
import org.hibernate.cfg.Configuration; 

public class HibernateUtil { 
    private static SessionFactory sessionFactory; 

     static { 
     try { 
      sessionFactory = new Configuration().configure().buildSessionFactory(); 
     } catch (Throwable ex) { 
      throw new ExceptionInInitializerError(ex); 
     } 
     } 

     public static SessionFactory getSessionFactory() { 
      // Alternatively, we could look up in JNDI here 
      return sessionFactory; 
     } 

     public static void shutdown() { 
      // Close caches and connection pools 
      getSessionFactory().close(); 
     } 

} 

在它被存儲這樣的數據庫:

ITEM_ID FILENAME IMAGENAME 
1 fooimage1.jpg Image One 
1 fooimage3.jpg Image Three 
1 fooimage2.jpg Image Two 

顯然我期望它的順序是圖片二,圖片三,圖片一。 我失蹤了。這來自「Java Persistence with Hibernate」一書。我使用的是Hibernate 3.6.9版本。 我嘗試了所有3種排序選項:未排序,自然,比較器的類名。它們沒有任何作用。

+0

嘗試在你的項目類中實現.equals和hashCode方法.. – 2012-01-15 04:56:36

+0

爲什麼你是否想要它如何存儲在數據庫中,而檢索只是對它進行排序。無論如何,數據庫存儲是不固定的。 – 2012-01-15 06:03:58

+0

@Ramesh,是的,我同意你的觀點。不應該擔心它是如何存儲在數據庫中的,而只是專注於從數據庫中檢索它是如何保存在持久性上下文中的。 – 2012-01-15 15:32:16

回答

0

你缺少的是Hibernate用它自己的Map實現替換你的TreeMap,以實現級聯,延遲加載等等,而Hiberbate不可能知道地圖必須按照你的比較。

因此你需要告訴Hibernate你的映射應該被排序,並給它使用比較器的類。見http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#d0e10663

請注意,由於您爲此地圖提供了一個setter,並且盲目地將當前地圖替換爲作爲參數傳遞的地圖,所以任何人都可以用另一個沒有以相同方式排序的地圖替換地圖。不應該有這個屬性的公開二傳手。

+0

現在我的理解是:無法控制條目在數據庫中的存儲順序。通過映射,我們只能控制集合在session中的加載方式。是否正確理解? – 2012-01-15 15:27:56

+0

是的,這是正確的。不過,我真的不明白它與原來的問題有何關係。 – 2012-01-15 15:34:42

+0

@Nizet,我錯誤地認爲我將能夠控制域對象將如何存儲在數據庫中。所以我傳遞了比較器,將它從TreeMap中移除,並期待它會影響數據庫存儲的順序。 – 2012-01-16 04:51:18

0

該問題駐留在Comparator類中。您提供的比較方法根據兩個字符串的比較返回int值(如果strA> strB爲1,如果strA == strB爲0,如果strA爲012,則爲-1)。這就是爲什麼你得到的行按鍵的字母順序排序(圖像一,圖像三,然後圖像二)。如果你想結果發生了逆轉,比方說,(圖片二,三圖像然後圖像中的一個),嘗試修改您的比較類,如下所示:

@Override 
public int compare(String strA, String strB){ 
    if(strB.equals(strB) { 
     return 0; 
    } else { 
     return -strB.compareTo(strA); 
    } 
}