1
votes

Suppose their are two tables:

(1)Parent :parent_id(PK),parent_name,create_date,update_date

(2)Child :child_id(PK),child_name,create_date,update_date

Now while using @manytomany a third table would be created.Let it be : (3)Parent_Child

Typicall, the JPA provider will create a join table by using primary keys (i.e. parent_id and child_id). My question is that can we have any possibility of having column to set create_date/update_date by using @manytomany relationship while updating or creating.

2
Do you want to set create_date/update_date on child when you update/create a parent or the other way around?White Feather
Thanks for ur reply buddy....gulshan kumar
While inserting on parent to child or child to parent I need to update my third table (parent_child) with create_date/update_date (Basically we always use id"s for @ many to many so I need to know whether it is possible with other columns ,here create_date/update_date)gulshan kumar

2 Answers

0
votes

If I understand well you are trying to link parent and child through create OR update datetime. It means that you will always have to sync these elements during creation and update and than join them appropriately like in:

SELECT
*
FROM
parent
LEFT JOIN child
    ON parent.create_date = child.create_date 
        OR parent.update_date = child.update_date;

Anyway I would say this is not safe, as create_date and update_date are not necessarily unambiguous.

Regards

0
votes

Update: I researched it a little bit and found that people have made an Association Entity to solve this sort of problem. There are some limitations with doing that, but the end result doesn't look overly terrible. Still, there might be some better ways to design this that I haven't thought about yet.

The Parent entity will have a OneToMany mapping to the ParentChild association entity. The mappedBy attribute must be set to force the usage of the association entity:

@Entity
public class Parent {
    @Id @GeneratedValue private Long id;

    @OneToMany(mappedBy="parent", cascade=CascadeType.ALL)
    private List<ParentChild> children = new ArrayList<ParentChild>();

    public void addChild(Child child, boolean teamLead) {
        ParentChild association = new ParentChild();
        association.setChild(child);
        association.setParent(this);
        association.setTeamLead(teamLead);
        children.add(association);
        child.setParent(this);
    }
    public Long getId() { return id; }

}

and the child entity will hold a reference to the Parent entity, as is usual with a unidirectional ManyToMany relationship.

@Entity
public class Child {
    @Id @GeneratedValue private Long id;

    @ManyToOne
    private Parent parent;

    public Parent getParent() { return parent; }
    public void setParent(Parent parent) { this.parent = parent; }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
}

Then the association entity will have ManyToOne references to both entities, plus a primary key. The association references use the same id field as the primary key because of the @MapsId annotation.

@Entity
public class ParentChild {
    @EmbeddedId
    private ParentChildKey id;

    @ManyToOne
    @MapsId("parentId")
    private Parent parent;

    @ManyToOne
    @MapsId("childId")
    private Child child;

    private boolean teamLead;

    public ParentChild() { id = new ParentChildKey(); }
    public boolean isTeamLead() { return teamLead; }
    public void setTeamLead(boolean teamLead) { this.teamLead = teamLead; }
    public Parent getParent() { return parent; }
    public void setParent(Parent parent) { this.parent = parent; id.setParentId(parent.getId());}
    public Child getChild() { return child; }
    public void setChild(Child child) { this.child = child; id.setChildId(child.getId());}

}

Nothing special about the primary key entity.

@Embeddable
public class ParentChildKey implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long parentId;
    private Long childId;
    public Long getParentId() { return parentId; }
    public void setParentId(Long parentId) { this.parentId = parentId; }
    public Long getChildId() { return childId; }
    public void setChildId(Long childId) { this.childId = childId; }    
    ... getters and setters
}

So, it did an insert and select for me without too much trouble, but you can see it seems like a lot of extra work just for an extra field. Of course, the extra field (in this case, teamLead) is stored efficiently, but I can imagine a sort of "roles" type configuration that would be easier to work with and make more sense in the long run.