简体   繁体   中英

hibernate session.flush with spring @transactional

I am using spring and hibernate in my application and using spring transaction.

So i have 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 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 automatic commit the transaction on completion of 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"/>

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM