Java 休眠删除查询

Java 休眠删除查询,java,hibernate,Java,Hibernate,当我尝试从数据库中删除条目时,使用 session.delete(object) 然后我可以说: 1) 如果该行存在于数据库中,那么将执行两个SQL查询:一个select,然后是delete 2) 如果数据库中不存在该行,则只执行select查询 但同样,这不是更新的情况。不管是否存在DB行,只执行更新查询 请让我知道为什么删除操作会出现这种行为。这不是一个性能问题吗,因为两个查询被命中而不是一个查询 编辑: 我正在使用hibernate 3.2.5 示例代码: SessionFactory

当我尝试从数据库中删除条目时,使用

session.delete(object) 
然后我可以说:

1) 如果该行存在于数据库中,那么将执行两个SQL查询:一个select,然后是delete

2) 如果数据库中不存在该行,则只执行select查询

但同样,这不是更新的情况。不管是否存在DB行,只执行更新查询

请让我知道为什么删除操作会出现这种行为。这不是一个性能问题吗,因为两个查询被命中而不是一个查询

编辑:

我正在使用hibernate 3.2.5

示例代码:

SessionFactory sessionFactory = new Configuration().configure("student.cfg.xml").buildSessionFactory();
    Session session = sessionFactory.openSession();
    Student student = new Student();
    student.setFirstName("AAA");
    student.setLastName("BBB");
    student.setCity("CCC");
    student.setState("DDD");
    student.setCountry("EEE");
    student.setId("FFF");
    session.delete(student);
    session.flush();
            session.close();
cfg.xml

<property name="hibernate.connection.username">system</property>
    <property name="hibernate.connection.password">XXX</property>
    <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
    <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521/orcl</property>      
    <property name="hibernate.jdbc.batch_size">30</property>
    <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
    <property name="hibernate.cache.use_query_cache">false</property>
    <property name="hibernate.cache.use_second_level_cache">false</property>
    <property name="hibernate.connection.release_mode">after_transaction</property>
    <property name="hibernate.connection.autocommit">true</property>
    <property name="hibernate.connection.pool_size">0</property>
    <property name="hibernate.current_session_context_class">thread</property>    
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.hbm2ddl.auto">update</property>        
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.infy.model.Student" table="STUDENT">
    <id name="id" column="ID">
        <generator class="assigned"></generator>
    </id>
    <property name="firstName" type="string" column="FIRSTNAME"></property>
    <property name="lastName" type="string" column="LASTNAME"></property>
    <property name="city" type="string" column="CITY"></property>
    <property name="state" type="string" column="STATE"></property>
    <property name="country" type="string" column="COUNTRY"></property>        
</class>
系统
XXX
oracle.jdbc.OracleDriver
jdbc:oracle:thin:@localhost:1521/orcl
30
org.hibernate.dialen.oraclealent
假的
假的
事后交易
真的
0
线
真的
更新
hbm.xml

<property name="hibernate.connection.username">system</property>
    <property name="hibernate.connection.password">XXX</property>
    <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
    <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521/orcl</property>      
    <property name="hibernate.jdbc.batch_size">30</property>
    <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
    <property name="hibernate.cache.use_query_cache">false</property>
    <property name="hibernate.cache.use_second_level_cache">false</property>
    <property name="hibernate.connection.release_mode">after_transaction</property>
    <property name="hibernate.connection.autocommit">true</property>
    <property name="hibernate.connection.pool_size">0</property>
    <property name="hibernate.current_session_context_class">thread</property>    
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.hbm2ddl.auto">update</property>        
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.infy.model.Student" table="STUDENT">
    <id name="id" column="ID">
        <generator class="assigned"></generator>
    </id>
    <property name="firstName" type="string" column="FIRSTNAME"></property>
    <property name="lastName" type="string" column="LASTNAME"></property>
    <property name="city" type="string" column="CITY"></property>
    <property name="state" type="string" column="STATE"></property>
    <property name="country" type="string" column="COUNTRY"></property>        
</class>

我不确定,但是:

  • 如果使用非瞬态对象调用delete方法,这意味着首先从数据库获取对象。因此,看到select语句是正常的。也许最后你会看到2选择+1删除

  • 如果使用瞬态对象调用delete方法,则可能有一个
    cascade=“delete”
    或类似的方法需要首先检索对象,以便在需要时可以执行“嵌套操作”


编辑: 使用临时实例调用delete()意味着执行以下操作:

MyEntity entity = new MyEntity();
entity.setId(1234);
session.delete(entity);
这将删除id为1234的行,即使该对象是Hibernate未检索到的简单pojo、不存在于其会话缓存中、根本不由Hibernate管理


如果您有实体关联,Hibernate可能必须获取完整实体,以便它知道删除是否应级联到关联实体。

原因是要删除对象,Hibernate要求对象处于持久状态。因此,Hibernate首先获取对象(选择),然后删除它(删除)

为什么Hibernate需要首先获取对象?原因是Hibernate拦截器可能已启用(),并且对象必须通过这些拦截器才能完成其生命周期。如果直接在数据库中删除行,拦截器将不会运行

另一方面,可以使用批量操作在单个SQL delete语句中删除实体:

Query q = session.createQuery("delete Entity where id = X");
q.executeUpdate();

为了理解hibernate的这种特殊行为,理解一些hibernate概念很重要-

休眠对象状态

瞬态-如果对象已处于瞬态状态,则该对象处于瞬态状态 已实例化,但仍未与Hibernate会话关联

持久性-持久性实例在 数据库和标识符值。它可能已经被保存或删除了 但是,根据定义,它是在会话范围内加载的

分离-分离实例是已持久化的对象, 但会议已经结束

交易写在后面

接下来要理解的是“事务写在后面”。当修改附加到hibernate会话的对象时,它们不会立即传播到数据库。Hibernate这样做至少有两个不同的原因

  • 执行批量插入和更新
  • 仅传播最后的更改。如果一个对象被更新多次,它仍然只触发一条update语句

一级缓存

Hibernate有一个叫做“第一级缓存”的东西。每当您将对象传递给
save()
update()
saveOrUpdate()
,以及每当您使用
load()
get()
list()
iterate()
scroll()
检索对象时,该对象将添加到会话的内部缓存中。这是它跟踪对各种对象的更改的地方

休眠拦截器和对象生命周期侦听器-

从会话到应用程序的侦听器接口和侦听器回调允许应用程序在保存、更新、删除或加载持久对象之前检查和/或操作其属性。


本节已更新

级联

Hibernate允许应用程序定义关联之间的级联关系。例如,
'cascade-delete'
从父级到子级关联将导致在删除父级时删除所有子级

那么,为什么这些都很重要。

能够进行事务后置写入,能够跟踪对象(对象图)的多个更改为了能够执行生命周期回调,hibernate需要知道对象是否是临时/分离的,并且在对基础对象和关联关系进行任何更改之前,它需要将对象放在其一级缓存中

这就是为什么hibernate(有时)会发出一条
'SELECT'
语句,在对象进行更改之前将对象(如果尚未加载)加载到其一级缓存中

为什么hibernate有时只发出“SELECT”语句?

Hibernate发出一个
'SELECT'
语句来确定对象处于什么状态。如果select语句返回一个对象,则该对象处于
分离
状态,如果不返回对象,则该对象处于
瞬态
状态

进入您的场景-

Delete“Delete”发出SELECT语句,因为hibernate nee