【问题标题】:JPA - Using insertable/updatableJPA - 使用可插入/可更新
【发布时间】:2011-03-19 03:14:00
【问题描述】:

我正在编写一个 Web 服务来维护一个数据库。我正在尝试将 JPA (EclipseLink) 用于实体类。但是,数据库使用自然主键,因此由于外键约束,ID 字段的更新可能会失败。我们的 DBA 提供了更新 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不合适的情况?

非常感谢您对此提出任何建议。

【问题讨论】:

    标签: java jpa orm eclipselink


    【解决方案1】:

    如果我将 ID 字段设置为不可编辑 (...) 并调用 parent.setParent(newParent),这是否仍会更新实体对象中的 ID?这对任何子实体有何影响?它们也会更新(或不更新)吗?

    updatable=false 表示无论您在对象级别做什么,该列都不会成为 SQL UPDATE 语句的一部分,因此不应更新 Id。而且我还想说子实体不应该受到影响,特别是因为你没有级联任何东西。

    另一个我不知道如何处理的场景是我需要同时更新 ID 和另一个属性 (...)

    好吧,我的理解是无论如何你都必须调用该函数,所以我会先调用它。

    也许这是JPA不合适的情况?

    我不确定原始 SQL 是否能更好地处理您的情况。实际上,如果可以的话,更改主键的整个想法听起来很奇怪。

    【讨论】:

    • 主键是用户输入的,如果有错别字,我们需要让他们更正。我不希望它经常发生,但有可能。
    • 我同意,我习惯于使用 ID 序列,但我无法控制此架构中自然主键的使用。
    • @sdoca:我猜到你不能改变模型,所以我没有坚持。
    猜你喜欢
    • 1970-01-01
    • 2015-11-01
    • 2012-07-01
    • 2016-03-16
    • 2012-08-19
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2021-03-15
    相关资源
    最近更新 更多