7、Delete
1) 返回值
void
2)事件监听处理类及重要代码
DefaultDeleteEventListener
public
void
onDelete(DeleteEvent event, Set transientEntities)
throws
HibernateException {
EntityEntry entityEntry = persistenceContext.getEntry( entity );
if
( entityEntry ==
null
) {
persister = source .getEntityPersister( event.getEntityName(), entity );
if
( ForeignKeys.isTransient( persister.getEntityName(), entity,
null
, source ) ) {
deleteTransientEntity( source, entity , event.isCascadeDeleteEnabled(), persister, transientEntities );
// EARLY EXIT!!!
return
;
}
performDetachedEntityDeletionCheck( event );
entityEntry = persistenceContext.addEntity(
entity,
( persister.isMutable() ? Status.MANAGED : Status.READ_ONLY),
persister.getPropertyValues( entity ),
key,
version,
LockMode.NONE,
true
,
persister,
false
,
false
);
}
else
{
if
( entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE ) {
return
;
}
persister = entityEntry.getPersister();
id = entityEntry.getId();
version = entityEntry.getVersion();
}
deleteEntity(
source,
entity,
entityEntry,
event.isCascadeDeleteEnabled(),
event.isOrphanRemovalBeforeUpdates(),
persister,
transientEntities
);
}
3)事务范围外的处理方式
如果在事务范围外,delete不会得到执行;delete操作,只是把EntityDeleteAction加入到ActionQueue中的deletions队列中,detetions实际上是一个ArrayList;直到flush时才会执行。
当然当实体是持久态/游离态时,才会将
EntityDeleteAction加入到ActionQueue队列中。
4)瞬时态
可以删除一个瞬时态的实体,处理过程是将瞬时对象加入瞬时对象列表中,然后执行相关级联操作。处理程序不会对瞬时对象在StatefulPersistenceContext中做任何处理。完成删除操作时,
实体状态仍旧
是瞬时态。
5)
游离态
如果在
StatefulPersistenceContext找不到实体对应的EntityEntry,且实体的关键列值为null或与unsaved-value相等,则认为该实体为游离态,则作为游离态对象进行处理。
创建对象EntityEntry加入StatefulPersistenceContext中,并将
EntityDeleteAction加入到ActionQueue队列中。将实体状态标识为DELETED状态。直到commit前,实体一直是DELETED状态,
事务提交后,将会变成DETACHED
(游离)
状态。
6)
持久态
如果在
StatefulPersistenceContext找得到实体对应的EntityEntry,且实体的状态不为DELETED或GONE状态,则认为是持久态,进行持久态对象处理过程。
将
EntityDeleteAction加入到ActionQueue队列中。将实体状态标识为DELETED状态。直到commit前,实体一直是DELETED状态,
事务提交后,将会变成DETACHED
(游离)
状态。
7)总结
8、Flush
1) 返回值
void
2)事件监听处理类及重要代码
DefaultFlushEventListener
public
void
onFlush(FlushEvent event)
throws
HibernateException {
final
EventSource source = event.getSession();
final
PersistenceContext persistenceContext = source.getPersistenceContext();
if
( persistenceContext.getNumberOfManagedEntities() > 0 ||
persistenceContext.getCollectionEntries().size() > 0 ) {
try
{
source.getEventListenerManager().flushStart();
flushEverythingToExecutions( event ); // 将entities和collections的相应动作加入ActionQueue中
performExecutions( source ); // 然后执行ActionQueue所有的Actions
postFlush( source );
}
finally
{
source.getEventListenerManager().flushEnd(
event.getNumberOfEntitiesProcessed(),
event.getNumberOfCollectionsProcessed()
);
}
postPostFlush( source );
if
( source.getFactory().getStatistics().isStatisticsEnabled() ) {
source.getFactory().getStatisticsImplementor().flush();
}
}
}
ActionQueue
private
<E
extends
Executable & Comparable<?> & Serializable>
void
executeActions(ExecutableList<E> list)
throws
HibernateException {
// todo : consider ways to improve the double iteration of Executables here:
// 1) we explicitly iterate list here to perform Executable#execute()
// 2) ExecutableList#getQuerySpaces also iterates the Executables to collect query spaces.
try
{
for
( E e : list ) {
try
{
e.execute();
}
finally
{
beforeTransactionProcesses.register( e.getBeforeTransactionCompletionProcess() );
afterTransactionProcesses.register( e.getAfterTransactionCompletionProcess() );
}
}
}
finally
{
if
( session.getFactory().getSettings().isQueryCacheEnabled() ) {
// Strictly speaking, only a subset of the list may have been processed if a RuntimeException occurs.
// We still invalidate all spaces. I don't see this as a big deal - after all, RuntimeExceptions are
// unexpected.
Set<Serializable> propertySpaces = list.getQuerySpaces();
invalidateSpaces( propertySpaces.toArray(
new
Serializable[propertySpaces.size()] ) );
}
}
list.clear();
session.getTransactionCoordinator().getJdbcCoordinator().executeBatch();
}
3)事务范围外的处理方式
3.1) 设置connection为自动提交
假如,没有显式地创建一个事务并开启,然后对一个游离态对象进行delete操作,即该操作不在事务范围内,如果不执行flush操作,delete动作不会得到执行; 如果执行flush操作,
由于事务为自动提交,delete操作的delete sql将执行并提交至数据库。没有显式事务同样可以提交
数据
更新
,不只是save,还有delete、update、persist、merge操作。
3.2)设置connection为非自动提交
假如,
没有显式地创建一个事务并开启,然后对一个游离态对象进行delete操作,即该操作不在事务范围内,如果不执行flush操作,delete动作不会得到执行; 如果执行flush操作,
由于事务为手动提交,delete操作的delete sql将执行但事务得不到提交。
3.3)flush的作用
除了DefaultSaveOrUpdateEventListener中个别的情况外,其他的操作如update、persist、merge、delete等,只是将相应的Action加入到ActionQueue各自的队列中,并不会立即执行
相应的
数据库操作。这里说的
DefaultSaveOrUpdateEventListener中个别情况是指,save 操作在有些情况下不是将Action加入到ActionQueue中,而是直接执行Insert sql 操作并更新至
数
据库中。所以,一般情况下,只有等到flush时,
Actions
才会得到执行。flush的作用就是执行ActionQueue中的各种Action。
3.4)flush与commit的区别
3.4.1)commit包含flush操作,但处理的东西比flush多;commit还要执行关闭当前事务,开启新事务的工作。一旦当前事务提交,该事务就结束了,就不可再用了。
3.4.2)flush操作只是执行ActionQueue中的Action,执行完Action之后,将对ActionQueue进行清空避免同一操作多次被执行。
3.4.3)flush操作在显式地事务范围内时,可以执行多次,对事务本身没有影响,当前事务不会关闭,还处于活跃中;只是执行并清空的ActionQueue队列中的Action。
3.4.4)就算没有显式的事务,flush操作同样可以更新数据库,只要Connection.
setAutoCommit
(true);
3.4.5)没有Transaction,就没有commit方法;但没有Transaction,可以执行flush方法。
4)瞬时态
无
5)持久态
无
6)游离态
无