oracle 在只读同义词上禁用刷新时休眠自动更新

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1056747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 18:28:36  来源:igfitidea点击:

Disable Hibernate auto update on flush on read only synonyms

oraclehibernatespring

提问by Arvind

I have a table and two databases which have the same table, but one is a symlink of the other one and only read is permitted on this table.

我有一个表和两个具有相同表的数据库,但一个是另一个的符号链接,并且该表只允许读取。

I have mapped the table to Java using Hibernate and I use spring to set the Entity Manager's data source as one of the two databases based on some input criteria.

我已使用 Hibernate 将表映射到 Java,并使用 spring 根据某些输入条件将实体管理器的数据源设置为两个数据库之一。

I call only read only operations (selects) when I am connected to the second database, but it seems Hibernate tries to flush something back to the database and it fails telling update is not allowed on this view.

当我连接到第二个数据库时,我只调用只读操作(选择),但似乎 Hibernate 尝试将某些内容刷新回数据库,但它未能告诉此视图不允许更新。

How do I disable this update only for the second datasource and keep it normal for the first one?

如何仅对第二个数据源禁用此更新并为第一个数据源保持正常?

Update: Looking at the stack trace, the flush seems to be started here:

更新:查看堆栈跟踪,刷新似乎从这里开始:

          at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
          at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
          at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
          at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
          at org.hibernate.ejb.AbstractEntityManagerImpl.beforeCompletion(AbstractEntityManagerImpl.java:504)
          ... 55 more

Is this related to hibernate.transaction.flush_before_completion property? Can I set it to false for the second data source?

这与 hibernate.transaction.flush_before_completion 属性有关吗?对于第二个数据源,我可以将其设置为 false 吗?

回答by Stefan Steinegger

Most probably your entities become "dirty" the same moment they are loaded from the database, and Hibernate thinks that it needs to store the changes. This happens, if your accessors (get and set methods) are not returning the exact same value or referencethat had been set by Hibernate.

很可能您的实体在从数据库加载的同时变得“脏”,并且 Hibernate 认为它需要存储更改。如果您的访问器(get 和 set 方法)没有返回与Hibernate 设置的完全相同的值或引用,就会发生这种情况。

In our code, this happened with lists, developers created new list instances because they didn't like the type they got in the setter.

在我们的代码中,这发生在列表中,开发人员创建了新的列表实例,因为他们不喜欢在 setter 中获得的类型。

If you don't want to change the code, change the mapping to field access.

如果您不想更改代码,请将映射更改为字段访问。

You can also prevent Hibernate of storing changes by setting FlushMode to never on the session, but this only hides the real problem which will still occur in other situations an will lead to unnecessary updates.

您还可以通过在会话中将 FlushMode 设置为从不来防止 Hibernate 存储更改,但这只会隐藏在其他情况下仍然会发生的真正问题,并会导致不必要的更新。

回答by Darren Hicks

First you need to determine if this is DDL or DML. If you don't know, then I recommend you set hibernate.show_sql=trueto capture the offending statement.

首先,您需要确定这是 DDL 还是 DML。如果您不知道,那么我建议您设置hibernate.show_sql=true来捕获违规语句。

If it is DDL, then it's most likely going to be Hibernate updating the schema for you and you'd want to additionally configure the hibernate.hbm2ddl.autosetting to be either "update" or "none", depending on whether you're using the actual db or the symlinked (read-only) one, respectivley. You can use "validate" instead of none, too.

如果它是 DDL,那么它很可能是 Hibernate 为您更新架构,并且您需要另外将hibernate.hbm2ddl.auto设置配置为“更新”或“”,具体取决于您是否分别使用实际的数据库或符号链接(只读)数据库。您也可以使用“ validate”而不是 none。

If it is DML, then I would first determine whether your code is for some reason making a change to an instance which is still attached to an active Hibernate Session. If so, then a subsequent read may cause a flush of these changes without ever explicitly saving the object (Grails?). If this is the case, consider evicting the instance causing the flush( or using transport objects instead ).

如果是 DML,那么我将首先确定您的代码是否出于某种原因对仍附加到活动 Hibernate 会话的实例进行了更改。如果是这样,那么后续读取可能会导致刷新这些更改,而无需明确保存对象(Grails?)。如果是这种情况,请考虑驱逐导致刷新的实例(或使用传输对象代替)。

Are you perhaps using any aspects or Hibernate lifecycle events to provide auditing of the objects? This, too, could cause access of a read-only to result in an insert or update being run.

您是否可能使用任何方面或 Hibernate 生命周期事件来提供对象审计?这也可能导致访问只读以导致运行插入或更新。

It may turn out that you need to provide alternative mappings for the offending class should the updatability of a field come into play, but the code is doing everything exactly as you'd like ( this is unlikely ;0 ). If you are in an all-annotation world, this may be tricky. If working with hbm.xml, then providing an alternative mapping is easier.

如果字段的可更新性发挥作用,您可能需要为违规类提供替代映射,但代码完全按照您的意愿执行所有操作(这不太可能;0)。如果您处于全注释世界中,这可能会很棘手。如果使用 hbm.xml,则提供替代映射会更容易。