為什麼在Hibernate/JPA實體中避免使用Lombok @EqualsAndHashCode?
Lombok 是一個非常受歡迎和有用的圖書館。儘管如此,請注意Lombok @EqualsAndHashCode對實體的影響可能會帶來嚴重問題。
實體應實施equals()和hashCode()。主要問題是Hibernate要求實體在其所有狀態轉換(瞬態,附加,分離 和刪除)中等於自身。使用Lombok @EqualsAndHashCode不會尊重此要求。
避免下面這些方法 :
1. 避免使用的Lombok預設行為@EqualsAndHashCode:
@Entity @EqualsAndHashCode <b>public</b> <b>class</b> LombokDefaultProduct implements Serializable { <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) <b>private</b> Long id; <b>private</b> String name; <b>private</b> String code;
2. 避免使用只有主鍵的Lombok@EqualsAndHashCode
@Entity @EqualsAndHashCode(exclude = {<font>"name"</font><font>, </font><font>"code"</font><font>}) <b>public</b> <b>class</b> LombokIdProduct implements Serializable { <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) <b>private</b> Long id; <b>private</b> String name; <b>private</b> String code; </font>
3. 避免使用預設equals()和hashCode(),下面實體沒有編寫自己的這兩個方法,使用的是預設,不推薦這樣做:
@Entity <b>public</b> <b>class</b> DefaultProduct implements Serializable { <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) <b>private</b> Long id; <b>private</b> String name; <b>private</b> String code; <b>public</b> Long getId() { <b>return</b> id; } <b>public</b> <b>void</b> setId(Long id) { <b>this</b>.id = id; } <b>public</b> String getName() { <b>return</b> name; } <b>public</b> <b>void</b> setName(String name) { <b>this</b>.name = name; } <b>public</b> String getCode() { <b>return</b> code; } <b>public</b> <b>void</b> setCode(String code) { <b>this</b>.code = code; } }
4. 避免使用只依賴主鍵的equals()和hashCode():
@Entity <b>public</b> <b>class</b> IdProduct implements Serializable { <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) <b>private</b> Long id; <b>private</b> String name; <b>private</b> String code; <b>public</b> Long getId() { <b>return</b> id; } <b>public</b> <b>void</b> setId(Long id) { <b>this</b>.id = id; } <b>public</b> String getName() { <b>return</b> name; } <b>public</b> <b>void</b> setName(String name) { <b>this</b>.name = name; } <b>public</b> String getCode() { <b>return</b> code; } <b>public</b> <b>void</b> setCode(String code) { <b>this</b>.code = code; } @Override <b>public</b> <b>int</b> hashCode() { <b>int</b> hash = 3; hash = 89 * hash + Objects.hashCode(<b>this</b>.id); <b>return</b> hash; } @Override <b>public</b> <b>boolean</b> equals(Object obj) { <b>if</b> (<b>this</b> == obj) { <b>return</b> <b>true</b>; } <b>if</b> (obj == <b>null</b>) { <b>return</b> false; } <b>if</b> (getClass() != obj.getClass()) { <b>return</b> false; } <b>final</b> IdProduct other = (IdProduct) obj; <b>if</b> (!Objects.equals(<b>this</b>.id, other.id)) { <b>return</b> false; } <b>return</b> <b>true</b>; } }
推薦這些方法: 1. 依靠@NaturalId
@Entity <b>public</b> <b>class</b> NaturalIdProduct implements Serializable { <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) <b>private</b> Long id; <b>private</b> String name; @NaturalId @Column(nullable = false, updatable = false, unique = <b>true</b>, length = 50) <b>private</b> String code; <b>public</b> Long getId() { <b>return</b> id; } <b>public</b> <b>void</b> setId(Long id) { <b>this</b>.id = id; } <b>public</b> String getName() { <b>return</b> name; } <b>public</b> <b>void</b> setName(String name) { <b>this</b>.name = name; } <b>public</b> String getCode() { <b>return</b> code; } <b>public</b> <b>void</b> setCode(String code) { <b>this</b>.code = code; } @Override <b>public</b> <b>boolean</b> equals(Object o) { <b>if</b> (<b>this</b> == o) { <b>return</b> <b>true</b>; } <b>if</b> (!(o instanceof NaturalIdProduct)) { <b>return</b> false; } NaturalIdProduct naturalIdProduct = (NaturalIdProduct) o; <b>return</b> Objects.equals(getCode(), naturalIdProduct.getCode()); } @Override <b>public</b> <b>int</b> hashCode() { <b>return</b> Objects.hash(getCode()); } }
2. 依靠主鍵:
@Entity <b>public</b> <b>class</b> GoodProduct implements Serializable { <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) <b>private</b> Long id; <b>private</b> String name; <b>private</b> String code; <b>public</b> Long getId() { <b>return</b> id; } <b>public</b> <b>void</b> setId(Long id) { <b>this</b>.id = id; } <b>public</b> String getName() { <b>return</b> name; } <b>public</b> <b>void</b> setName(String name) { <b>this</b>.name = name; } <b>public</b> String getCode() { <b>return</b> code; } <b>public</b> <b>void</b> setCode(String code) { <b>this</b>.code = code; } @Override <b>public</b> <b>boolean</b> equals(Object obj) { <b>if</b> (<b>this</b> == obj) { <b>return</b> <b>true</b>; } <b>if</b> (!(obj instanceof GoodProduct)) { <b>return</b> false; } <b>return</b> id != <b>null</b> && id.equals(((GoodProduct) obj).id); } @Override <b>public</b> <b>int</b> hashCode() { <b>return</b> 2018; } }
良好的equals()和hashCode():
原始碼可以在 這裡 找到