0

Here is my entities:

@Entity
@Table(name="workflows") 
public class WorkflowDB {
...
    @OneToMany(cascade = CascadeType.ALL, mappedBy="workflow", fetch = FetchType.EAGER)
    private Set<ActivityDB> activities; 
...
}


@Entity
@Table(name="activities") 
public class ActivityDB {
...
    @ManyToOne
    @JoinColumn(name="id_workflow")
    @Fetch(FetchMode.JOIN)
    private WorkflowDB workflow;    

    @OneToMany(cascade = CascadeType.ALL)
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinTable(name = "dependency", joinColumns = {
        @JoinColumn(name = "id_activity")}, inverseJoinColumns = {
        @JoinColumn(name = "id_dependent")})
    private Set<ActivityDB> dependencyActivities;
...
}

PS: Don't ask me why this strange (to me) @OneToMany. See here

Well, I have a Workflow. This Workflow have nodes ( activities ) wich are a graph ( nodes can have nodes to build a path )

Lets say I have a Workflow "W". So, "W".activities = {Ac1, Ac2} But, "Ac1".dependencyActivities = { Ac2 }

When I save the workflow by the first time, with some activities in "activities" Set, or when I update the workflow, all it's activities are duplicated in database, receiving new IDs.

The "activities" table will show:

-----------
! 1 ! Ac1 !
-----------
! 2 ! Ac2 !
-----------
! 3 ! Ac2 !
-----------

I supose Ac2 is duplicated because its in "W".activities set AND "Ac1".dependencyActivities set. Am I correct?

What can I do to avoid this behaviour? How to update the workflow AND it's children (and children of children recursively) at once?

****EDIT**** I think the point is how I see the dependency chain of the activities. All dependency solutions are wellcome.

Community
  • 1
  • 1
Magno C
  • 1,922
  • 4
  • 28
  • 53
  • @ JoinTable and @ OneToMany is fishy, try @ ManyToMany. Also on the @OneToMany in WorkflowDB use updatable=false, so, the activities will not be updated when the workflowDB is updated – Zeus Jul 10 '14 at 15:45
  • I've edited my question. Can you explain your comment in a answer? – Magno C Jul 10 '14 at 15:51
  • I cannot use @ManyToMany: One node belongs to just ONE workflow. – Magno C Jul 10 '14 at 15:54

1 Answers1

0

In the WorkflowDB @OneToMany mapping use updatable=false, so, the activities will not be updated when the workflowDB is updated like below.

@Entity
@Table(name="workflows") 
public class WorkflowDB {
...
    @OneToMany(cascade = CascadeType.ALL, mappedBy="workflow", fetch = FetchType.EAGER, **updatable=false**)
    private Set<ActivityDB> activities; 
...
}
Zeus
  • 6,386
  • 6
  • 54
  • 89
  • @MagnoC try to do it in all the relationships, it will help avoid unnecessary updates to the child entities. – Zeus Jul 10 '14 at 15:55
  • Well, I forgot to say : All Activities must be refreshed when I save the workflow. The steps are: 1) the user load a workflow. 2) the user create some activities (and dependencies). 3) the user save the workflow (and all activities and dependencies). If the workflow have activities already, they must be updated, if not, must be added ( and it's dependency chain). – Magno C Jul 10 '14 at 15:59
  • In that case updatable attribute does not make sense. Can you record what you store in the db the first time you save a workflow object and after you update. My concern is, if you add AC2 to WF.Activities list and AC2 to AC1.dependancies for the first time, hibernate might end up adding two rows with AC2 in the DB the first time itself rather than wait for the update because hibernate does not know if the AC2 is same or different in both the lists. – Zeus Jul 10 '14 at 16:12
  • In order for this to work, you need to store the ActivityDB items first and then use these stored entities to update/save the workflow table and dependance table, so hibernate would know the references well. – Zeus Jul 10 '14 at 16:25
  • Yeap! I think I won't need to create the "Activity" repository because the activities do not need to be updated alone, only in workflow update event. The first object to go to database is the workflow (always without activities). When I update the workflow, it's in persistent state and it's activities list may have (or not) some persistent and transient activities. Each activity dependency list may have persistent and transient activities too. I'm almost killing all of then and recreate all the list because it's small, but will have unnecessary increase of the primary key ID. – Magno C Jul 10 '14 at 16:41
  • Are you saying you will delete all and re-insert the transient/detached entities back into the db every time you update the workflow? (Activities) – Zeus Jul 10 '14 at 17:24
  • No, no... Just said my head is hot enough to make me do this. But I know it's a bad thing to do. Just a joke. I create another entity called "dependencies" and create a routine that take the "activities" from workflow and check if there is a persistent activity. If no, ADD, if yes, do not touch. Will post the results soon. – Magno C Jul 10 '14 at 18:25
  • Solved using code control. I check if there is a persistent copy of Activities on Workflow persistent instance just before save ( using an attribute 'tag'). I can successfully avoid dupicating. – Magno C Jul 11 '14 at 11:59