Hibernate2.1.6 Source Code Analysis Source: CSDN
Likebean
Article continuously updated each modification will be identified by color, and if there is any questions to identify the first annotation
1.sessionImpl.saveorupdate
Public void saveorupdate (Object obj) throws hibernateException {if (obj == null) throw new nullpointRexception ("Attempted to update null); // If the object is empty, throw an exception
IF (ReassociateifunInitializedProxy (obj)) Return;
Object Object = unproxyandreassociate (obj); // a proxy is always "update", Never "save"
EntityEntry E = GetEntry (Object); // Take Obj related ENTITYENTRY from the session, this object holds PO Current Status IF (E! = Null && E.STATUS! = Deleted) {// If in Obj in Session There is already corresponding ENTITYENTRY, that is, OBJ is already PO, and the status is not deleted, then do something not // do nothing for persistent instances log.trace ("SaveorUpdate () Persistent Instance");} else if (e! = NULL) {// ie. E.Status == deleted // If Obj has a corresponding ENTITYENTRY, that is, OBJ is already Po, and the status is deleted, then execute the delete operation log.trace ("saveorupdate () deleted Instance "); save (obj);} else {
// the object is transient Boolean isUnsaved = interceptor.isUnsaved (object); // interceptor is configurable, default Configratiron, return null ClassPersister persister = getPersister (object); // get the obj Persister Class mapping information if (isUnsaved == NULL) {// use unsaved-value
IF (Persister.isunsaved (Object)) / / Refer to AbstractTentityPersister.isunsaved, if the OBJ's IDentifier is empty, return True, otherwise, if the version of Version Property is empty, return true, otherwise return false {log.trace ("SaveorUpdate () unsaved instance "); save (obj);} else {// If the OBJ is still in the transient state, OBJ has a corresponding record in the database, then DoupDate Serializable ID = Persister.GetIdentifier (Object); if (log. iStraceNabled ()) log.trace ("SaveorUpdate () Previously Saved Instance With ID:" ID); DOUPDATE (Object, ID, Persister);}} else {if (isunsaved.BooleanValue ()) {log.trace (" SaveorUpdate () unsaved instance "); Save (OBJ);" SaveorUpdate () previously saved instance "); doupdate (Object, persister.getiDentifier (Object), persister);}}
2.Session Impl.save
Public serializable save (object obj) throws hibernateException {
IF (obj == null) throw new nullpointersRext ("Attempted to Save Null);
Object object = unproxy (obj); // throws exception if uninitialize
ENTITYENTRY E = GetEntry (Object); if (e! = Null) // If there is a PO {if (E.STATUS == DELETED) {// if the PO status is deleted, Flush ForceFlush (e);} else {log.trace ("Object Already Associated with session); // Returns the ID of the PO, nothing to return Return E.ID;}}
Serializable id = saveWithGeneratedIdentifier (object, Cascades.ACTION_SAVE_UPDATE, null); // id might be generated by SQL insert reassociateProxy (obj, id); // TODO:? Move into saveWithGeneratedIdentifier () return id;
}
3.Session Impl.savewithGeneratedIdIndifier
private Serializable saveWithGeneratedIdentifier (Object object, Cascades.CascadingAction action, Object anything) throws HibernateException {ClassPersister persister = getPersister (object); try {Serializable id = persister.getIdentifierGenerator () .generate (this, object); // generated identity of obj If the id is assigned, then directly returns Obj's Identity. If it is Native, depending on the characteristics of the underlying database, idiF (ID == null) {throw new IdentifierGenerationException ("null id generated for:" Object.getClass ()) ;} else if (id == IdentifierGeneratorFactory.SHORT_CIRCUIT_INDICATOR) {return getIdentifier (object);! // yick} else if (id == IdentifierGeneratorFactory.IDENTITY_COLUMN_INDICATOR) {return doSave (object, null, persister, true, action, anything) } Else {if (log.isDebugeload ()) log.debug ("generated identifier: id); Return DOSAVE (Object, ID, Persister, False, Action, Anything);}} catch (sqlexception sqle) {throw NEW JDBCEXCEPTION ("Could Not Save Object", SQLE);}} 4.Session Impl.dosave
// Hibernate When executing Insert, INSERT SQL generally does not immediately perform Id, unless you use the IdEntity mechanism to generate ID, otherwise INSERT SQL will only execute when it is postponed to session.flush, will first generate the ID that needs to return (Using the mechanism such as Sequence IT, as long as the Identity mechanism is not the Identity mechanism, then put the Insert SQL plans in the inserts this queue, wait for INSERT SQL when Flush, but you need to pay attention to the INDENTITY mechanism generates ID Obj When you are inserting OBJ, Hibernate will execute all Insert SQL in the Insertions queue, why need to do this, unknown.
private Serializable doSave (final Object object, Key key, final ClassPersister persister, final boolean replicate, final boolean useIdentityColumn, final Cascades.CascadingAction cascadeAction, final Object anything) throws HibernateException {
IF (Validatable) ()) .validate (); // Verify OBJ's legitimacy serializable id; if (useidentityColumn) {// If it is the ID generated by the Identity mechanism, then session insert queue Existing Insert SQL is all executed, what is necessary? ID = null; executeinserts ();} else {id = key.getiDentifier ();}
// put a placeholder in Entries, So We don't recurse back and try to save () The // Same Object Again. Questions: SHOULD THIS BE DONE BEFORE ONSAVE () IS CALLED? // LIKEWISE, SHOULD IT BE DONE BEFORE ONUPDATE ()? Addentry (Object, Saving, Null, ID, NULL, LOCKMODE.WRITE, User, false); // okay if id is null here
// cascade-save to body is saved // before processing the son (from table data), first processes the father (primary table data) first Cascading ; try {cascades.cascade (this, Persister, Object, cascadeaction, cascades.cascade_before_insert_after_delete, anything;} finally {cascading--;}
Object [] value = personister.getPropertyValues (object); type [] types = persister.getpropertytypes ();
Boolean substitude = false; if (! replicate) {
Substitution = interceptor.onsave (Object, ID, VALUES, PERSISTER.GETPROPERTYNAMES (), TYPES);
// keep the existing version number in the case of replicate if (persister.isVersioned ()) {substitute = Versioning.seedVersion (values, persister.getVersionProperty (), persister.getVersionType ()) || substitute;}!}
if (persister.hasCollections ()) {// TODO: make OnReplicateVisitor extend WrapVisitor if (replicate) {OnReplicateVisitor visitor = new OnReplicateVisitor (this, id); visitor.processValues (values, types);} WrapVisitor visitor = new WrapVisitor (this ); // substitutes into values by side-effect visitor.processValues (values, types); substitute = substitute || visitor.isSubstitutionRequired ();} if (substitute) persister.setPropertyValues (object, values);
TypeFactory.deepCopy (values, types, persister.getPropertyUpdateability (), values); nullifyTransientReferences (values, types, useIdentityColumn, object); checkNullability (values, persister, false);
If (UseIdentityColumn) {// If it is an ID generated by the Identity mechanism, then it will not wait until Flush, it will be inserted into the data, because the ID is to return, this ID generated by the Identity mechanism can only be generated. ScheduledIdentityInsertion insert = new ScheduledIdentityInsertion (values, object, persister, this); insert.execute (); executions.add (insert); id = insert.getGeneratedId (); persister.setIdentifier (object, id); key = new Key ( ID, persister; Checkuniqueness (key, object);
Object version = Versioning.getVersion (values, persister); addEntity (key, object); addEntry (object, LOADED, values, id, version, LockMode.WRITE, useIdentityColumn, persister, replicate); nonExists.remove (key);
IF (! users) {INSERTIONS.ADD (New ScheduledInsertion (ID, Values, Object, Persister, This);
// cascade-save to collections AFTER the collection owner was saved // father has been processed, the process where the son cascading ; try {Cascades.cascade (this, persister, object, cascadeAction, Cascades.CASCADE_AFTER_INSERT_BEFORE_DELETE, anything);} finally {cascading -;
Return ID;
}
5. SessionImpl.doUpdateMutable private void doUpdateMutable (Object object, Serializable id, ClassPersister persister) throws HibernateException {if (log.isTraceEnabled ()) log.trace ( "updating" MessageHelper.infoString (persister, id));
Key Key = New key (id, person); checkuniqueason (key, object); // Check if the Object has the same one of the corresponding ID in Session, if there is, throw an exception
IF ("" ",") {log.debug ("Calling OnUpdate ()"); if ((Lifecycle) Object) .onupdate (this)) {// do callback log.debug ("Update Vetoed by Onupdate ) ")"); Reassociate (Object, ID, Persister); Return;}}
// this is a transient Object with existing personistent state not loading by the session
New onupdatevisitor (this, id) .process (Object, Persister);
Addentity (Key, Object); // Incorporate Obj into session management, Transient Obj becomes PO Addentry (Object, Loaded, Null, ID, PERSISTER.GETVERSION (Object), LockMode.none, True, Persister, False ;