我正在编写一个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 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不合适的情况?
非常感谢任何有关此建议。
答案 0 :(得分:5)
如果我将ID字段设置为不可编辑(...)并调用
parent.setParent(newParent)
,这还会更新实体对象中的ID吗?这对任何子实体有何影响?他们也会更新(或不更新)吗?
updatable=false
表示无论您在对象级别执行什么操作,该列都不会成为SQL UPDATE语句的一部分,因此不应更新Id
。而且我也很想说儿童实体不应该受到影响,特别是因为你没有级联任何东西。
我不知道如何处理的另一种情况是我需要更新ID和其他属性(...)
好吧,我的理解是你必须先调用这个函数,所以我先调用它。
也许这是JPA不合适的情况?
我不确定原始SQL会更好地处理您的情况。实际上,如果可能的话,改变主键的整个想法听起来很奇怪。