简体   繁体   English

hibernate session.flush with spring @transactional

[英]hibernate session.flush with spring @transactional

I am using spring and hibernate in my application and using spring transaction. 我在我的应用程序中使用spring和hibernate并使用spring事务。

So i have service layer with annotation @transaction on methods and DAO layer having methods for database query. 所以我在方法和带有数据库查询方法的DAO层上有注释@transaction的服务层。

@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? 问题是当我想在数据库中保存一个对象时,我必须在DAO层方法结束时使用session.flush() 。为什么?

I think if i have annotated @transaction,then spring should automatic commit the transaction on completion of service method. 我想如果我有注释@ transaction,那么spring应该在完成服务方法时自动提交事务。

DAO layer : 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;
    }

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. 是的,如果你的DAO方法有@Transactional ,那么你不需要手动刷新会话,如果方法中的操作成功,hibernate将负责刷新会话作为提交事务的一部分。

Check this link to know on how @Transactional works - Spring - @Transactional - What happens in background? 查看此链接以了解@Transactional的工作原理 - Spring - @Transactional - 后台会发生什么?

By default, hibernate stacks its queries so they can be optimized when they are finally executed onto the database. 默认情况下,hibernate会堆叠其查询,以便在最终执行到数据库时对其进行优化。

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. 你离开jvm的“保存”房子并在一个大的奇怪的数据库上执行你的查询。

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. commit的含义是在事务结束后结束,并使数据库的更改对其他人可见。 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. 坦率地说,我不确定它是否是最佳实践,但对于正常的CRUD操作,您应该能够在您的dao层中添加flush。 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. 如果您希望java优化您的交易,那么您必须将其添加到您的服务层。 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 ;) 保持简单和愚蠢;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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