2010-07-21 72 views
4

我正在寫一個web服務來維護一個數據庫。我正嘗試將JPA(EclipseLink)用於實體類。但是,數據庫使用自然主鍵,因此由於外鍵約束,ID字段的更新可能會失敗。我們的DBA提供了一個函數來更新ID字段,這些字段將使用更新的ID創建一個新的父記錄,更新子記錄以指向新的父項並刪除舊的父項。JPA - 使用可插入/可更新

如果ID字段可以爲「正常」更新,我會像這樣的情況:

@Entity 
@Table(name = "PARENT") 
public class Parent implements Serializable 
{ 
    private static final long serialVersionUID = 1L; 
    private String parent; 
    private String attribute; 
    private Set<Child> childs; 

    public Parent() 
    { 
    } 

    @Id 
    @Column(name = "PARENT") 
    public String getParent() 
    { 
     return this.parent; 
    } 

    public void setParent(String parent) 
    { 
     this.parent = parent; 
    } 

    @Column(name = "ATTRIBUTE") 
    public String getAttribute() 
    { 
     return this.attribute; 
    } 

    public void setAttribute(String attribute) 
    { 
     this.attribute = attribute; 
    } 

    @OneToMany(mappedBy = "parentBean") 
    public Set<Child> getChilds() 
    { 
     return this.childs; 
    } 

    public void setChilds(Set<Child> childs) 
    { 
     this.childs = childs; 
    } 
} 

@Entity 
@Table(name = "CHILD") 
public class Child implements Serializable 
{ 
    private static final long serialVersionUID = 1L; 
    private String child; 
    private String attribute; 
    private Parent parentBean; 

    public Child() 
    { 
    } 

    @Id 
    @Column(name = "CHILD") 
    public String getChild() 
    { 
     return this.child; 
    } 

    public void setChild(String child) 
    { 
     this.child = child; 
    } 

    @Column(name = "ATTRIBUTE") 
    public String getAttribute() 
    { 
     return this.attribute; 
    } 

    public void setAttribute(String attribute) 
    { 
     this.attribute = attribute; 
    } 

    @ManyToOne 
    @JoinColumn(name = "PARENT") 
    public Parent getParent() 
    { 
     return this.parent; 
    } 

    public void setParent(Parent parent) 
    { 
     this.parent = parent; 
    } 
} 

我也有一個方法GenericServiceBean類調用函數:

@Stateless 
public class GenericServiceBean implements GenericService 
{ 
    @PersistenceContext(unitName = "PersistenceUnit") 
    EntityManager em; 

    public GenericServiceBean() 
    { 
     // empty 
    } 

    @Override 
    public <T> T create(T t) 
    { 
     em.persist(t); 
     return t; 
    } 

    @Override 
    public <T> void delete(T t) 
    { 
     t = em.merge(t); 
     em.remove(t); 
    } 

    @Override 
    public <T> T update(T t) 
    { 
     return em.merge(t); 
    } 

    @Override 
    public <T> T find(Class<T> type, Object id) 
    { 
     return em.find(type, id); 
    } 

    . . . 

    @Override 
    public String executeStoredFunctionWithNamedArguments(String functionName, 
      LinkedHashMap<String, String> namedArguments) 
    { 
     Session session = JpaHelper.getEntityManager(em).getServerSession(); 

     StoredFunctionCall functionCall = new StoredFunctionCall(); 
     functionCall.setProcedureName(functionName);   
     functionCall.setResult("RESULT", String.class); 

     for (String key : namedArguments.keySet()) 
     { 
      functionCall.addNamedArgumentValue(key, namedArguments.get(key)); 
     } 

     ValueReadQuery query = new ValueReadQuery(); 
     query.setCall(functionCall); 

     String status = (String)session.executeQuery(query); 

     return status; 
    } 
} 

如果我將ID字段設置爲不可編輯:

@Id 
    @Column(name = "PARENT", udpatable=false) 
    public String getParent() 
    { 
     return this.parent; 
    } 

並調用parent.setParent(newParent)這會不會更新實體對象中的ID?這如何影響任何兒童實體?他們是否也會更新(或不)?

我不知道如何處理的另一種情況是我需要更新ID和另一個屬性。我是否應該調用更新(和提交)數據庫中ID的函數,然後通過正常的set *方法調用ID和屬性,然後持久化上下文將只提交屬性更改?

也許這是JPA不合適的情況?

對此的任何建議,非常感謝。

回答

4

如果我將ID字段設置爲不可編輯(...)並調用parent.setParent(newParent)這是否仍會更新實體對象中的ID?這如何影響任何兒童實體?他們是否也會更新(或不)?

updatable=false意味着列將不會是SQL UPDATE語句的一部分,無論你在對象級別做什麼,因此Id不應該被更新。而且我也很想說孩子們不應該受到影響,特別是因爲你沒有任何級聯。

另一種情況我不知道如何處理是我需要同時更新ID和其他屬性(...)

嗯,我的理解是,你必須無論如何調用函數,所以我會先打電話。

也許這是JPA不合適的情況?

我不確定原始SQL會更好地處理您的情況。實際上,如果可能的話,改變主鍵的想法聽起來很奇怪。

+0

主鍵由用戶輸入,如果有拼寫錯誤,我們需要讓他們糾正它。我不指望它經常發生,但它是可能的。 – sdoca 2010-07-22 15:21:04

+0

@sdoca:我明白了。但仍然:) – 2010-07-22 15:52:02

+0

我同意,我習慣於使用序列的ID,但我沒有任何控制在這個模式中使用自然主鍵。 – sdoca 2010-07-22 16:01:59