web-dev-qa-db-ja.com

hibernate session.flush with spring @transactional

アプリケーションでSpringとHibernateを使用し、SpringTransactionを使用しています。

したがって、メソッドにアノテーション_@Transaction_が付いたサービスレイヤーと、データベースクエリ用のメソッドがあるDAOレイヤーがあります。

_@Transactional(readOnly = false)
public void get(){

}
_

問題は、オブジェクトをデータベースに保存したい場合、DAOレイヤーメソッドの最後でsession.flush()を使用する必要があることです。どうして?

_@Transaction_に注釈を付けた場合、Springはサービスメソッドの完了時にトランザクションを自動的にコミットするはずです。

DAOレイヤー:

_public BaseEntity saveEntity(BaseEntity entity) throws Exception {
        try {
            Session session = sessionFactory.getCurrentSession();
            session.saveOrUpdate(entity);
            session.flush();
        } catch (HibernateException he) {
            throw new Exception("Failed to save entity " + entity);
        }
        return entity;
    }
_

サービス層:

_    @Transactional(readOnly = false)
    public BaseEntity saveEntity(BaseEntity entity) throws Exception {
        return dao.saveEntity(entity);
    }
_

春の設定:

_<context:property-placeholder properties-ref="deployProperties" />

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

    <!-- Activate Spring Data JPA repository support -->
    <jpa:repositories base-package="com" />

    <!-- Declare a datasource that has pooling capabilities-->   
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close"
        p:driverClass="${app.jdbc.driverClassName}"
        p:jdbcUrl="${app.jdbc.url}"
        p:user="${app.jdbc.username}"
        p:password="${app.jdbc.password}"
        p:acquireIncrement="5"
        p:idleConnectionTestPeriod="60"
        p:maxPoolSize="100"
        p:maxStatements="50"
        p:minPoolSize="10" />

    <!-- Declare a JPA entityManagerFactory -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
        p:persistenceXmlLocation="classpath*:META-INF/persistence.xml"
        p:persistenceUnitName="hibernatePersistenceUnit"
        p:dataSource-ref="dataSource"
        p:jpaVendorAdapter-ref="hibernateVendor"/>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
        p:dataSource-ref="dataSource" p:configLocation="${hibernate.config}"
        p:packagesToScan="com" />

    <!-- Specify our ORM vendor -->
    <bean id="hibernateVendor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
                p:showSql="false"/>

    <!-- Declare a transaction manager-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
        p:entityManagerFactory-ref="entityManagerFactory"/>
_
11
Ankit Gupta

はい、@Transactional DAOメソッドの場合、セッションを手動でフラッシュする必要はありません。メソッドの操作が成功した場合、hibernateはトランザクションのコミットの一部としてセッションのフラッシュを処理します。

このリンクをチェックして、@ Transactionalがどのように機能するかを確認してください- Spring-@Transactional-バックグラウンドで何が起こりますか?

5
Chaitanya

デフォルトでは、Hibernateはクエリをスタックして、最終的にデータベースで実行されるときに最適化できるようにします。

フラッシュの穴は、このスタックをフラッシュして、トランザクションでデータベースに実行することです。 jvmの「保存」ハウスを離れ、大きな奇妙なデータベースでクエリを実行します。

これが、フラッシュなしで保存したものを選択できない理由です。それは単にまだデータベースにありません。

コミットの意味は、トランザクションが完了すると終了し、データベースの変更を他の人に見えるようにすることです。いったんコミットが実行されると、もう戻ることはできません。

率直に言って、それがベストプラクティスであるかどうかは正確にはわかりませんが、通常のCRUD操作では、daoレイヤーにフラッシュを追加できるはずです。このようにして、サービス層でそれについて心配する必要はありません。

Javaでトランザクションを最適化する場合は、サービスレイヤーに追加する必要があります。ただし、パフォーマンスの問題がない場合は解決する必要がないことに注意してください。フラッシュコード全体をサービス層に入れると、コードの可読性が低下します。シンプルで愚かなものにしてください;)

0
user3620653