hibernate session.flush with spring @transactional

北战南征 提交于 2020-01-12 14:04:36

问题


I am using Spring and Hibernate in my application and using Spring Transaction.

So I have a service layer with annotation @Transaction on methods and DAO layer having methods for database query.

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

}

The issue is when I want to save an object in the database,then I have to use session.flush() at the end of DAO layer method. Why?

I think if I have annotated @Transaction, then Spring should automatically commit the transaction on completion of the service method.

DAO layer :

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;
    }

Service layer :

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

spring config :

<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"/>

回答1:


Yes, if you have @Transactional for your DAO method then you need not flush the session manually, hibernate will take care of flushing the session as part of committing the transaction if the operations in the method are successful.

Check this link to know on how @Transactional works - Spring - @Transactional - What happens in background?




回答2:


By default, hibernate stacks its queries so they can be optimized when they are finally executed onto the database.

The hole point of flush is to flush this stack and execute it in your transaction onto the database. Your leaving the "save" house of the jvm and execute your query on a big strange database.

This is why you can't select something you've just saved without a flush. It's simply not in the database yet.

The meaning of commit is ending once transaction and make changes of the database visible for others. Once commit has been executed there's no return possible anymore.

Frankly I'm not exactly sure if it is a best practice but for normal CRUD operations you should be able to add flush into your dao layer. This way you don't need to worry about it into the service layer.

If you want java to optimize your transaction then you'll have to add it into your service layer. But remember that you don't need to solve performance issues when there aren't any! Flushes all over your code into the service layer is not good for the code readability. Keep it simple and stupid ;)



来源:https://stackoverflow.com/questions/26121297/hibernate-session-flush-with-spring-transactional

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!