Java 使用 spring @transactional 休眠 session.flush
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26121297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
hibernate session.flush with spring @transactional
提问by Ankit Gupta
I am using Spring and Hibernate in my application and using Spring Transaction.
我在我的应用程序中使用 Spring 和 Hibernate,并使用 Spring Transaction。
So I have a service layer with annotation @Transaction
on methods and DAO layer having methods for database query.
所以我有一个带有@Transaction
方法注释的服务层和带有数据库查询方法的 DAO 层。
@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?
问题是当我想在数据库中保存一个对象时,我必须session.flush()
在 DAO 层的末尾使用方法。为什么?
I think if I have annotated @Transaction
, then Spring should automatically commit the transaction on completion of the 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"/>
回答by Chaitanya
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.
是的,如果你有@Transactional
你的 DAO 方法,那么你不需要手动刷新会话,如果方法中的操作成功,hibernate 将负责刷新会话作为提交事务的一部分。
Check this link to know on how @Transactional works - Spring - @Transactional - What happens in background?
检查此链接以了解 @Transactional 的工作原理 - Spring - @Transactional - 后台会发生什么?
回答by user3620653
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. 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.
坦率地说,我不确定这是否是最佳实践,但对于正常的 CRUD 操作,您应该能够将刷新添加到您的 dao 层中。这样你就不用担心它进入服务层了。
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 ;)
如果您希望 java 优化您的事务,那么您必须将其添加到您的服务层中。但是请记住,当没有性能问题时,您不需要解决任何问题!将所有代码都刷新到服务层不利于代码可读性。保持简单和愚蠢;)