0

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

实体代码如下所示:

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

现在,我的问题是 Web 应用程序不使用表所属的模式的所有者连接到数据库。例如,模式(在 Oracle 中)被调用pizza,而 webapp 用来连接的 db 用户是pizza_webapp. 这是出于安全原因。pizza_webapp用户只有选择/更新/删除权限,不能修改数据库本身的结构。我在这里别无选择,这是我无法改变的政策。

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

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

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

到目前为止,我们通过向模式添加同义词pizza_webapp,指向模式来解决这个问题pizza。它可以工作,但是在添加实体时跨多个数据库进行维护并不有趣。

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

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

4

2 回答 2

1

对的,这是可能的:

@SQLDelete(sql="update {h-schema}pizza set status = 2 where id = ?")
于 2019-10-08T15:16:49.443 回答
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对象在哪里。

于 2012-11-22T11:25:00.350 回答