Joabe Lucena
Joabe Lucena

Reputation: 812

Hibernate/JPA: Add/Remove child from collection on update() or saveOrUpdate() not working

I have the two classes:

@Entity
@Table(name="Task_Monitor_Header")
@SequenceGenerator(name="INC_TASK_HEADER",sequenceName="GEN_TMH_ID")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Task {

    @Id
    @Column(name="tmh_id")
    @GeneratedValue(strategy=GenerationType.AUTO,generator="INC_TASK_HEADER")
    private Integer id = new Integer(0);

    @ManyToMany
    @Fetch(FetchMode.JOIN)
    @Cascade({CascadeType.SAVE_UPDATE})
    @JoinTable(name="task_equipment",
            joinColumns=@JoinColumn(name="task_id"),
            inverseJoinColumns=@JoinColumn(name="equipment_id"))
    private Set<Equipment> equipments = new HashSet<Equipment>();

    @OneToMany(mappedBy="task", targetEntity = TaskCondition.class, orphanRemoval=true)
    @Fetch(FetchMode.JOIN)
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
    @OrderBy(value="seq")
    private Set<TaskCondition> conditions = new HashSet<TaskCondition>();
    ...
}

and

@Entity
@Table(name="Task_Monitor_Items")
@SequenceGenerator(name="INC_TASK_ITEMS",sequenceName="GEN_TMI_ID")
@JsonIgnoreProperties(ignoreUnknown = true)
public class TaskCondition {

    @Id
    @Column(name="tmi_id")
    @GeneratedValue(strategy=GenerationType.AUTO,generator="INC_TASK_ITEMS")
    private int id;

    @ManyToOne
    @JoinColumn(name="tmi_task_id")
    @JsonBackReference(value="conditions")
    private Task task;
...
}

And when I try add or remove a child from collection conditions, and call hibernate save() or saveOrUpdate() it doesn't change database state but, it works fine if I do the same on equipments (@ManyToMany) collection.

Eg.

public class TaskDaoImpl implements TaskDao {

    @Autowired
    private SessionFactory session;

    @Override
    public void edit(Task task, Authentication authentication) {

        //Retrieve first child of Set
        TaskCondition condition = task.getConditions().iterator().next();

        //Remove that child
        task.getConditions().remove(condition);

        //Update the whole thing
        session.getCurrentSession().saveOrUpdate(task);

    }
}

Could someone help me? I've already tried @CascadeType.DELETE_ORPHAN, orphanRemoval=true without success.

Upvotes: 0

Views: 1385

Answers (2)

Joabe Lucena
Joabe Lucena

Reputation: 812

Thanks everybody for answer, I found the problem!

The problem is that Hibernate before deleting, updates the FK column setting it to null and in my database it was NOT NULL.

And changed it to unidirectional relationship

@OneToMany(fetch=FetchType.EAGER)
@JoinColumn(name="tmi_task_id", referencedColumnName = "tmh_id")
@Cascade({CascadeType.SAVE_UPDATE})
private Set<TaskCondition> conditions;

Upvotes: 0

Bruno S.
Bruno S.

Reputation: 178

If it is a bidirectional relationship, you have to remove the reference from both entities:

task.getConditions().remove(condition);
condition.setTask(null);

The same applies for create.

Upvotes: 3

Related Questions