我有一个表和两个具有相同表的数据库,但是一个是另一个的符号链接,只允许在此表上读取。
我已使用Hibernate将表映射到Java,并使用spring将Entity Manager的数据源设置为基于某些输入条件的两个数据库之一。
当我连接到第二个数据库时,我只调用只读操作(选择),但似乎Hibernate尝试将某些内容刷回数据库,并且无法在此视图上告知更新。
如何仅针对第二个数据源禁用此更新并保持第一个数据源正常?
更新: 看看堆栈跟踪,冲洗似乎从这里开始:
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$1.beforeCompletion(AbstractEntityManagerImpl.java:504) ... 55 more
这与hibernate.transaction.flush_before_completion属性有关吗?我可以为第二个数据源将其设置为false吗?
答案 0 :(得分:7)
很可能你的实体在从数据库加载的同时变得“脏”,而Hibernate认为它需要存储更改。如果您的访问者(get和set方法)没有返回由Hibernate设置的完全相同的值或引用,则会发生这种情况。
在我们的代码中,这发生在列表中,开发人员创建了新的列表实例,因为他们不喜欢他们在setter中获得的类型。
如果您不想更改代码,请将映射更改为字段访问。
您还可以通过在会话中将FlushMode设置为never来阻止Hibernate存储更改,但这只会隐藏在其他情况下仍会出现的实际问题,这将导致不必要的更新。
答案 1 :(得分:1)
首先,您需要确定这是DDL还是DML。如果你不知道,那么我建议你设置 hibernate.show_sql = true 来捕获有问题的陈述。
如果是DDL,那么很可能Hibernate会为您更新架构,并且您还需要另外配置 hibernate.hbm2ddl.auto 设置要么是“更新”,要么“无”,具体取决于您使用的是实际数据库还是符号链接(只读)数据库。您也可以使用“验证”代替“
”。如果它是DML,那么我首先要确定您的代码是否由于某种原因对仍然附加到活动Hibernate会话的实例进行了更改。如果是这样,那么后续的读取可能会导致这些更改的刷新而没有明确地保存对象(Grails?)。如果是这种情况, 会考虑逐出导致刷新 的实例(或者使用传输对象)。
您是否可以使用任何方面或Hibernate生命周期事件来提供对象的审核?这也可能导致访问只读,导致插入或更新正在运行。
如果字段的可更新性发挥作用,您可能需要为违规类提供替代映射,但代码正在按照您的意愿完成所有操作(这不太可能; 0)。如果你处于一个全注释世界,这可能会很棘手。如果使用hbm.xml,那么提供替代映射会更容易。