Laa*_*ssi 13 java sql schema hibernate abstract
我试图使用@SQLDelete
Hibernate 的注释进行软删除.当数据库模式是静态的时,它很有效,即:在SQL中传递它.
不幸的是,似乎SQL按原样传递给了EntityPersister
s(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团队能够接受它
正如链接作者所述:
\n\n我目前正在开发一个 Seam 应用程序,该应用程序需要在数据库中进行软删除。在右侧,您可以看到我的数据库图表的片段,其中包含一个CUSTOMER
和APP_USER
表。这只是一个直接的一对多关系,但需要注意的重要一点是每个表中的 \xe2\x80\x9cDELETED\xe2\x80\x9d 字段。该字段将用于跟踪软删除。如果该字段包含\xe2\x80\x981\xe2\x80\x99,则该记录已被删除,如果该字段包含\xe2\x80\x980\xe2\x80\x99,则该记录尚未\xe2\x80\x99被删除。
在使用像 Hibernate 这样的 ORM 之前,我必须自己使用 SQL 来跟踪和设置这个标志。\xe2\x80\x99 不会非常难做到,但谁愿意编写一堆样板代码只是为了跟踪记录是否已被删除。这就是 Hibernate 和注释发挥作用的地方。
\n\n下面是 Hibernate 使用 seamgen 生成的 2 个实体类。为了清楚起见,我省略了部分代码。
\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//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@SQLDelete
注释,该注释将覆盖该实体的默认\nHibernate 删除。@Where
注释来过滤查询,仅返回\n未软删除\xe2\x80\x99的记录。另请注意,在\nCUSTOMER 类中,我@Where
向 appUsers 集合添加了 。这\n需要仅获取该客户尚未被软删除的\nappUsers。中提琴!现在,每当您删除这些实体时,它都会将\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另请注意,@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)通常是相当方便。
您可以创建一个DeleteEventListener
诸如:
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 归档时间: |
|
查看次数: |
1023 次 |
最近记录: |