我定義了一個發電機的JPA類:JPA ID生成策略
<sequence-generator name="MY_SEQ" allocation-size="-1"
sequence-name="MY_SEQ"
initial-value="100000000" />
有,我已經有一個實體的ID的情況,但是當我插入實體被用生成器生成的ID。
是否有可能定義一個生成器,它只會在不存在時生成一個ID?
我使用Hibernate作爲JPA Provider。
謝謝
我定義了一個發電機的JPA類:JPA ID生成策略
<sequence-generator name="MY_SEQ" allocation-size="-1"
sequence-name="MY_SEQ"
initial-value="100000000" />
有,我已經有一個實體的ID的情況,但是當我插入實體被用生成器生成的ID。
是否有可能定義一個生成器,它只會在不存在時生成一個ID?
我使用Hibernate作爲JPA Provider。
謝謝
我找不到在JPA中這樣做的方法,所以我使用了Hibernate EJB3事件偵聽器。我騎着saveWithGeneratedId
使用反射來檢查@Id
註釋的實體,然後檢查該字段是否有值。如果它有一個值,那麼我請撥打saveWithRequestedId
。其他方面,我讓它生成Id。這很好,因爲如果我需要一個Id,我仍然可以使用Hibernate的序列。反射可能會增加開銷,所以我可能會稍微改變它。我正考慮在所有實體中使用getId()
或getPK()
方法,因此我不必搜索@Id
哪個字段。
在我使用反射之前,我嘗試調用session.getIdentifier(實體)來檢查,但我得到TransientObjectException(「實例沒有與此會話關聯」)。我不知道如何讓實體進入會話而不先保存它,所以我放棄了。以下是我寫的聽衆代碼。
public class MergeListener extends org.hibernate.ejb.event.EJB3MergeEventListener
{
@Override
protected Serializable saveWithGeneratedId(Object entity, String entityName, Object anything, EventSource source, boolean requiresImmediateIdAccess) {
Integer id = null;
Field[] declaredFields = entity.getClass().getDeclaredFields();
for (Field field : declaredFields) {
Id annotation = field.getAnnotation(javax.persistence.Id.class);
if(annotation!=null) {
try {
Method method = entity.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1));
Object invoke = method.invoke(entity);
id = (Integer)invoke;
} catch (Exception ex) {
//something failed (method not found..etc) , keep going anyway
}
break;
}
}
if(id == null ||
id == 0) {
return super.saveWithGeneratedId(entity, entityName, anything, source, requiresImmediateIdAccess);
} else {
return super.saveWithRequestedId(entity, id, entityName, anything, source);
}
}
}
然後我不得不把監聽器添加到我的persistence.xml
<property name="hibernate.ejb.event.merge" value="my.package.MergeListener"/>
這不是一個好主意,序列用於代理鍵,在商業意義上毫無意義,但向你保證,不會有重複因此在插入時沒有錯誤。
你怎麼已有的ID,如果該條目不存在。這是一個壞主意,實施你在說什麼。 – 2011-02-22 18:57:54
我有2個數據庫。一個在服務器上,另一個在PC上。這個想法是我將數據下載到個人電腦上,這樣我就可以'離線'工作,這涉及到將實體放到PC上。在PC上使用我們的軟件時,他們可以創建新的實體。我需要序列的新entites,如果它已經有一個ID我想插入實體與該ID。 – Allan 2011-02-23 12:58:33