使用JPA时构建器模式的最佳实践和实现

时间:2015-08-07 19:32:57

标签: java hibernate jpa design-patterns builder

我有一个适合建造者模式的课程,有许多参数,我宁愿不使用大量的伸缩式建造者。

我的问题是这个类是JPA实体,对我来说这是一个新手。

拥有私有的最终数据成员会抛出一个错误,因为它们没有在构造函数中初始化,据我所知,JPA需要一个空的受保护构造函数。

有人可以帮忙吗?一个例子太棒了,我已经包含了下面代码的基本示例,但它非常通用。我对许多访问者和数据成员表示感谢,以节省空间/时间。

  @Entity//(name= "TABLE_NAME") //name of the entity / table name
public class Bean implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id //primary key
    @GeneratedValue
    Long id;
    private final DateTime date;
    private final String title;
    private final String intro;


    //used by jpa
    protected Bean(){}

    private Bean(Bean Builder beanBuilder){
        this.date = beanBuilder;
        this.title = beanBuilder;

        this.intro = beanBuilder;
    }

    public DateTime getDate() {
        return date;
    }

    public String getTitle() {
        return title;
    }

    public static class BeanBuilder Builder{

        private final DateTime date;
        private final String title; 

        //private optional 

        public BeanBuilder(DateTime date, String title) {
            this.date = date;
            this.title = title;
        }

        public BeanBuilder intro(String intro){
            this.intro = intro;
            return this;
        }

        public BeanBuilder solution(String solution){
            this.intro = solution;
            return this;
        }

        public Bean buildBean(){
            return new Bean(this);
        }

    }

}

5 个答案:

答案 0 :(得分:2)

标记为final的成员字段必须在构造期间分配值,并且此值为final(即不能更改)。因此,所有声明的构造函数必须为所有 final字段赋值。

这解释了编译器错误。

来自JLS

  

必须在声明它的类的每个构造函数的末尾明确赋值空白的最终实例变量,否则会发生编译时错误(§8.8,§16.9)。

答案 1 :(得分:2)

我不确定你的意思是什么,但是在Hibernate工作时使用不可变对象并不是一个好主意(不是说你做不到,或者你不应该)。

考虑一下,因为Hibernate / JPA定义了" states"对于物体,它们是可变的;否则你会有一个静态数据库,或类似 insert-once-never-modify 数据库。

不可变的概念是一个非常着名的(现在的)概念,主要是从函数式编程中借用的,它并没有真正以同样的方式应用于OOP。如果你正在使用Hibernate,你不应该有不可变的对象......至少到今天为止。

<强>更新

如果你想拥有他们称之为只读实体的东西,你可以使用Hibernate本身的@Immutable注释。密切关注作为实体成员的馆藏。

答案 2 :(得分:2)

不确定为什么要这样做。也许最好将成员变量定义为 @Column(name = "id", nullable = false, updatable = false) 例如

答案 3 :(得分:2)

JPA 2.1规范“2.1实体类”一节说:

  

实体类的方法或持久性实例变量都不是   最终

..意味着您无法构建真正不可变的JPA实体。但是,我真的不明白这是多么大的问题。只是不要让实体类公开公共setter?

答案 4 :(得分:1)

当涉及严格的Java不变性时,实体应该是可变的。例如,一旦访问关联,延迟加载的关联将改变对象状态。

如果您需要以实际不可变的方式使用实体数据(例如,出于多线程目的),那么请考虑使用DTO(因为实体也不是要以实时方式访问)。