2010-07-21 75 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