Changes to IndirectSet JPA not reflected in Spring frontend

EDIT: Solved, but I don't know what was different now. If anyone can explain what happened differently, I would appreciate it.

It now works by merging with the parent rather than the child, for example:

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

      

It works now, but I don't quite understand why it would work until my previous attempt did.

Original attempt / question:

I have a problem with Spring JPA and IndirectSets. I have two Parent and Child objects defined below. I have a Spring form in which I am trying to create a new Child and link it to an existing parent and then everything will be reflected in the database and in the frontend. What happens is that it ends up in the database, but the UI doesn't seem to agree.

Two objects that are related to each other in the OneToMany relationship as follows:

@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;
    }
}

      

And, of course, various simple properties on each of them. The problem is when I edit these simple properties from my Spring frontend everything works nicely. I can save new objects of these types and they will show up when I use JPATemplate to search for, say, all parents (getJpaTemplate (). Find ("select p from Parent p")) or for individual objects by ID or some other property.

The problem I am running into is that I am currently trying to create a new child linked to an existing parent from the link from the Parent page. Here's the important controller bits (note that I've put JPA foo in the controller here to make it clearer: the actual JpaDaoSupport is actually in another class, appropriately layered):

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()));
}

      

As I said, I can run the form and fill in the new values ​​for Child - the parent's details are not even displayed. When it goes back to the controller, it goes through and saves it to the underlying database, but the interface never reflects it. As soon as I restart the application, it is all there and populated accordingly.

What can I do to clarify this? I tried to trigger additional merges, tried to update (which gave a transaction exception), all that just didn't write my own database access code. I'm pretty sure each class has appropriate equals () and hashCode (), has full JPA debug to see it making the appropriate SQL calls (it doesn't seem to make any new calls on the Child table), and stepped through the debugger ( all in IndirectSets as expected, and between saving and displaying the Parent object gets a new memory address). What's my next step?

+2


a source to share


1 answer


I'm not sure if this has anything to do with your problem, but why do you have a property childLinkID

in your class Parent

? This seems really strange, especially since you are using the appropriate column for the join. I wonder how one can work with this mapping and I will fix it. Can you try (also uninstall referencedColumnName

, you don't need this)?

And by the way, why don't you establish both sides of the connection between Parent

and Child

in the same method? This makes the code hard to read and is IMO maintainable.




You edited the question as I answered and changed the cascading from Parent

to Child

, but it seems to work around a real issue and I'm not sure if you won't run into other issues. Try to fix your mapping as I suggested.

0


a source







All Articles