简体   繁体   中英

Hibernate Cascaded update on non primary key column

I have two tables with a structure like this.

  • Tables:

1) Obj table -

在此输入图像描述

2) subobj table

在此输入图像描述

My scenario is I have the is_deleted column, on delete I don't want to delete records instead I want to set is_deleted as true and update the required dependencies.

  • Detailed scenrios:

1) consider, user is deleting a row from obj table having an Id 1.now subobj table rows associated with obj_id 1 should set is_deleted as true.

2) subobj table contains a self-referencing fk 'parent_subobj' . in this case also I want to manage the dependencies for example, if user is deleting subobj record having an id 2 then, is_deleted should be true for records with 'parent_subobj' 2.

Entity classes: (reverse engineered using JBOSS tool)

Obj class :-

@Entity
@Table(name = "obj", schema = "public")
public class Obj implements java.io.Serializable
{
  private static final long serialVersionUID = 1L;

  @Id
  @Column(name = "id", unique = true, nullable = false)
  private int id;

  @Column(name = "obj_name", length = 100)
  private String objName;

  @Column(name = "is_deleted")
  private Boolean isDeleted;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "obj")
  private Set<Subobj> subobjs = new HashSet<Subobj>(0);
 // getters and setters
}

Subobj class :-

@Entity
@Table(name = "subobj", schema = "public")
public class Subobj implements java.io.Serializable
{
  @Id
  @Column(name = "id", unique = true, nullable = false)
  private int id;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "obj_id")
  private Obj obj;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "parent_subobj")
  private Subobj subobj;

  @Column(name = "subobj_name", length = 100)
  private String subobjName;

  @Column(name = "is_deleted")
  private Boolean isDeleted;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "subobj")
  private Set<Subobj> subobjs = new HashSet<Subobj>(0);
} 

so is it possible to do so in Hibernate or I have to create a separate trigger for cascade update. Please suggest the changes required

Hibernate and PostgreSQL only have support for "standard" cascading operations, such as a straight deletion of a record. There are no "out-of-the-box" cascading updates of the kind that you are looking for. You can code the behaviour you are looking for in your java code, but doing it as two triggers is much cleaner and less error-prone (imagine two java apps accessing the same table).

The trigger function and trigger on obj :

CREATE FUNCTION del_obj() RETURNS trigger AS $$
BEGIN
  UPDATE obj SET is_deleted = true WHERE id = OLD.id;
  UPDATE subobj SET is_deleted = true WHERE obj_id = OLD.id;
  RETURN NULL; -- fail the delete operation
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER tr_del_obj
  BEFORE DELETE ON obj
  FOR EACH ROW EXECUTE PROCEDURE del_obj();

The trigger function and trigger on subobj :

CREATE FUNCTION del_subobj() RETURNS trigger AS $$
BEGIN
  UPDATE subobj SET is_deleted = true WHERE id = OLD.id;
  DELETE FROM subobj WHERE parent_subobj = OLD.id;
  RETURN NULL; -- fail the delete operation
END; $$ LANGUAGE plpgsql;

CREATE TRIGGER tr_del_subobj
  BEFORE DELETE ON subobj
  FOR EACH ROW EXECUTE PROCEDURE del_subobj();

Look carefully at the last trigger function. It updates the is_deleted column of the record that is being deleted (but not really) and then deletes the records that refer to it. So when you "delete" a subobj record with id=2 then that record's is_deleted is set to true and then other records with parent_subobj=2 are "deleted". This cascades the update of the field is_deleted without deleting any records. But carefully consider the possibility of a loop here: if you have a record with id=2;parent_subobj=3 and then another record with id=3;parent_subobj=2 you have an endless loop. You can avoid this by carefully managing the assignment of parent_subobj or otherwise use a recursive CTE that checks for loops.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM