非主键列

时间:2015-05-28 06:58:41

标签: java sql database hibernate postgresql

我有两个表格,结构如下。

1)对象表 -

enter image description here

2)subobj表

enter image description here

我的方案是我有is_deleted列,在删除时我不想删除记录而是要将 is_deleted设置为true 并更新所需的依赖项。

  • 详细的scenrios:

1)考虑,用户正在从obj表中删除一行,该表具有Id 1.now subobj表与obj_id相关联的行1应将is_deleted设置为true。

2)subobj表包含自引用fk ' parent_subobj' 。在这种情况下,我也想管理依赖项,例如,如果用户正在删除id为2的subobj记录,那么 is_deleted 应该为' parent_subobj' 2。

实体类:(使用JBOSS工具进行逆向工程)

Obj类: -

@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类: -

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

所以可以在Hibernate中这样做,或者我必须为级联更新创建一个单独的触发器。请建议所需的更改

1 个答案:

答案 0 :(得分:2)

Hibernate和PostgreSQL仅支持“标准”级联操作,例如直接删除记录。没有您想要的那种“开箱即用”级联更新。您可以在java代码中编写您正在寻找的行为,但是将其作为两个触发器进行编写更简洁,更不容易出错(假设两个Java应用程序访问同一个表)。

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

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

仔细查看最后一个触发功能。它更新正在删除的记录的is_deleted列(但不是真的),然后删除引用它的记录。因此,当您使用subobj“删除”id=2条记录时,该记录的is_deleted将设置为true,然后其他记录parent_subobj=2将被“删除”。这将级别更新字段is_deleted而不删除任何记录。但仔细考虑循环的可能性:如果你有一个id=2;parent_subobj=3的记录,然后另一个记录id=3;parent_subobj=2你有一个无限循环。您可以通过仔细管理parent_subobj的分配或以其他方式使用检查循环的recursive CTE来避免这种情况。