Hibernate @SQLDelete sql没有添加架构

Laa*_*ssi 13 java sql schema hibernate abstract

我试图使用@SQLDeleteHibernate 的注释进行软删除.当数据库模式是静态的时,它很有效,即:在SQL中传递它.
不幸的是,似乎SQL按原样传递给了EntityPersisters(cf EntityClass的方法,CustomSQL createCustomSQL(AnnotationInstance customSqlAnnotation)所以我无法找到一种方法来动态传递模式名称,就像在Native SQL查询中一样使用{h-schema}
了没有人为这个问题找到一个好的解决方法(我正在使用Hibernate 4.3.5)?

编辑:除非有真正的解决方案,否则org.hibernate.persister.entity.AbstractEntityPersister在方法中设置自定义SQL查询时,我最终通过替换架构占位符来修改代码源doLateInit.

Edit2:我在Hibernate JIRA中为这种行为创建了一个问题.我将在今天晚些时候创建一个拉取请求,我希望Hibernate团队能够接受它

Sky*_*ker 1

使用 Hibernate 注释进行软删除。

\n\n

正如链接作者所述:

\n\n

我目前正在开发一个 Seam 应用程序,该应用程序需要在数据库中进行软删除。在右侧,您可以看到我的数据库图表的片段,其中包含一个CUSTOMERAPP_USER表。这只是一个直接的一对多关系,但需要注意的重要一点是每个表中的 \xe2\x80\x9cDELETED\xe2\x80\x9d 字段。该字段将用于跟踪软删除。如果该字段包含\xe2\x80\x981\xe2\x80\x99,则该记录已被删除,如果该字段包含\xe2\x80\x980\xe2\x80\x99,则该记录尚未\xe2\x80\x99被删除。

\n\n

在此输入图像描述

\n\n

在使用像 Hibernate 这样的 ORM 之前,我必须自己使用 SQL 来跟踪和设置这个标志。\xe2\x80\x99 不会非常难做到,但谁愿意编写一堆样板代码只是为了跟踪记录是否已被删除。这就是 Hibernate 和注释发挥作用的地方。

\n\n

下面是 Hibernate 使用 seamgen 生成的 2 个实体类。为了清楚起见,我省略了部分代码。

\n\n

客户.java

\n\n
//Package name...\n\n//Imports...\n\n@Entity\n@Table(name = "CUSTOMER")\n//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.\n@SQLDelete(sql="UPDATE customer SET deleted = \'1\' WHERE id = ?")\n//Filter added to retrieve only records that have not been soft deleted.\n@Where(clause="deleted <> \'1\'")\npublic class Customer implements java.io.Serializable {\n    private long id;\n    private Billing billing;\n    private String name;\n    private String address;\n    private String zipCode;\n    private String city;\n    private String state;\n    private String notes;\n    private char enabled;\n    private char deleted;\n    private Set appUsers = new HashSet(0);\n\n    // Constructors...\n\n    // Getters and Setters...\n\n    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer")\n    // Filter added to retrieve only records that have not been soft deleted.\n    @Where(clause = "deleted <> \'1\'")\n    public Set getAppUsers() {\n        return this.appUsers;\n    }\n\n    public void setAppUsers(Set appUsers) {\n        this.appUsers = appUsers;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

应用程序用户.java

\n\n
//Package name...\n\n//Imports...\n\n@Entity\n@Table(name = "APP_USER")\n//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.\n@SQLDelete(sql="UPDATE app_user SET deleted = \'1\' WHERE id = ?")\n//Filter added to retrieve only records that have not been soft deleted.\n@Where(clause="deleted <> \'1\'")\npublic class AppUser implements java.io.Serializable {\n    private long id;\n    private Customer customer;\n    private AppRole appRole;\n    private char enabled;\n    private String username;\n    private String appPassword;\n    private Date expirationDate;\n    private String firstName;\n    private String lastName;\n    private String email;\n    private String phone;\n    private String fax;\n    private char deleted;\n    private Set persons = new HashSet(0);\n\n    // Constructors...\n\n    // Getters and Setters...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以下两个步骤是我实现软删除所需要做的全部操作。

\n\n
    \n
  1. 添加了@SQLDelete注释,该注释将覆盖该实体的默认\nHibernate 删除。
  2. \n
  3. 添加@Where注释来过滤查询,仅返回\n未软删除\xe2\x80\x99的记录。另请注意,在\nCUSTOMER 类中,我@Where向 appUsers 集合添加了 。这\n需要仅获取该客户尚未被软删除的\nappUsers。
  4. \n
\n\n

中提琴!现在,每当您删除这些实体时,它都会将\xe2\x80\x9cDELETED\xe2\x80\x9d字段设置为 \xe2\x80\x981\xe2\x80\x99 ,当您查询这些实体时,它只会返回包含\xe2\x80\x980\xe2\x80\x99 在\xe2\x80\x9cDELETED\xe2\x80\x9d字段中。

\n\n

难以置信,但这就是使用 Hibernate 注释实现软删除的全部内容。

\n\n

笔记:

\n\n

另请注意,@Where(clause="deleted \xe2\x80\x981\xe2\x80\x99")您可以使用 hibernate 过滤器(http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-filters)全局过滤掉所有 \ xe2\x80\x98删除了\xe2\x80\x99实体。我发现定义 2 个实体管理器(\xe2\x80\x98normal\xe2\x80\x99 一个过滤已删除的项目,另一个不过滤\xe2\x80\x99t,对于极少数情况\xe2\x80\xa6)通常是相当方便。

\n\n

使用EntityPersister

\n\n

您可以创建一个DeleteEventListener诸如:

\n\n
public class SoftDeleteEventListener extends DefaultDeleteEventListener {\n\n/**\n * \n */\nprivate static final long serialVersionUID = 1L;\n\n@Override\npublic void onDelete(DeleteEvent event, Set arg1) throws HibernateException {\n    Object o = event.getObject();\n    if (o instanceof SoftDeletable) {\n        ((SoftDeletable)o).setStatusId(1);\n        EntityPersister persister = event.getSession().getEntityPersister( event.getEntityName(), o);\n        EntityEntry entityEntry = event.getSession().getPersistenceContext().getEntry(o);\n        cascadeBeforeDelete(event.getSession(), persister, o, entityEntry, arg1);\n\n        cascadeAfterDelete(event.getSession(), persister, o, arg1);\n\n    } else {\n        super.onDelete(event, arg1);\n    }\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

像这样将它挂接到你的persistence.xml中

\n\n
<property name = "hibernate.ejb.event.delete" value = "org.something.SoftDeleteEventListener"/> \n
Run Code Online (Sandbox Code Playgroud)\n\n

另外,不要忘记更新注释中的级联。

\n\n

资源链接:

\n\n
    \n
  1. Hibernate:用继承覆盖sql-delete
  2. \n
  3. 用于 CRUD 操作的自定义 SQL
  4. \n
  5. 用于创建、更新和删除的自定义 SQL
  6. \n
\n