在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中硬编码模式名称......)
答案 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
对象。