【问题标题】:Hibernate component mapping of an immutable object不可变对象的休眠组件映射
【发布时间】:2013-03-22 07:36:32
【问题描述】:

我有一个不可变对象,它是使用组件映射的 Hibernate 持久对象的成员。例如,PinDrop 对应一个表,该表具有不可变类型的字段Point

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>

这不起作用,因为在运行时 Hibernate 抱怨 Point 没有 xy 的设置器。有没有办法将不可变对象用作 Hibernate 持久对象的组件?

跟进:我没有使用注解,而是hbm.xmlmutableimmutable 都不是 componentpropertyhbm.xml 中的有效属性。

【问题讨论】:

    标签: java hibernate


    【解决方案1】:

    您可以告诉 hibernate 使用字段访问(在您的 hbm 中属性 access=field),这样 hibernate 就不会抱怨缺少访问器。

    Hibernate 使用反射来修改最终字段,因此它应该可以工作。

    【讨论】:

    • 我不相信这会奏效,但确实如此。显然,最终字段可以使用反射进行修改。我想知道这对 Java 内存模型有什么影响,因为 final 字段保证是线程安全的并且对所有线程都正确可见。
    【解决方案2】:

    Hibernate 并不喜欢不可变对象。您最好的选择是

    • 使用不使用 final 关键字但没有设置器的伪不可变对象,然后告诉 Hibernate 通过字段设置值。
    • 让休眠填充可变构建器对象,然后将其属性复制到适当的不可变对象中。不幸的是,这意味着每个 BO/DTO 有两个类。

    【讨论】:

    • 我更喜欢第一个选项,而不是通过反射设置最终字段。设置最终字段太奇怪了,就像史蒂夫评论的那样,可能会与其他有效的线程安全假设混淆。
    【解决方案3】:

    你试过@Immutable注解吗?

    将实体或集合标记为不可变。没有注释意味着 元素是可变的。

    应用程序可能不会更新不可变实体。更新到 不可变实体将被忽略,但不会引发异常。 @Immutable 只能用于根实体。

    @Immutable 放置在集合上使集合不可变, 意味着对集合的添加和删除不是 允许。在这种情况下会引发 HibernateException。

    据我所知,在 *.hbm.xml 中使表不可变,mutable="false" 属性可以提供帮助。

    【讨论】:

    • 我会将这个放在hbm.xml 文件中的哪个位置?
    • 表不是不可变的,而是组件
    猜你喜欢
    • 2014-04-27
    • 2014-05-12
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多