是否有可能使`@ SQLDelete`考虑`hibernate.default_schema`参数?

时间:2012-11-21 16:36:49

标签: sql hibernate annotations

在webapp中,我使用Hibernate的@SQLDelete注释来“软删除”实体(即将状态列设置为表示其“已删除”状态的值,而不是实际从表中删除它们)

实体代码如下所示:

@Entity
@SQLDelete(sql="update pizza set status = 2 where id = ?")
public class Pizza { ... }

现在,我的问题是Web应用程序不使用表所属的架构的所有者连接到DB。例如。架构(在Oracle中)称为pizza,而webapp用于连接的db用户是pizza_webapp。这是出于安全原因。 pizza_webapp用户只有select / update / delete权限,不能修改DB本身的结构。我在这里没有任何选择,这是一项我无法改变的政策。

我在hibernate config中使用hibernate-default_schema参数指定表实际所在的模式的名称:

<property name="hibernate.default_schema">pizza</property>

这适用于通过映射实体的所有内容,Hibernate知道如何在它生成的SQL中的表名前面添加模式名称。但不适用于原始SQL,@SQLDelete包含原始SQL。这是“按原样”执行的,并产生"table or view not found error"

到目前为止,我们通过向pizza_webapp架构添加同义词来解决此问题,指向pizza架构。它有效,但在添加实体时维护多个DB并不好玩。

那么,是否可以让@SQLDelete考虑hibernate.default_schema参数?

(注意:显然我不想在SQL中硬编码模式名称......)

2 个答案:

答案 0 :(得分:1)

是的,有可能:

@SQLDelete(sql="update {h-schema}pizza set status = 2 where id = ?")

答案 1 :(得分:0)

我找不到任何针对此问题的Hibernate解决方案。但是我找到了一个基于Oracle功能的变通方法。我在使用它之前执行此操作:

//set the default schema at DB session level for raw SQL queries (see @SQLDelete)
HibernateUtil.currentSession().doWork(new Work() {
    @Override
    public void execute(Connection connection) throws SQLException {
        connection.createStatement().execute("ALTER SESSION SET CURRENT_SCHEMA="+HibernateUtil.getDefaultSchema());
    }
});

我的工作正常,但不幸的是只在Oracle上(至少对我们来说这是好的)。也许有不同的方法在其他RDBMS上实现相同的东西?

编辑:getDefaultSchema()类中的HibernateUtil方法执行此操作以从Hibernate的配置中获取默认架构:

defaultSchema = config.getProperty("hibernate.default_schema");

其中config是我的org.hibernate.cfg.Configuration对象。