JPA IndirectSet更改未反映在Spring前端中

时间:2010-04-29 23:42:19

标签: spring orm jpa spring-mvc toplink-essentials

编辑:解决了,但我不知道现在有什么不同。如果有人能够解释发生的事情,我会很感激。

现在它的工作方式是只合并父母而不是儿童,如下:

Parent parent = child.getParent();
parent.getChildren().add(child);
getJpaTemplate().merge(parent);

现在,它似乎正在起作用,但我不明白为什么这会在我之前的尝试没有的情况下起作用。

原始尝试/问题:

我遇到了Spring JPA和IndirectSets的问题。我有两个实体,父和子,定义如下。我有一个Spring表单,我正在尝试创建一个新的Child并将其链接到现有的Parent,然后将所有内容反映在数据库和Web界面中。发生的事情是它被放入数据库,但UI似乎不同意。

在OneToMany关系中相互链接的两个实体,如下所示:

@Entity
@Table(name = "parent", catalog = "myschema", uniqueConstraints = @UniqueConstraint(columnNames = "ChildLinkID"))
public class Parent {
    private Integer id;
    private String childLinkID;

    private Set<Child> children = new HashSet<Child>(0);

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "ChildLinkID", unique = true, nullable = false, length = 6)
    public String getChildLinkID() {
        return this.childLinkID;
    }

    public void setChildLinkID(String childLinkID) {
        this.childLinkID = childLinkID;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
    public Set<Child> getChildren() {
        return this.children;
    }

    public void setChildren(Set<Child> children) {
        this.children = children;
    }
}

@Entity
@Table(name = "child", catalog = "myschema")
public class Child extends
    private Integer id;
    private Parent parent;

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ChildLinkID", referencedColumnName = "ChildLinkID", nullable = false)
    public Parent getParent() {
        return this.parent;
    }

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

当然,每种都有各种简单的属性。现在,问题在于,当我从Spring界面编辑这些简单的属性时,一切都运行得很漂亮。我可以坚持使用这些类型的新实体,当使用JPATemplate对所有父母(getJpaTemplate()。find(“从父p中选择p”))或按ID或单个实体进行查找时,它们会出现另一个属性。

我遇到的问题是,现在,我正在尝试通过Parent页面中的链接创建一个链接到现有Parent的新Child。这是控制器的重要部分(请注意,我已将JPA foo放在控制器中以使其更清晰;实际的JpaDaoSupport实际上在另一个类中,适当分层):

protected Object formBackingObject(HttpServletRequest request) throws Exception {
    String parentArg = request.getParameter("parent");
    int parentId = Integer.parseInt(parentArg);
    Parent parent = getJpaTemplate().find(Parent.class, parentId);
    Child child = new Child();
    child.setParent(parent);
    NewChildCommand command = new NewChildCommand();
    command.setChild(child);
    return command;
}

protected ModelAndView onSubmit(Object cmd) throws Exception {
    NewChildCommand command = (NewChildCommand)cmd;
    Child child = command.getChild();
    child.getParent().getChildren().add(child);
    getJpaTemplate().merge(child);
    return new ModelAndView(new RedirectView(getSuccessView()));
}

就像我说的那样,我可以浏览表单并填写Child的新值 - 甚至不显示Parent的详细信息。当它返回到控制器时,它会通过并将其保存到底层数据库,但接口从不反映它。一旦我重新启动应用程序,它就会全部存在并正确填充。

我该怎么做才能清除它?我试图调用额外的合并,尝试刷新(这给了一个事务异常),一切都只是编写我自己的数据库访问代码。我已经确保每个类都有一个适当的equals()和hashCode(),有完整的JPA调试,看它正在进行适当的SQL调用(它似乎没有对Child表进行任何新的调用)和步骤通过调试器(它在IndirectSets中,如预期的那样,在保存和显示Parent之间,对象采用新的内存地址)。我的下一步是什么?

1 个答案:

答案 0 :(得分:0)

不确定这与您的问题有关,但为什么您的childLinkID课程中有Parent属性?这看起来很奇怪,特别是因为您使用相应的列进行连接。我想知道这个映射是如何工作的,我会解决这个问题。你可以试试吗(也删除referencedColumnName,你不需要这个)?

顺便说一句,为什么不在同一方法中设置ParentChild之间的链接的两边?这使得代码难以阅读并维护IMO。


您在我回答时编辑了问题,并将级联从Parent更改为Child,但这看起来像是解决了真正的问题,我不确定您是否会面对其他问题问题。请按照我的建议尝试修复您的映射。