首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >有没有办法为Hibernate管理的对象声明final字段?

有没有办法为Hibernate管理的对象声明final字段?
EN

Stack Overflow用户
提问于 2009-05-26 18:41:17
回答 6查看 10.8K关注 0票数 24

我刚刚开始使用Hibernate,到目前为止我看到的所有示例看起来都很像Hibernate文档中的教程:

代码语言:javascript
复制
package org.hibernate.tutorial.domain;
import java.util.Date;

public class Event {

    private Long id;
    private String title;
    private Date date;

    public Event() {}

    /* Accessor methods... */
}

具体地说:没有一个字段被声明为final,并且必须有一个无参数构造函数,以便Hibernate框架可以实例化该类并设置它的字段。

但问题是-我真的不喜欢让我的类以任何方式可变,只要我能避免它(实践:不可变对象是这样做的一个非常有力的论据)。那么,有没有办法让Hibernate工作,即使我将每个字段都声明为“final”

我知道Hibernate使用反射来实例化它的类,因此需要能够调用某种构造函数,而不会冒着选择错误的构造函数或将错误的值传递给其中一个参数的风险,所以调用no-arg构造函数并一次设置一个字段可能更安全。但是,是否可以向Hibernate提供必要的信息,以便它可以安全地实例化不可变对象?

代码语言:javascript
复制
public class Event {

    private final Long id;
    private final String title;
    private final Date date;

    public Event(@SetsProperty("id") Long id,
        @SetsProperty("title") String title,
        @SetsProperty("date") Date date) {

        this.id = id;
        this.title = title;
        this.date = new Date(date.getTime());
    }

    /* Accessor methods... */
}

当然,@SetsProperty注释是虚构的,但看起来并不是遥不可及。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-05-28 10:34:49

这听起来不像是Hibernate的用例,因为它执行的许多操作都涉及到可变状态:

合并对象更改脏状态checking

  • flushing

也就是说,如果你关心的是不变性,你可以选择在你的对象周围提供包装器,使用复制构造函数:

代码语言:javascript
复制
public class FinalEvent {
    private final Integer id;

    public FinalEvent(Event event) {
        id = event.id;
    }
}

不过,这确实意味着额外的工作。

考虑到这一点,hibernate会话通常是线程绑定的,这至少使最终的字段安全发布的一个好处无效。

您还在寻找final字段的其他哪些好处?

票数 8
EN

Stack Overflow用户

发布于 2009-05-28 11:19:54

不可变对象是指没有修改其状态(即其字段)的方法的对象。这些字段不必是最终字段。因此,您可以删除所有的赋值函数,并配置Hibernate使用字段访问函数而不是取值函数,或者您可以只将无参数构造函数和赋值函数标记为已弃用。这是一个变通的方法,但总比什么都没有好。

票数 13
EN

Stack Overflow用户

发布于 2010-09-10 17:18:11

实际上,在JDK 1.5+中,hibernate可以处理(通过反射)更改最终字段。创建一个受保护的默认构造函数(),它将字段设置为一些默认值/null等...Hibernate可以并且将在实例化对象时覆盖这些值。

这一切都要归功于对Java1.5内存模型的更改--为了实现序列化/反序列化,所做的相关更改(允许最终结果不是最终的)。

代码语言:javascript
复制
public class Event {

private final Long id;
private final String title;
private final Date date;

// Purely for serialization/deserialization
protected Event() {
    id = null;
    title = null;
    date = null;
}

public Event(Long id, String title, Data date) {
    this.id = id;
    this.title = title;
    this.date = date;
}

/* Accessor methods... */

}

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/912093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档