Hibernate @SQLDelete sql没有添加架构

时间:2016-08-05 14:13:22

标签: java sql hibernate schema abstract

我正在尝试使用Hibernate的@SQLDelete注释进行软删除。当DB模式是静态的时,它很有效,即:在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中为此行为创建了an issue。我今天晚些时候会创建一个拉取请求,我希望Hibernate团队接受它

3 个答案:

答案 0 :(得分:0)

像这样使用

@SQLDelete(sql = "UPDATE {h-schema}LEAVE  SET STATUS = 'DELETED' WHERE id = ?", check = ResultCheckStyle.COUNT)

答案 1 :(得分:0)

我认为有两种方式 首先是添加:

app.datasource.schema=<schema_name> 

到您的 application.properties。

第二种是在表模型的注释中使用模式 enter image description here

答案 2 :(得分:-1)

Soft deletes using Hibernate annotations.

如链接作者所述:

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

enter image description here

在像Hibernate之类的ORM之前,我必须使用SQL自己跟踪和设置这个标志。这样做并不是很难,但是谁想要编写一堆样板代码只是为了跟踪记录是否已被删除。这就是Hibernate和注释的用武之地。

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

Customer.java

//Package name...

//Imports...

@Entity
@Table(name = "CUSTOMER")
//Override the default Hibernation delete and set the deleted flag rather than deleting the record from the db.
@SQLDelete(sql="UPDATE customer SET deleted = '1' WHERE id = ?")
//Filter added to retrieve only records that have not been soft deleted.
@Where(clause="deleted <> '1'")
public class Customer implements java.io.Serializable {
    private long id;
    private Billing billing;
    private String name;
    private String address;
    private String zipCode;
    private String city;
    private String state;
    private String notes;
    private char enabled;
    private char deleted;
    private Set appUsers = new HashSet(0);

    // Constructors...

    // Getters and Setters...

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer")
    // Filter added to retrieve only records that have not been soft deleted.
    @Where(clause = "deleted <> '1'")
    public Set getAppUsers() {
        return this.appUsers;
    }

    public void setAppUsers(Set appUsers) {
        this.appUsers = appUsers;
    }
}

AppUser.java

//Package name...

//Imports...

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

    // Constructors...

    // Getters and Setters...
}

以下两个步骤是我为实现软删除所必须做的一切。

  1. 添加了覆盖默认值的@SQLDelete注释 Hibernate删除该实体。
  2. 添加了@Where注释以过滤查询并仅返回 未被软删除的记录。另请注意 CUSTOMER类我在appUsers集合中添加了@Where。这是 只需要获取没有的客户的appUsers 被软删了。
  3. 中提琴!现在,只要您删除这些实体,它就会将“DELETED”字段设置为“1”,当您查询这些实体时,它只会返回“DELETED”中包含“0”的记录字段。

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

    注意:

    还要注意,您可以使用hibernate过滤器(http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-filters)来全局过滤掉所有“已删除”的实体,而不是使用@Where(clause="deleted ‘1’")语句。我发现定义了两个实体管理器(“正常”一个过滤掉已删除的项目,另一个没有,对于极少数情况......)通常非常方便。

    使用EntityPersister

    您可以创建DeleteEventListener,例如:

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

    将其挂钩到 persistence.xml ,就像这样

    <property name = "hibernate.ejb.event.delete" value = "org.something.SoftDeleteEventListener"/> 
    

    另外,请勿忘记在注释中更新您的级联。

    资源链接:

    1. Hibernate: Overwrite sql-delete with inheritace
    2. Custom SQL for CRUD operations
    3. Custom SQL for create, update and delete