[英]Best practice and implementation of a builder pattern when using JPA
我有一個適合構建器模式的類,有很多參數,我寧願不使用大量的伸縮構造函數。
我的問題是這個類是一個 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);
}
}
}
標記為final
成員字段必須在構造期間分配一個值,並且該值是最終的(即不能更改)。 因此,所有聲明的構造函數都必須為所有final
字段賦值。
這解釋了您的編譯器錯誤。
從JLS :
必須在聲明它的類的每個構造函數的末尾明確分配一個空白的 final 實例變量,否則會發生編譯時錯誤(第 8.8 節、第 16.9 節)。
我不確定你的意思,但是在 Hibernate 中工作時擁有不可變的對象並不是一個好主意(並不是說你不能這樣做,或者你不應該這樣做)。
想一想,因為 Hibernate/JPA 為對象定義了“ 狀態”,它們是可變的; 否則你會有一個靜態數據庫,或者類似插入一次永不修改的數據庫。
不可變的概念是一個眾所周知的(現在)概念,主要是從函數式編程中借來的,它並沒有真正以相同的方式應用於 OOP。 如果您正在使用 Hibernate,您不應該擁有不可變的對象……至少在今天之前是這樣。
更新
如果你想擁有他們所謂的只讀實體,你可以使用 Hibernate 本身的@Immutable
注釋。 作為實體成員密切關注集合。
不知道你為什么要這樣做。 例如,最好將成員變量定義為@Column(name = "id", nullable = false, updatable = false)
JPA 2.1 規范的“2.1 實體類”部分說:
實體類的任何方法或持久實例變量都不能是最終的。
..意味着您無法構建真正不可變的 JPA 實體。 但是,我真的不明白這怎么會是一個大問題。 只是不要讓實體類公開公共設置器?
當涉及到嚴格的 Java 不變性時,實體應該是可變的。 例如,一旦訪問關聯,延遲加載的關聯將更改對象狀態。
如果您需要以真正不可變的方式使用實體數據(例如,用於多線程目的),那么請考慮使用 DTO(因為實體也不能被當前訪問)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.