css的hibernate学习日志--源码分析--get&save的过程
--get:
sessionImpl调用IdentifierLoadAccessImpl.load(id);在这个方法中,sessionFactoryImpl.getEntityPersister从entityPersisters map取entity的mapping信息,放到LoadEvent, 然后sessionImpl.fireLoad(event);
fireLoad从listeners列表找到onload的listener并调用其onload.
这个listener是DefaultLoadEventListener。参数event和loadType. get将调用load-->onLoad取entity。看onLoad的说明:
Coordinates the efforts to load a given entity. First, an attempt is made to load the entity from the session-level cache. If not found there, an attempt is made to locate it in second-level cache. Lastly, an attempt is made to load it directly from the datasource.
onLoad方法里有清晰的结构,loadFromXXX. 我们看loadFromDatasource,其调用了SingleTableEntitypersister.onLoad,这个方法在其父类里。它调用EntityLoader.load(在其父类里).
--stackTrace:
sessionImpl-->DefaultLoadEventListener-->persister-->EntityLoader
最接近DB的一层,从Loader.doQuery()开始。
注意其getSQLString()在子类中实现,这里是OuterJoinLoader。在prepareQueryStatement中将sql打印到log,在getResultSet中终于调到熟悉的st.executeQuery();
load的策略主要在listener里实现,与DB交互的细节在persister&loader中。
--后记:
persister有singletable, joined and union。loader有EntityLoader, QueryLoader,CriterialLoader等,queryLoader用ast(基于antlr)分析和生成sql。EntityLoader和CriterialLoader从JoinWalker取得sql.(参见AbstractEntityJoinWalker)
-------saveOrUpdate的过程:----------
类似get,可以分析saveOrUpdate的过程。sessionImpl fireSaveOrUpdate,调用一系列listeners, 这里是DefaultUpdateEventListener.但是基本没有实质性的操作。那,数据什么时候存到DB去的呢?
session.flush()的时候。flush也有相应的DefaultFlushEventListener。
flush()很关键,相反,saveOrUpdate甚至可以不要。如果session.get(User.class,2);即使不调用saveOrUpdate,user对像也会在flush的时候与DB同步。
这里要注意的一点,是transaction. autocommit属性默认为false(也不建议改为true), 则没有commit操作,数据不会存到DB。
--flush()的过程:
flush()主要有两个过程(对entity及connections):flush和perform。flush将有改变的操作放到session的actionQueue,perform一个个执行(通过上边提到过的persister)。