我不認爲這是用於使用定製標註使用純JPA的2 API定製標識出的現成的支持。但是如果你想使用提供商特定的API,那麼這項工作非常簡單。 Sample Example
要獨立提供者嘗試以下任何技巧....
IdGeneratorHolder
public abstract class IdGeneratorHolder {
/* PersistentEntity is a marker interface */
public static IdGenerator getIdGenerator(Class<? extends PersistentEntity> entityType) {
/* sample impelementation */
if(Product.class.isAssignableFrom(entityType)) {
return new ProductIdGenerator();
}
return null;
}
}
一般IdGenerator接口
public interface IdGenerator {
String generate();
}
具體IdGenerator - 產品ID生成
public class ProductIdGenerator implements IdGenerator {
public String generate() {
/* some complicated logic goes here */
return ${generatedId};
}
}
現在將生成的ID或者設置爲無參數構造函數或,使用@PrePersist方法。
Product.java
public class Product implements PersistentEntity {
private String id;
public Product() {
id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
}
@PrePersist
public void generateId() {
id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
}
}
在上面的例子中所有的ID具有相同的類型,即java.lang.String
的。如果持久實體有不同類型的IDS .....
IdGenerator.java
public interface IdGenerator {
CustomId generate();
}
CustomId.java
public class CustomId {
private Object id;
public CustomId(Object id) {
this.id = id;
}
public String toString() {
return id.toString();
}
public Long toLong() {
return Long.valueOf(id.toString());
}
}
Item.java
@PrePersist
public void generateId() {
id = IdGeneratorHolder.getIdGenerator(getClass()).generate().toLong();
}
您還可以使用自定義的註釋......
CustomIdGenerator.java
public @interface CustomIdGenerator {
IdStrategy strategy();
}
IdStrategy.java
enum IdStrategy {
uuid, humanReadable,
}
IdGeneratorHolder.java
public abstract class IdGeneratorHolder {
public static IdGenerator getIdGenerator(Class<? extends PersistentEntity> entityType) {
try { // again sample implementation
Method method = entityType.getMethod("idMethod");
CustomIdGenerator gen = method.getAnnotation(CustomIdGenerator.class);
IdStrategy strategy = gen.strategy();
return new ProductIdGenerator(strategy);
}
還有一件事......如果我們在@PrePersist方法中設置了id,則equals()方法不能依賴id字段(即,代理鍵),我們必須使用業務/自然鍵來實現equals()方法。但是,如果我們在無參數構造函數中將id字段設置爲某個唯一值(uuid或應用程序中唯一的「app-uid」),它可以幫助我們實現equals()方法。
public boolean equals(Object obj) {
if(obj instanceof Product) {
Product that = (Product) obj;
return this.id ==that.id;
}
return false;
}
如果我們或他人通話(有意或錯誤)的@PrePersist註解的方法1倍以上,「唯一的ID將被改變!」所以在no-arg構造函數中設置id是可取的。或者爲了解決這個問題,把一個非空檢查...
@PrePersist
public void generateId() {
if(id != null)
id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
}
}
UPDATE
如果我們把ID生成的 無參數的構造函數,那不是 從數據庫加載實體 時產生問題?因爲Hibernate 將調用無參數的構造 導致現有的IDS是 重新生成
是的,你說得對,我錯過了一部分。 :(其實,我想告訴你的是: - 在我的應用程序中每個實體對象與組織實體相關聯的,所以我創建了一個抽象的超類有兩個構造函數,每一個實體(組織除外)擴展該類
protected PersistentEntityImpl() {
}
protected PersistentEntityImpl(Organization organization) {
String entityId = UUIDGenerator.generate();
String organizationId = organization.getEntityId();
identifier = new EntityIdentifier(entityId, organizationId);
}
的無參數的構造是JPA的供應商,我們從來沒有調用無參數的構造函數,但其他組織根據構造函數。正如你所看到的,ID是在基礎的組織構造函數分配的。(我真的錯過了這一點同時寫出答案,對不起)
看看你是否可以在你的應用中實現這個或者類似的策略
第二個選項是使用 @PrePersist批註。我把在 和方法不會被擊中,並給了我 的異常,說明我需要 手動設置的ID。是否有 我應該做的其他事情?
理想情況下,在保持實體對象之前,JPA提供者應該調用@PrePersist方法(在類中聲明的方法以及在超類中聲明的所有其他方法)。不能告訴你什麼是錯的,除非你顯示一些代碼和控制檯。
我看過一樣,如果可能的話,想避免xml文件。但是如果我找不到替代品,我想我會訴諸於此。謝謝! – digiarnie 2010-11-24 01:47:09
@digiarnie看到更新 – Bozho 2010-11-24 07:27:00