java - Hibernate 非主键列的级联更新

标签 java sql database hibernate postgresql

我有两个具有这样结构的表。

  • 表格:

1) 对象表 -

enter image description here

2) 子对象表

enter image description here

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

  • 详细场景:

1) 考虑,用户正在从 obj 表中删除 ID 为 1 的行。现在与 obj_id 1 关联的子 obj 表行应将 is_deleted 设置为 true。

2) subobj 表包含一个自引用 fk 'parent_subobj'。在这种情况下,我也想管理依赖关系,例如,如果用户删除 ID 为 2 的 subobj 记录,则对于 'parent_subobj' 2 的记录,is_deleted 应该为 true .

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

对象类:-

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

子对象类:-

@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 中这样做,或者我必须创建一个单独的触发器来进行级联更新。请提出所需的更改

最佳答案

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 列,然后删除引用它的记录。因此,当您“删除”带有 id=2subobj 记录时,该记录的 is_deleted 将设置为 true 并且那么其他带有 parent_subobj=2 的记录将被“删除”。这会级联字段 is_deleted 的更新,而不删除任何记录。但请仔细考虑这里出现循环的可能性:如果您有一 strip 有 id=2;parent_subobj=3 的记录,然后又有一 strip 有 id=3;parent_subobj=2 的记录,那么您有无限循环。您可以通过仔细管理 parent_subobj 的分配或使用 recursive CTE 来避免这种情况。检查循环。

关于java - Hibernate 非主键列的级联更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30499309/

相关文章:

java - 我该怎么做才能使 jar /类更小?

sql - 帮我找到数据 block

SQL Server : create dynamically queries to select all related data in DB based on entry table and ID

java - 从实现类覆盖自定义 jar 文件中的配置属性时,entityManagerFactory 中出现错误

java - 单生产者多消费者 Java

java - 更新Android的Sqlite和ContentValues中的值

SQL:在一条语句中插入多组值?

mysql查询结果。将三列值转换为结果中的一行并按第一列值排序

java - 创建单个对象时如何执行多个构造函数

sql - Oracle:采用前 n 条记录的优雅方式(top-k 查询)