java - 为什么在 Hibernate 中需要在 session.delete() 之后调用 session.flush()?

标签 java spring hibernate

问题是下面的代码片段没有删除数据库中的记录。

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通过以下三种情况刷新到数据库。

  1. commit()- 当您提交事务时
  2. 在运行查询之前
  3. 当您调用 session.flush()

这里最重要的是第二个。每次查询后,Hibernate session 都不会刷新数据库。如果我们通过 Hibernate 运行 Native SQL Query,Hibernate 不知道刷新 session ,或者如果运行 HQL,Hibernate 也不知道刷新 session 。调用 flush 将使 session 状态与数据库同步。

请参阅以下内容: Hibernate flush before deleteFlushing the Session

关于java - 为什么在 Hibernate 中需要在 session.delete() 之后调用 session.flush()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30215081/

相关文章:

java - 使用 ImprovedNamingStrategy 创建表时出错

java - 无法在表之间建立连接 只能进行读取操作,但不能进行插入操作

java - 如何检测 MotionEvent.ACTION_MOVE 何时完成

java - 将 jvm 参数传递给 Gradle 测试任务

design-patterns - 在不使用Singleton的情况下从非bean对象获取Spring Application上下文

java - 接收消息调用存储过程时找不到对应参数

java - 如何在 HQL 中使用 "order by case when ..."?

java - 从 Java 到 C# - 泛型转换为 BaseClass

java - 字符串归并排序实现

spring - 将 spring boot 从 2.1.9 升级到 2.2.0 ,现在启动时出现异常