当前位置: 首页 > 知识库问答 >
问题:

非主键列上的Hibernate级联更新

东郭淇
2023-03-14

我有两张这样结构的桌子。

  • 表:

1) Obj表-

2) subobj表

我的场景是我有is_deleted列,在delete上我不想删除记录,而是想将is_deleted设置为true并更新所需的依赖项

  • 详细场景:

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

2) 子对象表包含自引用fk“父对象”子对象。在这种情况下,我还想管理依赖关系,例如,如果用户正在删除id为2的子对象记录,那么对于具有“parent_subobj”2的记录,“is_deleted”应该为true。

实体类:(使用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
}

子对象类:-

@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个答案

呼延衡
2023-03-14

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=2子对象记录“删除”时,该记录的将被删除设置为true,然后使用父对象的其他记录将被“删除”。这将级联字段的更新是否已删除,而不删除任何记录。但是仔细考虑这里有一个循环的可能性:如果你有一个记录<代码> ID=2;父项_subobj=3,然后是另一条id=3的记录;parent_subobj=2您有一个无止境的循环。您可以通过仔细管理parent\u subbj的赋值或使用递归CTE检查循环来避免这种情况。

 类似资料:
  • 问题内容: 有没有一种方法可以将两个主键合并为一个,然后级联更新所有受影响的关系?这是场景: 客户(idCustomer int PK,公司varchar(50)等) CustomerContacts(idCustomerContact int PK,idCustomer int FK,名称varchar(50)等) CustomerNotes(idCustomerNote int PK,idCu

  • 我想使用Hibernate条件语言编写此查询。我对Hibernate很陌生,无法将此查询转换为条件形式。我参考了很多关于 SO 的答案,但就我而言,我在不同的列上使用内部连接而不是主键/外键列。我提到了这个,但仍然不能正确。

  • 问题内容: 我遇到一种情况,我需要在ORM类层次结构中的对象上联接表,其中join列不是基类的主键。这是表格设计的示例: 这是映射(为简洁起见,省略了getter和setter方法 鉴于其连接列不是,我如何添加映射? 我尝试了以下方法: 这将失败,因为用于检索Bar对象的SQL试图从FOO表中获取BAR_ID值。我也尝试过将JoinTable注释替换为 这不会产生SQL错误,也不会检索任何数据,因

  • 我正在处理遗留系统,需要从数据库中读取一些信息。下面是表格关系 供应商(vendorid-pk,vendorEid,name) VendorContactBridge(bridgeid-pk,vendorEid,contactEid) 联系人(contactid-pk,contactEid,phone) vendorEid和contactEid不是表的主键,但用作联接表VendoContactBr

  • 在我的jpa映射中,我试图将带有一个主键的父类映射到带有复合键的子类,但似乎插入了错误的表,它已经生成了2个表,但不幸的是我没有绑定外键(policy_value_summary_id) 我试图用策略值(子类)保存策略摘要值(父),如下所示 下面是输出给我的错误

  • 问题内容: 我收到的时候我想改变我的以下异常中的。 我知道我要更改表中的主键。我正在使用JPA注释。 我通过使用以下单个HQL查询解决了此问题: 而不是使用更多的OO方法: 知道差异是什么吗? 问题答案: 我无法想象你为什么要这么做。完全没有 您为什么要更改实体的身份?您还需要更新指向它的其他表中的所有外键。似乎很痛苦,没有收获。您最好将其设置为“业务密钥”(普通属性),并使用更永久的代理密钥。我