001: //$Id: StatelessSessionImpl.java 10018 2006-06-15 05:21:06Z steve.ebersole@jboss.com $
002: package org.hibernate.impl;
003:
004: import java.io.Serializable;
005: import java.sql.Connection;
006: import java.util.Collections;
007: import java.util.Iterator;
008: import java.util.List;
009: import java.util.Map;
010: import java.util.Set;
011:
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014: import org.hibernate.CacheMode;
015: import org.hibernate.ConnectionReleaseMode;
016: import org.hibernate.Criteria;
017: import org.hibernate.EmptyInterceptor;
018: import org.hibernate.EntityMode;
019: import org.hibernate.FlushMode;
020: import org.hibernate.HibernateException;
021: import org.hibernate.Interceptor;
022: import org.hibernate.LockMode;
023: import org.hibernate.MappingException;
024: import org.hibernate.ScrollMode;
025: import org.hibernate.ScrollableResults;
026: import org.hibernate.SessionException;
027: import org.hibernate.StatelessSession;
028: import org.hibernate.Transaction;
029: import org.hibernate.UnresolvableObjectException;
030: import org.hibernate.cache.CacheKey;
031: import org.hibernate.collection.PersistentCollection;
032: import org.hibernate.engine.EntityKey;
033: import org.hibernate.engine.PersistenceContext;
034: import org.hibernate.engine.QueryParameters;
035: import org.hibernate.engine.StatefulPersistenceContext;
036: import org.hibernate.engine.Versioning;
037: import org.hibernate.engine.query.HQLQueryPlan;
038: import org.hibernate.engine.query.NativeSQLQueryPlan;
039: import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
040: import org.hibernate.event.EventListeners;
041: import org.hibernate.id.IdentifierGeneratorFactory;
042: import org.hibernate.jdbc.Batcher;
043: import org.hibernate.jdbc.JDBCContext;
044: import org.hibernate.loader.criteria.CriteriaLoader;
045: import org.hibernate.loader.custom.CustomLoader;
046: import org.hibernate.loader.custom.CustomQuery;
047: import org.hibernate.persister.entity.EntityPersister;
048: import org.hibernate.persister.entity.OuterJoinLoadable;
049: import org.hibernate.pretty.MessageHelper;
050: import org.hibernate.proxy.HibernateProxy;
051: import org.hibernate.type.Type;
052: import org.hibernate.util.CollectionHelper;
053:
054: /**
055: * @author Gavin King
056: */
057: public class StatelessSessionImpl extends AbstractSessionImpl implements
058: JDBCContext.Context, StatelessSession {
059:
060: private static final Log log = LogFactory
061: .getLog(StatelessSessionImpl.class);
062:
063: private JDBCContext jdbcContext;
064: private PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext(
065: this );
066:
067: StatelessSessionImpl(Connection connection,
068: SessionFactoryImpl factory) {
069: super (factory);
070: this .jdbcContext = new JDBCContext(this , connection,
071: EmptyInterceptor.INSTANCE);
072: }
073:
074: // inserts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
075:
076: public Serializable insert(Object entity) {
077: errorIfClosed();
078: return insert(null, entity);
079: }
080:
081: public Serializable insert(String entityName, Object entity) {
082: errorIfClosed();
083: EntityPersister persister = getEntityPersister(entityName,
084: entity);
085: Serializable id = persister.getIdentifierGenerator().generate(
086: this , entity);
087: Object[] state = persister.getPropertyValues(entity,
088: EntityMode.POJO);
089: if (persister.isVersioned()) {
090: boolean substitute = Versioning.seedVersion(state,
091: persister.getVersionProperty(), persister
092: .getVersionType(), this );
093: if (substitute) {
094: persister.setPropertyValues(entity, state,
095: EntityMode.POJO);
096: }
097: }
098: if (id == IdentifierGeneratorFactory.POST_INSERT_INDICATOR) {
099: id = persister.insert(state, entity, this );
100: } else {
101: persister.insert(id, state, entity, this );
102: }
103: persister.setIdentifier(entity, id, EntityMode.POJO);
104: return id;
105: }
106:
107: // deletes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108:
109: public void delete(Object entity) {
110: errorIfClosed();
111: delete(null, entity);
112: }
113:
114: public void delete(String entityName, Object entity) {
115: errorIfClosed();
116: EntityPersister persister = getEntityPersister(entityName,
117: entity);
118: Serializable id = persister.getIdentifier(entity,
119: EntityMode.POJO);
120: Object version = persister.getVersion(entity, EntityMode.POJO);
121: persister.delete(id, version, entity, this );
122: }
123:
124: // updates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125:
126: public void update(Object entity) {
127: errorIfClosed();
128: update(null, entity);
129: }
130:
131: public void update(String entityName, Object entity) {
132: errorIfClosed();
133: EntityPersister persister = getEntityPersister(entityName,
134: entity);
135: Serializable id = persister.getIdentifier(entity,
136: EntityMode.POJO);
137: Object[] state = persister.getPropertyValues(entity,
138: EntityMode.POJO);
139: Object oldVersion;
140: if (persister.isVersioned()) {
141: oldVersion = persister.getVersion(entity, EntityMode.POJO);
142: Object newVersion = Versioning.increment(oldVersion,
143: persister.getVersionType(), this );
144: Versioning.setVersion(state, newVersion, persister);
145: persister.setPropertyValues(entity, state, EntityMode.POJO);
146: } else {
147: oldVersion = null;
148: }
149: persister.update(id, state, null, false, null, oldVersion,
150: entity, null, this );
151: }
152:
153: // loading ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154:
155: public Object get(Class entityClass, Serializable id) {
156: return get(entityClass.getName(), id);
157: }
158:
159: public Object get(Class entityClass, Serializable id,
160: LockMode lockMode) {
161: return get(entityClass.getName(), id, lockMode);
162: }
163:
164: public Object get(String entityName, Serializable id) {
165: return get(entityName, id, LockMode.NONE);
166: }
167:
168: public Object get(String entityName, Serializable id,
169: LockMode lockMode) {
170: errorIfClosed();
171: Object result = getFactory().getEntityPersister(entityName)
172: .load(id, null, lockMode, this );
173: temporaryPersistenceContext.clear();
174: return result;
175: }
176:
177: public void refresh(Object entity) {
178: refresh(bestGuessEntityName(entity), entity, LockMode.NONE);
179: }
180:
181: public void refresh(String entityName, Object entity) {
182: refresh(entityName, entity, LockMode.NONE);
183: }
184:
185: public void refresh(Object entity, LockMode lockMode) {
186: refresh(bestGuessEntityName(entity), entity, lockMode);
187: }
188:
189: public void refresh(String entityName, Object entity,
190: LockMode lockMode) {
191: final EntityPersister persister = this .getEntityPersister(
192: entityName, entity);
193: final Serializable id = persister.getIdentifier(entity,
194: getEntityMode());
195: if (log.isTraceEnabled()) {
196: log.trace("refreshing transient "
197: + MessageHelper.infoString(persister, id, this
198: .getFactory()));
199: }
200: // TODO : can this ever happen???
201: // EntityKey key = new EntityKey( id, persister, source.getEntityMode() );
202: // if ( source.getPersistenceContext().getEntry( key ) != null ) {
203: // throw new PersistentObjectException(
204: // "attempted to refresh transient instance when persistent " +
205: // "instance was already associated with the Session: " +
206: // MessageHelper.infoString( persister, id, source.getFactory() )
207: // );
208: // }
209:
210: if (persister.hasCache()) {
211: final CacheKey ck = new CacheKey(id, persister
212: .getIdentifierType(),
213: persister.getRootEntityName(),
214: this .getEntityMode(), this .getFactory());
215: persister.getCache().remove(ck);
216: }
217:
218: String previousFetchProfile = this .getFetchProfile();
219: Object result = null;
220: try {
221: this .setFetchProfile("refresh");
222: result = persister.load(id, entity, lockMode, this );
223: } finally {
224: this .setFetchProfile(previousFetchProfile);
225: }
226: UnresolvableObjectException.throwIfNull(result, id, persister
227: .getEntityName());
228: }
229:
230: public Object immediateLoad(String entityName, Serializable id)
231: throws HibernateException {
232: throw new SessionException(
233: "proxies cannot be fetched by a stateless session");
234: }
235:
236: public void initializeCollection(PersistentCollection collection,
237: boolean writing) throws HibernateException {
238: throw new SessionException(
239: "collections cannot be fetched by a stateless session");
240: }
241:
242: public Object instantiate(String entityName, Serializable id)
243: throws HibernateException {
244: errorIfClosed();
245: return getFactory().getEntityPersister(entityName).instantiate(
246: id, EntityMode.POJO);
247: }
248:
249: public Object internalLoad(String entityName, Serializable id,
250: boolean eager, boolean nullable) throws HibernateException {
251: errorIfClosed();
252: EntityPersister persister = getFactory().getEntityPersister(
253: entityName);
254: if (!eager && persister.hasProxy()) {
255: return persister.createProxy(id, this );
256: }
257: Object loaded = temporaryPersistenceContext
258: .getEntity(new EntityKey(id, persister, EntityMode.POJO));
259: //TODO: if not loaded, throw an exception
260: return loaded == null ? get(entityName, id) : loaded;
261: }
262:
263: public Iterator iterate(String query,
264: QueryParameters queryParameters) throws HibernateException {
265: throw new UnsupportedOperationException();
266: }
267:
268: public Iterator iterateFilter(Object collection, String filter,
269: QueryParameters queryParameters) throws HibernateException {
270: throw new UnsupportedOperationException();
271: }
272:
273: public List listFilter(Object collection, String filter,
274: QueryParameters queryParameters) throws HibernateException {
275: throw new UnsupportedOperationException();
276: }
277:
278: public boolean isOpen() {
279: return !isClosed();
280: }
281:
282: public void close() {
283: managedClose();
284: }
285:
286: public ConnectionReleaseMode getConnectionReleaseMode() {
287: return factory.getSettings().getConnectionReleaseMode();
288: }
289:
290: public boolean isAutoCloseSessionEnabled() {
291: return factory.getSettings().isAutoCloseSessionEnabled();
292: }
293:
294: public boolean isFlushBeforeCompletionEnabled() {
295: return true;
296: }
297:
298: public boolean isFlushModeNever() {
299: return false;
300: }
301:
302: public void managedClose() {
303: if (isClosed()) {
304: throw new SessionException("Session was already closed!");
305: }
306: jdbcContext.getConnectionManager().close();
307: setClosed();
308: }
309:
310: public void managedFlush() {
311: errorIfClosed();
312: getBatcher().executeBatch();
313: }
314:
315: public boolean shouldAutoClose() {
316: return isAutoCloseSessionEnabled() && !isClosed();
317: }
318:
319: public void afterTransactionCompletion(boolean successful,
320: Transaction tx) {
321: }
322:
323: public void beforeTransactionCompletion(Transaction tx) {
324: }
325:
326: public String bestGuessEntityName(Object object) {
327: if (object instanceof HibernateProxy) {
328: object = ((HibernateProxy) object)
329: .getHibernateLazyInitializer().getImplementation();
330: }
331: return guessEntityName(object);
332: }
333:
334: public Connection connection() {
335: errorIfClosed();
336: return jdbcContext.borrowConnection();
337: }
338:
339: public int executeUpdate(String query,
340: QueryParameters queryParameters) throws HibernateException {
341: errorIfClosed();
342: queryParameters.validateParameters();
343: HQLQueryPlan plan = getHQLQueryPlan(query, false);
344: boolean success = false;
345: int result = 0;
346: try {
347: result = plan.performExecuteUpdate(queryParameters, this );
348: success = true;
349: } finally {
350: afterOperation(success);
351: }
352: temporaryPersistenceContext.clear();
353: return result;
354: }
355:
356: public Batcher getBatcher() {
357: errorIfClosed();
358: return jdbcContext.getConnectionManager().getBatcher();
359: }
360:
361: public CacheMode getCacheMode() {
362: return CacheMode.IGNORE;
363: }
364:
365: public int getDontFlushFromFind() {
366: return 0;
367: }
368:
369: public Map getEnabledFilters() {
370: return CollectionHelper.EMPTY_MAP;
371: }
372:
373: public Serializable getContextEntityIdentifier(Object object) {
374: errorIfClosed();
375: return null;
376: }
377:
378: public EntityMode getEntityMode() {
379: return EntityMode.POJO;
380: }
381:
382: public EntityPersister getEntityPersister(String entityName,
383: Object object) throws HibernateException {
384: errorIfClosed();
385: if (entityName == null) {
386: return factory.getEntityPersister(guessEntityName(object));
387: } else {
388: return factory.getEntityPersister(entityName)
389: .getSubclassEntityPersister(object, getFactory(),
390: EntityMode.POJO);
391: }
392: }
393:
394: public Object getEntityUsingInterceptor(EntityKey key)
395: throws HibernateException {
396: errorIfClosed();
397: return null;
398: }
399:
400: public Type getFilterParameterType(String filterParameterName) {
401: throw new UnsupportedOperationException();
402: }
403:
404: public Object getFilterParameterValue(String filterParameterName) {
405: throw new UnsupportedOperationException();
406: }
407:
408: public FlushMode getFlushMode() {
409: return FlushMode.COMMIT;
410: }
411:
412: public Interceptor getInterceptor() {
413: return EmptyInterceptor.INSTANCE;
414: }
415:
416: public EventListeners getListeners() {
417: throw new UnsupportedOperationException();
418: }
419:
420: public PersistenceContext getPersistenceContext() {
421: return temporaryPersistenceContext;
422: }
423:
424: public long getTimestamp() {
425: throw new UnsupportedOperationException();
426: }
427:
428: public String guessEntityName(Object entity)
429: throws HibernateException {
430: errorIfClosed();
431: return entity.getClass().getName();
432: }
433:
434: public boolean isConnected() {
435: return jdbcContext.getConnectionManager()
436: .isCurrentlyConnected();
437: }
438:
439: public boolean isTransactionInProgress() {
440: return jdbcContext.isTransactionInProgress();
441: }
442:
443: public void setAutoClear(boolean enabled) {
444: throw new UnsupportedOperationException();
445: }
446:
447: public void setCacheMode(CacheMode cm) {
448: throw new UnsupportedOperationException();
449: }
450:
451: public void setFlushMode(FlushMode fm) {
452: throw new UnsupportedOperationException();
453: }
454:
455: public Transaction getTransaction() throws HibernateException {
456: errorIfClosed();
457: return jdbcContext.getTransaction();
458: }
459:
460: public Transaction beginTransaction() throws HibernateException {
461: errorIfClosed();
462: Transaction result = getTransaction();
463: result.begin();
464: return result;
465: }
466:
467: public boolean isEventSource() {
468: return false;
469: }
470:
471: /////////////////////////////////////////////////////////////////////////////////////////////////////
472:
473: //TODO: COPY/PASTE FROM SessionImpl, pull up!
474:
475: public List list(String query, QueryParameters queryParameters)
476: throws HibernateException {
477: errorIfClosed();
478: queryParameters.validateParameters();
479: HQLQueryPlan plan = getHQLQueryPlan(query, false);
480: boolean success = false;
481: List results = CollectionHelper.EMPTY_LIST;
482: try {
483: results = plan.performList(queryParameters, this );
484: success = true;
485: } finally {
486: afterOperation(success);
487: }
488: temporaryPersistenceContext.clear();
489: return results;
490: }
491:
492: public void afterOperation(boolean success) {
493: if (!jdbcContext.isTransactionInProgress()) {
494: jdbcContext.afterNontransactionalQuery(success);
495: }
496: }
497:
498: public Criteria createCriteria(Class persistentClass, String alias) {
499: errorIfClosed();
500: return new CriteriaImpl(persistentClass.getName(), alias, this );
501: }
502:
503: public Criteria createCriteria(String entityName, String alias) {
504: errorIfClosed();
505: return new CriteriaImpl(entityName, alias, this );
506: }
507:
508: public Criteria createCriteria(Class persistentClass) {
509: errorIfClosed();
510: return new CriteriaImpl(persistentClass.getName(), this );
511: }
512:
513: public Criteria createCriteria(String entityName) {
514: errorIfClosed();
515: return new CriteriaImpl(entityName, this );
516: }
517:
518: public ScrollableResults scroll(CriteriaImpl criteria,
519: ScrollMode scrollMode) {
520: errorIfClosed();
521: String entityName = criteria.getEntityOrClassName();
522: CriteriaLoader loader = new CriteriaLoader(
523: getOuterJoinLoadable(entityName), factory, criteria,
524: entityName, getEnabledFilters());
525: return loader.scroll(this , scrollMode);
526: }
527:
528: public List list(CriteriaImpl criteria) throws HibernateException {
529: errorIfClosed();
530: String[] implementors = factory.getImplementors(criteria
531: .getEntityOrClassName());
532: int size = implementors.length;
533:
534: CriteriaLoader[] loaders = new CriteriaLoader[size];
535: for (int i = 0; i < size; i++) {
536: loaders[i] = new CriteriaLoader(
537: getOuterJoinLoadable(implementors[i]), factory,
538: criteria, implementors[i], getEnabledFilters());
539: }
540:
541: List results = Collections.EMPTY_LIST;
542: boolean success = false;
543: try {
544: for (int i = 0; i < size; i++) {
545: final List currentResults = loaders[i].list(this );
546: currentResults.addAll(results);
547: results = currentResults;
548: }
549: success = true;
550: } finally {
551: afterOperation(success);
552: }
553: temporaryPersistenceContext.clear();
554: return results;
555: }
556:
557: private OuterJoinLoadable getOuterJoinLoadable(String entityName)
558: throws MappingException {
559: EntityPersister persister = factory
560: .getEntityPersister(entityName);
561: if (!(persister instanceof OuterJoinLoadable)) {
562: throw new MappingException(
563: "class persister is not OuterJoinLoadable: "
564: + entityName);
565: }
566: return (OuterJoinLoadable) persister;
567: }
568:
569: public List listCustomQuery(CustomQuery customQuery,
570: QueryParameters queryParameters) throws HibernateException {
571: errorIfClosed();
572: CustomLoader loader = new CustomLoader(customQuery,
573: getFactory());
574:
575: boolean success = false;
576: List results;
577: try {
578: results = loader.list(this , queryParameters);
579: success = true;
580: } finally {
581: afterOperation(success);
582: }
583: temporaryPersistenceContext.clear();
584: return results;
585: }
586:
587: public ScrollableResults scrollCustomQuery(CustomQuery customQuery,
588: QueryParameters queryParameters) throws HibernateException {
589: errorIfClosed();
590: CustomLoader loader = new CustomLoader(customQuery,
591: getFactory());
592: return loader.scroll(queryParameters, this );
593: }
594:
595: public ScrollableResults scroll(String query,
596: QueryParameters queryParameters) throws HibernateException {
597: errorIfClosed();
598: HQLQueryPlan plan = getHQLQueryPlan(query, false);
599: return plan.performScroll(queryParameters, this );
600: }
601:
602: public void afterScrollOperation() {
603: temporaryPersistenceContext.clear();
604: }
605:
606: public void flush() {
607: }
608:
609: public String getFetchProfile() {
610: return null;
611: }
612:
613: public JDBCContext getJDBCContext() {
614: return jdbcContext;
615: }
616:
617: public void setFetchProfile(String name) {
618: }
619:
620: public void afterTransactionBegin(Transaction tx) {
621: }
622:
623: protected boolean autoFlushIfRequired(Set querySpaces)
624: throws HibernateException {
625: // no auto-flushing to support in stateless session
626: return false;
627: }
628:
629: public int executeNativeUpdate(
630: NativeSQLQuerySpecification nativeSQLQuerySpecification,
631: QueryParameters queryParameters) throws HibernateException {
632: errorIfClosed();
633: queryParameters.validateParameters();
634: NativeSQLQueryPlan plan = getNativeSQLQueryPlan(nativeSQLQuerySpecification);
635:
636: boolean success = false;
637: int result = 0;
638: try {
639: result = plan.performExecuteUpdate(queryParameters, this );
640: success = true;
641: } finally {
642: afterOperation(success);
643: }
644: temporaryPersistenceContext.clear();
645: return result;
646: }
647:
648: }
|