📄 sessionimpl.java
字号:
Object version = Versioning.getVersion(values, persister); EntityEntry newEntry = addEntry(object, LOADED, values, id, version, LockMode.NONE, true, persister, false); new OnLockVisitor(this, id).process(object, persister); return newEntry; } public void lock(Object object, LockMode lockMode) throws HibernateException { if (object==null) throw new NullPointerException("attempted to lock null"); if (lockMode==LockMode.WRITE) throw new HibernateException("Invalid lock mode for lock()"); object = unproxyAndReassociate(object); //TODO: if object was an uninitialized proxy, this is inefficient, // resulting in two SQL selects EntityEntry entry = getEntry(object); if (entry==null) { final ClassPersister persister = getPersister(object); final Serializable id = persister.getIdentifier(object); if ( !isSaved(object) ) throw new HibernateException("cannot lock an unsaved transient instance: " + MessageHelper.infoString(persister) ); entry = reassociate(object, id, persister); cascading++; try { Cascades.cascade(this, persister, object, Cascades.ACTION_LOCK, Cascades.CASCADE_ON_LOCK, lockMode); } finally { cascading--; } } upgradeLock(object, entry, lockMode); } private void upgradeLock(Object object, EntityEntry entry, LockMode lockMode) throws HibernateException { if ( lockMode.greaterThan(entry.lockMode) ) { if (entry.status!=LOADED) { throw new ObjectDeletedException( "attempted to lock a deleted instance", entry.id, object.getClass() ); } final ClassPersister persister = entry.persister; if ( log.isTraceEnabled() ) log.trace( "locking " + MessageHelper.infoString(persister, entry.id) + " in mode: " + lockMode ); SoftLock lock=null; if ( persister.hasCache() ) lock = persister.getCache().lock(entry.id); try { persister.lock(entry.id, entry.version, object, lockMode, this); entry.lockMode = lockMode; } finally { // the database now holds a lock + the object is flushed from the cache, // so release the soft lock if ( persister.hasCache() ) persister.getCache().release(entry.id, lock); } } } public Query createFilter(Object collection, String queryString) { return new FilterImpl(queryString, collection, this); } public Query createQuery(String queryString) { return new QueryImpl(queryString, this); } public Query getNamedQuery(String queryName) throws MappingException { String queryString = factory.getNamedQuery(queryName); if(queryString!=null) { return createQuery(queryString); } SessionFactoryImpl.InternalNamedSQLQuery nq = factory.getNamedSQLQuery(queryName); if (nq!=null) { return createSQLQuery( nq.getQueryString(), nq.getReturnAliases(), nq.getReturnClasses() ); } throw new MappingException("Named query not known: " + queryName); } public Object instantiate(Class clazz, Serializable id) throws HibernateException { return instantiate( factory.getPersister(clazz), id ); } /** * give the interceptor an opportunity to override the default instantiation */ public Object instantiate(ClassPersister persister, Serializable id) throws HibernateException { Object result = interceptor.instantiate( persister.getMappedClass(), id ); if (result==null) result = persister.instantiate(id); return result; } public void setFlushMode(FlushMode flushMode) { this.flushMode = flushMode; } public FlushMode getFlushMode() { return flushMode; } /** * detect in-memory changes, determine if the changes are to tables * named in the query and, if so, complete execution the flush */ private boolean autoFlushIfRequired(Set querySpaces) throws HibernateException { if ( flushMode==FlushMode.AUTO && dontFlushFromFind==0 ) { int oldSize = collectionRemovals.size(); flushEverything(); if ( areTablesToBeUpdated(querySpaces) ) { log.trace("Need to execute flush"); execute(); postFlush(); // note: execute() clears all collectionXxxxtion collections return true; } else { log.trace("Dont need to execute flush"); // sort of don't like this: we re-use the same collections each flush // even though their state is not kept between flushes. However, its // nice for performance since the collection sizes will be "nearly" // what we need them to be next time. collectionCreations.clear(); collectionUpdates.clear(); updates.clear(); // collection deletions are a special case since update() can add // deletions of collections not loaded by the session. for ( int i=collectionRemovals.size()-1; i>=oldSize; i-- ) { collectionRemovals.remove(i); } } } return false; } /** * If the existing proxy is insufficiently "narrow" (derived), instantiate a new proxy * and overwrite the registration of the old one. This breaks == and occurs only for * "class" proxies rather than "interface" proxies. */ public Object narrowProxy(Object proxy, ClassPersister persister, Key key, Object object) throws HibernateException { if ( !persister.getConcreteProxyClass().isAssignableFrom( proxy.getClass() ) ) { if ( log.isWarnEnabled() ) log.warn( "Narrowing proxy to " + persister.getConcreteProxyClass() + " - this operation breaks ==" ); if (object!=null) { proxiesByKey.remove(key); return object; //return the proxied object } else { proxy = persister.createProxy( key.getIdentifier(), this ); proxiesByKey.put(key, proxy); //overwrite old proxy return proxy; } } else { return proxy; } } /** * Grab the existing proxy for an instance, if * one exists. (otherwise return the instance) */ public Object proxyFor(ClassPersister persister, Key key, Object impl) throws HibernateException { if ( !persister.hasProxy() ) return impl; Object proxy = proxiesByKey.get(key); if (proxy!=null) { return narrowProxy(proxy, persister, key, impl); } else { return impl; } } public Object proxyFor(Object impl) throws HibernateException { EntityEntry e = getEntry(impl); //can't use e.persister since it is null after addUninitializedEntity (when this method is called) ClassPersister p = getPersister(impl); return proxyFor( p, new Key(e.id, p), impl); } /** * Create a "temporary" entry for a newly instantiated entity. The entity is uninitialized, * but we need the mapping from id to instance in order to guarantee uniqueness. */ public void addUninitializedEntity(Key key, Object object, LockMode lockMode) { addEntity(key, object); addEntry( object, LOADING, null, key.getIdentifier(), null, lockMode, true, null /*getPersister(object)*/, false ); //temporary } /** * Add the "hydrated state" (an array) of an uninitialized entity to the session. We don't try * to resolve any associations yet, because there might be other entities waiting to be * read from the JDBC result set we are currently processing */ public void postHydrate(ClassPersister persister, Serializable id, Object[] values, Object object, LockMode lockMode) throws HibernateException { //persister.setIdentifier(object, id); Object version = Versioning.getVersion(values, persister); addEntry(object, LOADING, values, id, version, lockMode, true, persister, false); if ( log.isTraceEnabled() && version!=null ) log.trace("Version: " + version); } public void load(Object object, Serializable id) throws HibernateException { if (id==null) throw new NullPointerException("null is not a valid identifier"); doLoadByObject(object, id, LockMode.NONE); } public Object load(Class clazz, Serializable id) throws HibernateException { if (id==null) throw new NullPointerException("null is not a valid identifier"); Object result = doLoadByClass(clazz, id, true, true); ObjectNotFoundException.throwIfNull(result, id, clazz); return result; } public Object get(Class clazz, Serializable id) throws HibernateException { if (id==null) throw new NullPointerException("null is not a valid identifier"); return doLoadByClass(clazz, id, true, false); } /** * Load the data for the object with the specified id into a newly created object. * Do NOT return a proxy. */ public Object immediateLoad(Class clazz, Serializable id) throws HibernateException { Object result = doLoad(clazz, id, null, LockMode.NONE, false); ObjectNotFoundException.throwIfNull(result, id, clazz); //should it be UnresolvableObject? return result; } /** * Return the object with the specified id or null if no row with that id exists. Do not defer the load * or return a new proxy (but do return an existing proxy). Do not check if the object was deleted. */ public Object internalLoadOneToOne(Class clazz, Serializable id) throws HibernateException { return doLoadByClass(clazz, id, false, false); } /** * Return the object with the specified id or throw exception if no row with that id exists. Defer the load, * return a new proxy or return an existing proxy if possible. Do not check if the object was deleted. */ public Object internalLoad(Class clazz, Serializable id) throws HibernateException { Object result = doLoadByClass(clazz, id, false, true); UnresolvableObjectException.throwIfNull(result, id, clazz); return result; } /** * Load the data for the object with the specified id into the supplied * instance. A new key will be assigned to the object. If there is an * existing uninitialized proxy, this will break identity equals as far * as the application is concerned. */ private void doLoadByObject(Object object, Serializable id, LockMode lockMode) throws HibernateException { Class clazz = object.getClass(); if ( getEntry(object)!=null ) throw new PersistentObjectException( "attempted to load into an instance that was already associated with the Session: " + MessageHelper.infoString(clazz, id) ); Object result = doLoad(clazz, id, object, lockMode, true); ObjectNotFoundException.throwIfNull(result, id, clazz); if (result!=object) throw new NonUniqueObjectException(id, clazz); } /** * Load the data for the object with the specified id into a newly created * object. A new key will be assigned to the object. If the class supports * lazy initialization, return a proxy instead, leaving the real work for * later. This should return an existing proxy where appropriate. */ private Object doLoadByClass(Class clazz, Serializable id, boolean checkDeleted, boolean allowProxyCreation) throws HibernateException { if ( log.isTraceEnabled() ) log.trace( "loading " + MessageHelper.infoString(clazz, id) ); ClassPersister persister = getClassPersister(clazz); if ( !persister.hasProxy() ) { // this class has no proxies (so do a shortcut) return doLoad(clazz, id, null, LockMode.NONE, checkDeleted); } else { Key key = new Key(id, persister); Object proxy; if ( getEntity(key)!=null ) { // return existing object or initialized proxy (unless deleted) return proxyFor( persister, key, doLoad(clazz, id, null, LockMode.NONE, checkDeleted) // just to do the deleted check ); } else if ( ( proxy = proxiesByKey.get(key) )!=null ) { // return existing uninitialized proxy return narrowProxy(proxy, persister, key, null); } else if (allowProxyCreation) { // return new uninitialized proxy proxy = persister.createProxy(id, this); if ( persister.isBatchLoadable() ) batchLoadableEntityKeys.put(key, MARKER); proxiesByKey.put(key, proxy); return proxy; } else { // return a newly loaded object return doLoad(clazz, id, null, LockMode.NONE, checkDeleted); } } } /** * Load the data for the object with the specified id into a newly created object * using "for update", if supported. A new key will be assigned to the object. * This method always hits the db, and does not create proxies. It should return * an existing proxy where appropriate. */ private Object doLoad(Class clazz, Serializable id, LockMode lockMode, boolean allowNull) throws HibernateException { if (id==null) throw new NullPointerException("null is not a valid identifier"); if ( log.isTraceEnabled() ) log.trace( "loading " + MessageHelper.infoString(clazz, id) + " in lock mode: " + lockMode ); ClassPersister persister = getClassPersister(clazz); SoftLock lock = null; if ( persister.hasCache() ) lock = persister.getCache().lock(id); //increments the lock Object result; try { result = doLoad(clazz, id, null, lockMode, true); } finally { // the database now holds a lock + the object is flushed from the cache, // so release the soft lock if ( persister.hasCache() ) persister.getCache().release(id, lock); } if (!allowNull) ObjectNotFoundException.throwIfNull( result, id, persister.getMappedClass() ); //return existing proxy (if one exists) return proxyFor(persister, new Key(id, persister), result); } public Object load(Class clazz, Serializable id, LockMode lockMode) throws HibernateException { if (lockMode==LockMode.WRITE) throw new HibernateException("Invalid lock mode for load()"); if (lockMode==LockMode.NONE) return load(clazz, id); //we don't necessarily need to hit the db in this case return doLoad(clazz, id, lockMode, false); } public Object get(Class clazz, Serializable id, LockMode lockMode) throws HibernateException { if (lockMode==LockMode.WRITE) throw new HibernateException("Invalid lock mode for get()"); if (lockMode==LockMode.NONE) return get(clazz, id); //we don't necessarily need to hit the db in this case return doLoad(clazz, id, lockMode, true); } /** * Actually do all the hard work of loading up an object. * 1. see if its already loaded * 2. see if its cached * 3. actually go to the database */ private Object doLoad( final Class clazz, final Serializable id, final Object optionalObject, final LockMode lockMode, final boolean checkDeleted ) throws HibernateException { //DONT need to flush before a load by id, because ids are constant if ( log.isTraceEnabled() ) log.trace( "attempting to resolve " + MessageHelper.infoString(clazz, id) ); final ClassPersister persister = getClassPersister(clazz); final Key key = new Key(id, persister); if (optionalObject!=null) persister.setIdentifier(optionalOb
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -