2013-03-21 60 views
5

我有一個不可變的對象,它是使用組件映射的Hibernate持久對象的成員。例如,PinDrop對應一個表,其中有一個類型不變Point的領域:不可變對象的Hibernate組件映射

public class PinDrop { 
    private String name; 
    private Point location; 
    // Getters and setters for name and location 
} 

// Immutable Point 
public class Point { 
    private final double x; 
    private final double y; 
    // Getters for x and y, no setters 
} 

在我PinDrop.hbm.xml

<property name="name" column="name" type="string"/> 
<component name="location" class="Point> 
    <property name="x" column="location_x" type="double"/> 
    <property name="y" column="location_y" type="double"/> 
</component> 

這並不是因爲在運行時休眠工作抱怨說Point不有xy的安裝者。有沒有辦法將不可變對象用作Hibernate持久對象的組件?

後續行動:我沒有使用註釋,而是使用了hbm.xmlmutableimmutable均不在componentpropertyhbm.xml的有效屬性。

+0

你需要使字段「最終」? – 2013-03-21 22:36:08

回答

5

你可以告訴休眠使用字段訪問(屬性access=field在你的HBM),所以休眠不會抱怨缺少訪問者。

Hibernate使用反射修改最終字段,所以它應該工作。

+3

我不相信這會起作用,但它確實如此。顯然最終的字段可以使用反射進行修改。我想知道這對Java內存模型有什麼影響,因爲final字段保證是線程安全的,並且適用於所有線程。 – 2013-03-23 00:39:24

1

您是否試過@Immutable註釋?

將實體或集合標記爲不可變。沒有註釋意味着 元素是可變的。

不可變的實體可能不會被應用程序更新。更新到 不可變實體將被忽略,但不會引發異常。 @Immutable必須僅用於根實體。

@Immutable放置在集合上會使集合不可變, 意味着集合的添加和刪除不允許爲 。在這種情況下引發HibernateException。

據我所知,在* .hbm.xml中使表不變,mutable="false"屬性可以幫助。

+0

我在哪裏可以將它粘貼在'hbm.xml'文件中? – 2013-03-21 22:45:00

+0

該表不是不可變的,而是組件 – 2013-03-21 22:53:30

3

Hibernate並不喜歡不可變對象。你最好的選擇是要麼

  • 使用僞不可變對象不使用final關鍵字,但沒有制定者,然後告訴Hibernate通過字段設置值。
  • 讓hibernate填充可變生成器對象,然後讓它的屬性複製到一個合適的不可變對象中。不幸的是,這意味着每個BO/DTO有兩個類。
+0

我比第一個選項更喜歡通過反射設置最終字段。設置最終字段太奇怪了,就像史蒂夫評論的那樣,可能會混淆其他有效的線程安全假設。 – David 2015-01-06 14:01:09