我正在编写一个Web服务来维护数据库.我正在尝试将JPA(EclipseLink)用于实体类.但是,数据库使用自然主键,因此由于外键约束,ID字段的更新可能会失败.我们的DBA提供了一个更新ID字段的功能,这些ID字段将创建具有更新ID的新父记录,更新子记录以指向新父记录并删除旧父记录.
如果ID字段可以"正常"更新,我会遇到这样的情况:
@Entity @Table(name = "PARENT") public class Parent implements Serializable { private static final long serialVersionUID = 1L; private String parent; private String attribute; private Setchilds; 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 getChilds() { return this.childs; } public void setChilds(Set 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 publicT create(T t) { em.persist(t); return t; } @Override public void delete(T t) { t = em.merge(t); em.remove(t); } @Override public T update(T t) { return em.merge(t); } @Override public T find(Class type, Object id) { return em.find(type, id); } . . . @Override public String executeStoredFunctionWithNamedArguments(String functionName, LinkedHashMap 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不合适的情况?
对此有任何建议非常感谢.
如果我将ID字段设置为不可编辑(...)并且调用
parent.setParent(newParent)
将仍然更新实体对象中的ID?这对任何子实体有何影响?它们是否也会更新(或不更新)?
updatable=false
表示无论您在对象级别执行什么操作,该列都不会成为SQL UPDATE语句的一部分,因此Id
不应更新该列.而且我也很想说儿童实体不应该受到影响,特别是因为你没有任何级联.
我不知道如何处理的另一个场景是我需要更新ID和另一个属性(...)
好吧,我的理解是你无论如何都要调用这个函数,所以我先调用它.
也许这是JPA不合适的情况?
我不确定原始SQL会更好地处理您的情况.实际上,如果可能的话,改变主键的整个想法听起来很奇怪.