web-dev-qa-db-ja.com

Java / Hibernate-読み取り専用モードでは書き込み操作は許可されていません

私は最近多くの迷惑な例外を抱えています、そしてGoogleとこのフォーラムでのいくつかの調査の後、私はまだ私の問題を解決することができる答えを見つけていません。

これが問題です-休止状態で新しいオブジェクトを更新または作成しようとすると、次のエラーが発生することがあります。

_org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.Java:1186)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.Java:696)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.Java:419)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.Java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.Java:694)
_

本当に奇妙なのは、メソッドgetHibernateTemplate().saveOrUpdate(object);でオブジェクトを更新するときに機能することもありますが、同じオブジェクトで同じメソッドを呼び出すことによって機能しないこともありますが、最初にオブジェクトを取得する方法。

例:id、type、lengthの3つのフィールドを持つテーブルがあるとします。起こり得ることは、IDでオブジェクトを取得して長さを更新すると、それが機能することです。タイプ別に取得して長さを更新すると、機能しません。したがって、問題を回避するためにこれまで私が行ってきたのは、後で問題を引き起こさないメソッドをオブジェクトをフェッチすることですが、これが機能する方法を探して見つけるのがますます面倒になっています。

また、オブジェクト(すべてではなく、1つの特定のテーブルのみ)を作成しようとしたときにこの例外が発生し、回避策を見つけることができません。そして、トランザクションに@Transactional(readOnly = false)を追加しようとしましたが、何も変更されず、モードを表示すると、とにかく読み取り専用ではなかったことが示されました。

助言がありますか?

7月26日を編集:休止状態に関連するいくつかの構成を次に示します

_<property name="hibernateProperties">
    <props>
        <prop key="jdbc.fetch_size">20</prop>
        <prop key="jdbc.batch_size">25</prop>
        <prop key="cglib.use_reflection_optimizer">true</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="connection.autoReconnect">true</prop>
        <prop key="connection.autoReconnectForPools">true</prop>
        <prop key="connection.is-connection-validation-required">true</prop>
    </props>
</property>
_

また、それが役立つ場合

_<property name="transactionAttributes">
    <props>
        <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="execute*">PROPAGATION_REQUIRED</prop>
        <prop key="add*">PROPAGATION_REQUIRED</prop>
        <prop key="create*">PROPAGATION_REQUIRED</prop>
        <prop key="update*">PROPAGATION_REQUIRED</prop>
        <prop key="delete*">PROPAGATION_REQUIRED</prop>
    </props>
</property>
_

8月31日を編集:オブジェクトを保存するためにHibernateDaoSupportを拡張する私のクラスの関連コードは次のとおりです。

_public void createObject(Object persisObj) {
    getHibernateTemplate().save(persisObj);
}
_
15
Guillaume

ビューフィルターからシングルセッションプロパティを変更しました。問題が解決しました:

  <filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    <init-param>
      <param-name>singleSession</param-name>
      <param-value>false</param-value>
    </init-param>
  </filter>
6
Fırat KÜÇÜK

このエラーメッセージは通常、Spring OpenSessionInViewFilter を使用していて、Springが管理するトランザクションの外部で永続化操作を実行しようとしたときに表示されます。フィルターはセッションをFlushMode.NEVER/MANUALに設定します(使用しているSpringとHibernateのバージョンに応じて、これらはほぼ同等です)。 Springトランザクションメカニズムがトランザクションを開始すると、フラッシュモードが「COMMIT」に変更されます。トランザクションが完了すると、必要に応じてトランザクションをNEVER/MANUALに戻します。これが発生していないことを確信している場合、次に考えられる原因は、セッションのスレッドセーフでない使用です。 Hibernateセッションは1つのスレッドでのみ使用する必要があります。スレッド間で交差すると、あらゆる種類の混乱が発生する可能性があります。 Hibernateからロードされたエンティティは、ロードされたセッションへの参照を保持できるため、エンティティをスレッド間で渡すと、別のスレッドからもセッションにアクセスできることに注意してください。

11
Ryan Stewart

追加

@Transactional

あなたの機能の上

7
Ahmad R. Nazemi

私もこれに遭遇しました。 SpringのOpenSessionInViewFilterのフラッシュモードを手動に変更する必要があり、突然この例外が発生し始めました。 @Transactionalとして注釈が付けられていないメソッドで問題が発生していることがわかったので、Springはそのようなメソッドの外部にあるすべてのデータアクセスコードを暗黙的に読み取り専用として扱うと思います。メソッドに注釈を付けることで問題は解決しました。

別の方法は、HibernateTemplateオブジェクトの setCheckWriteOperations メソッドを呼び出すことです。

6
alh84001

アプリケーションコンテキストHibernateTemplateには以下のBeanを使用します。

<bean id="template" class="org.springframework.orm.hibernate4.HibernateTemplate">  
        <property name="sessionFactory" ref="mysessionFactory"></property>
        <property name="checkWriteOperations" value="false"></property>
        </bean>
5
Amit Sharma

これを使ってみてください

hibernateTemplate = new HibernateTemplate(sessionFactory);
hibernateTemplate.setCheckWriteOperations(false);

テンプレートはトランザクションを使用しているかどうかをチェックしていないため、エラーは解消されます。

3
bigrowedogg

@TransactionalアノテーションをDAOサービスクラス/メソッドに追加するのを忘れている必要があります。これは、データベース操作がSpring管理トランザクションによって処理されることを指定します。

2
wise king

1)データベース操作メソッドの上に@Transactionalを追加し、2)アノテーション駆動型トランザクションマネージャがあることを確認します

追加

上記のapplicationContext.xmlファイルのHibernateTransactionManager構成

1
user3345582

以下のコードは私のために働いています。

hibernateTemplate = new HibernateTemplate(sessionFactory);
hibernateTemplate.setCheckWriteOperations(false);
1
user3198259

私は同じ問題を抱えており、1日の調査の後、次の宣言を観察しました

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>

私は削除しました

mode="aspectj"

そして問題は消えた

0
Mihai