问题是下面的代码片段没有删除数据库中的记录。
import org.hibernate.Session;
import org.hibernate.SessionFactory;
...
...
void deleteForm() {
Session session = sessionFactory.openSession();
FormDO formDO = new FormDO();
formDO.setId(formId);
session.delete(formDO); // No delete SQL query is getting fired.
但是,如果我在删除后调用 session.flush(),它会完美运行。请注意,我没有使用任何交易。
在Session类的JavaDoc中对delete方法的描述是:
Remove a persistent instance from the datastore. The argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with existing persistent state.
而且我在网上看到很多代码片段表明在delete()之后没有必要调用flush()。其他论坛也有类似问题here但仍未得到答复。
此外,session.save 在没有 session.flush 的情况下也能正常工作。
我正在使用 Hibernate 4.2.16 + Spring 4.0.9 + JPA 1.0 注释。以下是供进一步引用的源文件,
FormDO.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="form")
public class FormDO {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
Integer id;
@Column(name="name")
String name;
...
...
Spring 配置文件
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/tempdb" />
<property name="username" value="root" />
<property name="password" value="****" />
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.test.FormDO</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
FormDAO.java
@Named
public class FormDAO {
@Inject
private SessionFactory sessionFactory;
public boolean deleteForm(Integer formId) {
Session session = sessionFactory.openSession();
FormDO formDO = new FormDO();
formDO.setId(formId);
session.delete(formDO);
session.flush(); // If this line is commented, record DOES NOT get deleted
return true;
}
public boolean saveForm(FormDO formDO) {
Session session = sessionFactory.openSession();
session.save(formDO); // Save doesn't require session.flush
return true;
}
...
...
更新:
我的困境主要是由于不一致。session.save 立即插入记录,但 session.delete 不会反射(reflect),除非显式调用 flush()。但是当我引用 Flushing the Session Afsun 发布的链接,通过阅读以下行消除了我的疑虑,
An exception is that objects using native ID generation are inserted when they are saved.
我非常感谢每个人发布的答案,因为几乎所有答案都指向了正确的方向,但 Afsun 完全消除了我的疑虑。谢谢!
最佳答案
当您通过 Hibernate 使用数据库时,您正在使用 Hibernate session
。 Hibernate session
通过以下三种情况刷新到数据库。
commit()
- 当您提交事务时- 在运行查询之前
- 当您调用
session.flush()
这里最重要的是第二个。每次查询后,Hibernate session
都不会刷新数据库。如果我们通过 Hibernate 运行 Native SQL Query
,Hibernate 不知道刷新 session ,或者如果运行 HQL
,Hibernate 也不知道刷新 session 。调用 flush 将使 session 状态与数据库同步。
请参阅以下内容:
Hibernate flush before delete和 Flushing the Session
关于java - 为什么在 Hibernate 中需要在 session.delete() 之后调用 session.flush()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30215081/