KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > amber > manager > AmberConnection


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.amber.manager;
31
32 import com.caucho.amber.AmberException;
33 import com.caucho.amber.AmberObjectNotFoundException;
34 import com.caucho.amber.AmberQuery;
35 import com.caucho.amber.AmberRuntimeException;
36 import com.caucho.amber.cfg.EntityResultConfig;
37 import com.caucho.amber.cfg.NamedNativeQueryConfig;
38 import com.caucho.amber.cfg.SqlResultSetMappingConfig;
39 import com.caucho.amber.collection.AmberCollection;
40 import com.caucho.amber.entity.*;
41 import com.caucho.amber.query.AbstractQuery;
42 import com.caucho.amber.query.QueryCacheKey;
43 import com.caucho.amber.query.QueryParser;
44 import com.caucho.amber.query.ResultSetCacheChunk;
45 import com.caucho.amber.query.UserQuery;
46 import com.caucho.amber.table.Table;
47 import com.caucho.amber.type.EntityType;
48 import com.caucho.config.ConfigException;
49 import com.caucho.ejb.EJBExceptionWrapper;
50 import com.caucho.jca.BeginResource;
51 import com.caucho.jca.CloseResource;
52 import com.caucho.jca.UserTransactionProxy;
53 import com.caucho.util.L10N;
54 import com.caucho.util.LruCache;
55
56 import javax.persistence.EntityNotFoundException;
57 import javax.persistence.EntityTransaction;
58 import javax.persistence.FlushModeType;
59 import javax.persistence.LockModeType;
60 import javax.persistence.Query;
61 import javax.persistence.PersistenceException;
62 import javax.persistence.EntityExistsException;
63 import javax.persistence.TransactionRequiredException;
64 import javax.sql.DataSource JavaDoc;
65 import javax.transaction.Status JavaDoc;
66 import javax.transaction.Synchronization JavaDoc;
67 import javax.transaction.Transaction JavaDoc;
68 import java.sql.Connection JavaDoc;
69 import java.sql.PreparedStatement JavaDoc;
70 import java.sql.ResultSet JavaDoc;
71 import java.sql.ResultSetMetaData JavaDoc;
72 import java.sql.SQLException JavaDoc;
73 import java.sql.Statement JavaDoc;
74 import java.util.ArrayList JavaDoc;
75 import java.util.List JavaDoc;
76 import java.util.Map JavaDoc;
77 import java.util.logging.Level JavaDoc;
78 import java.util.logging.Logger JavaDoc;
79
80 /**
81  * The entity manager from a entity manager proxy.
82  */

83 public class AmberConnection
84   implements BeginResource, CloseResource, Synchronization JavaDoc
85 {
86   private static final L10N L = new L10N(AmberConnection.class);
87   private static final Logger JavaDoc log
88     = Logger.getLogger(AmberConnection.class.getName());
89
90   private AmberPersistenceUnit _persistenceUnit;
91
92   private boolean _isRegistered;
93   private boolean _isThreadConnection;
94
95   private ArrayList JavaDoc<Entity> _entities = new ArrayList JavaDoc<Entity>();
96
97   private ArrayList JavaDoc<Entity> _txEntities = new ArrayList JavaDoc<Entity>();
98
99   private ArrayList JavaDoc<AmberCompletion> _completionList
100     = new ArrayList JavaDoc<AmberCompletion>();
101
102   private ArrayList JavaDoc<AmberCollection> _queries
103     = new ArrayList JavaDoc<AmberCollection>();
104
105   private EntityTransaction _trans;
106
107   private long _xid;
108   private boolean _isInTransaction;
109   private boolean _isXA;
110
111   private Connection JavaDoc _conn;
112   private Connection JavaDoc _readConn;
113
114   private boolean _isAutoCommit = true;
115
116   private int _depth;
117
118   private LruCache<String JavaDoc,PreparedStatement JavaDoc> _preparedStatementMap
119     = new LruCache<String JavaDoc,PreparedStatement JavaDoc>(32);
120
121   private ArrayList JavaDoc<Statement JavaDoc> _statements = new ArrayList JavaDoc<Statement JavaDoc>();
122
123   private QueryCacheKey _queryKey = new QueryCacheKey();
124
125   /**
126    * Creates a manager instance.
127    */

128   AmberConnection(AmberPersistenceUnit persistenceUnit)
129   {
130     _persistenceUnit = persistenceUnit;
131   }
132
133   /**
134    * Returns the persistence unit.
135    */

136   public AmberPersistenceUnit getPersistenceUnit()
137   {
138     return _persistenceUnit;
139   }
140
141   /**
142    * Set true for a threaded connection.
143    */

144   public void initThreadConnection()
145   {
146     _isThreadConnection = true;
147
148     register();
149   }
150
151   /**
152    * @PrePersist callback for default listeners and
153    * entity listeners.
154    */

155   public void prePersist(Entity entity)
156   {
157     try {
158       _persistenceUnit.callListeners(Listener.PRE_PERSIST, entity);
159     } catch (RuntimeException JavaDoc e) {
160       throw e;
161     } catch (Exception JavaDoc e) {
162       throw new EJBExceptionWrapper(e);
163     }
164   }
165
166   /**
167    * @PostPersist callback for default listeners and
168    * entity listeners.
169    */

170   public void postPersist(Entity entity)
171   {
172     try {
173       _persistenceUnit.callListeners(Listener.POST_PERSIST, entity);
174     } catch (RuntimeException JavaDoc e) {
175       throw e;
176     } catch (Exception JavaDoc e) {
177       throw new EJBExceptionWrapper(e);
178     }
179   }
180
181   /**
182    * @PreRemove callback for default listeners and
183    * entity listeners.
184    */

185   public void preRemove(Entity entity)
186   {
187     try {
188       _persistenceUnit.callListeners(Listener.PRE_REMOVE, entity);
189     } catch (RuntimeException JavaDoc e) {
190       throw e;
191     } catch (Exception JavaDoc e) {
192       throw new EJBExceptionWrapper(e);
193     }
194   }
195
196   /**
197    * @PostRemove callback for default listeners and
198    * entity listeners.
199    */

200   public void postRemove(Entity entity)
201   {
202     try {
203       _persistenceUnit.callListeners(Listener.POST_REMOVE, entity);
204     } catch (RuntimeException JavaDoc e) {
205       throw e;
206     } catch (Exception JavaDoc e) {
207       throw new EJBExceptionWrapper(e);
208     }
209   }
210
211   /**
212    * @PreUpdate callback for default listeners and
213    * entity listeners.
214    */

215   public void preUpdate(Entity entity)
216   {
217     try {
218       _persistenceUnit.callListeners(Listener.PRE_UPDATE, entity);
219     } catch (RuntimeException JavaDoc e) {
220       throw e;
221     } catch (Exception JavaDoc e) {
222       throw new EJBExceptionWrapper(e);
223     }
224   }
225
226   /**
227    * @PostUpdate callback for default listeners and
228    * entity listeners.
229    */

230   public void postUpdate(Entity entity)
231   {
232     try {
233       _persistenceUnit.callListeners(Listener.POST_UPDATE, entity);
234     } catch (RuntimeException JavaDoc e) {
235       throw e;
236     } catch (Exception JavaDoc e) {
237       throw new EJBExceptionWrapper(e);
238     }
239   }
240
241   /**
242    * @PostLoad callback for default listeners and
243    * entity listeners.
244    */

245   public void postLoad(Entity entity)
246   {
247     try {
248       _persistenceUnit.callListeners(Listener.POST_LOAD, entity);
249     } catch (RuntimeException JavaDoc e) {
250       throw e;
251     } catch (Exception JavaDoc e) {
252       throw new EJBExceptionWrapper(e);
253     }
254   }
255
256   /**
257    * Makes the instance managed.
258    */

259   public void persist(Object JavaDoc entity)
260   {
261     try {
262       if (entity == null)
263         return;
264
265       if (! (entity instanceof Entity))
266         throw new IllegalArgumentException JavaDoc(L.l("persist() operation can only be applied to an entity instance. If the argument is an entity, the corresponding class must be specified in the scope of a persistence unit."));
267
268       checkTransactionRequired("persist");
269
270       persistInternal(entity);
271
272     } catch (RuntimeException JavaDoc e) {
273       throw e;
274     } catch (SQLException JavaDoc e) {
275       throw new IllegalStateException JavaDoc(e);
276     } catch (Exception JavaDoc e) {
277       throw new EJBExceptionWrapper(e);
278     }
279   }
280
281   /**
282    * Makes the instance managed called
283    * from cascading operations.
284    */

285   public void persistNoChecks(Object JavaDoc entity)
286   {
287     try {
288       if (entity == null)
289         return;
290
291       persistInternal(entity);
292
293     } catch (EntityExistsException e) {
294       // This is not an issue. It is the cascading
295
// operation trying to persist the source
296
// entity from the destination end.
297
} catch (RuntimeException JavaDoc e) {
298       throw e;
299     } catch (SQLException JavaDoc e) {
300       throw new IllegalStateException JavaDoc(e);
301     } catch (Exception JavaDoc e) {
302       throw new EJBExceptionWrapper(e);
303     }
304   }
305
306   /**
307    * Merges the state of the entity into the current context.
308    */

309   public <T> T merge(T entityT)
310   {
311     try {
312
313       if (! (entityT instanceof Entity))
314         throw new IllegalArgumentException JavaDoc(L.l("merge() operation can only be applied to an entity instance. If the argument is an entity, the corresponding class must be specified in the scope of a persistence unit."));
315
316       flushInternal();
317
318       Entity entity = (Entity) entityT;
319
320       int state = entity.__caucho_getEntityState();
321
322       if (state == com.caucho.amber.entity.Entity.TRANSIENT) {
323         if (contains(entity)) {
324           // detached entity instance
325
throw new UnsupportedOperationException JavaDoc(L.l("Merge operation for detached instances is not supported"));
326         }
327         else {
328           // new entity instance
329
persist(entity);
330         }
331       }
332       else if (state >= com.caucho.amber.entity.Entity.P_DELETING) {
333         // removed entity instance
334
throw new IllegalArgumentException JavaDoc(L.l("Merge operation cannot be applied to a removed entity instance"));
335       }
336       else {
337         // managed entity instance: ignored.
338

339         // cascade children
340
entity.__caucho_cascadePrePersist(this);
341
342         // jpa/0i5g
343
entity.__caucho_cascadePostPersist(this);
344       }
345
346       // XXX: merge recursively for
347
// cascade=MERGE or cascade=ALL
348

349       return entityT;
350
351     } catch (RuntimeException JavaDoc e) {
352       throw e;
353     } catch (Exception JavaDoc e) {
354       throw new EJBExceptionWrapper(e);
355     }
356   }
357
358   /**
359    * Remove the instance.
360    */

361   public void remove(Object JavaDoc entity)
362   {
363     try {
364       if (entity == null)
365         return;
366
367       if (! (entity instanceof Entity))
368         throw new IllegalArgumentException JavaDoc(L.l("remove() operation can only be applied to an entity instance. If the argument is an entity, the corresponding class must be specified in the scope of a persistence unit."));
369
370       checkTransactionRequired("remove");
371
372       Entity instance = (Entity) entity;
373
374       // jpa/0k12
375
if (instance.__caucho_getConnection() == null)
376         throw new IllegalArgumentException JavaDoc(L.l("remove() operation can only be applied to a managed entity. This entity instance is detached which means it was probably removed or needs to be merged."));
377
378       int state = instance.__caucho_getEntityState();
379
380       if (state >= com.caucho.amber.entity.Entity.P_DELETING)
381         return;
382
383       Object JavaDoc oldEntity = getEntity(instance.getClass().getName(),
384                                    instance.__caucho_getPrimaryKey());
385
386       // jpa/0ga4
387
if (oldEntity == null)
388         throw new IllegalArgumentException JavaDoc(L.l("remove() operation can only be applied to a managed entity instance."));
389
390       // Pre-remove child entities.
391
instance.__caucho_cascadePreRemove(this);
392
393       delete(instance);
394
395       // jpa/0o30
396
// Post-remove child entities.
397
instance.__caucho_cascadePostRemove(this);
398
399     } catch (RuntimeException JavaDoc e) {
400       throw e;
401     } catch (Exception JavaDoc e) {
402       throw new EJBExceptionWrapper(e);
403     }
404   }
405
406   /**
407    * Find by the primary key.
408    */

409   /*
410     public Object find(String entityName, Object primaryKey)
411     {
412     try {
413     return load(entityName, primaryKey);
414     } catch (RuntimeException e) {
415     throw e;
416     } catch (Exception e) {
417     throw new EJBExceptionWrapper(e);
418     }
419     }
420   */

421
422   /**
423    * Find by the primary key.
424    */

425   public <T> T find(Class JavaDoc<T> entityClass,
426                     Object JavaDoc primaryKey)
427   {
428     return find(entityClass, primaryKey, null);
429   }
430
431   /**
432    * Find by the primary key.
433    */

434   public <T> T find(Class JavaDoc<T> entityClass,
435                     Object JavaDoc primaryKey,
436                     Map JavaDoc preloadedProperties)
437   {
438     try {
439       AmberEntityHome entityHome
440         = _persistenceUnit.getEntityHome(entityClass.getName());
441
442       if (entityHome == null) {
443         throw new IllegalArgumentException JavaDoc(L.l("find() operation can only be applied if the entity class is specified in the scope of a persistence unit."));
444       }
445
446       return (T) load(entityClass, primaryKey, preloadedProperties);
447     } catch (AmberObjectNotFoundException e) {
448       // JPA: should not throw at all, returns null only.
449
// log.log(Level.FINER, e.toString(), e);
450

451       return null;
452     } catch (RuntimeException JavaDoc e) {
453       throw e;
454     } catch (Exception JavaDoc e) {
455       throw new EJBExceptionWrapper(e);
456     }
457   }
458
459   /**
460    * Find by the primary key.
461    */

462   public <T> T getReference(Class JavaDoc<T> entityClass, Object JavaDoc primaryKey)
463     throws EntityNotFoundException, IllegalArgumentException JavaDoc
464   {
465     T reference = null;
466
467     try {
468       // XXX: only needs to get a reference.
469

470       reference = find(entityClass, primaryKey);
471
472       if (reference == null)
473         throw new EntityNotFoundException(L.l("entity with primary key {0} not found in getReference()", primaryKey));
474
475       if (! (entityClass.isAssignableFrom(Entity.class)))
476         throw new IllegalArgumentException JavaDoc(L.l("getReference() operation can only be applied to an entity class"));
477
478       return reference;
479
480     } catch (EntityNotFoundException e) {
481       throw e;
482     } catch (RuntimeException JavaDoc e) {
483       throw new IllegalArgumentException JavaDoc(e);
484     } catch (Exception JavaDoc e) {
485       throw new EJBExceptionWrapper(e);
486     }
487   }
488
489   /**
490    * Clears the connection
491    */

492   public void clear()
493   {
494     _entities.clear();
495     _txEntities.clear();
496   }
497
498   /**
499    * Creates a query.
500    */

501   public Query createQuery(String JavaDoc sql)
502   {
503     try {
504       AbstractQuery queryProgram = parseQuery(sql, false);
505
506       return new QueryImpl(queryProgram, this);
507     } catch (RuntimeException JavaDoc e) {
508       throw new IllegalArgumentException JavaDoc(e);
509     } catch (Exception JavaDoc e) {
510       throw new EJBExceptionWrapper(e);
511     }
512   }
513
514   /**
515    * Creates an instance of the named query
516    */

517   public Query createNamedQuery(String JavaDoc name)
518   {
519     String JavaDoc sql = _persistenceUnit.getNamedQuery(name);
520
521     if (sql != null)
522       return createQuery(sql);
523
524     NamedNativeQueryConfig nativeQuery
525       = _persistenceUnit.getNamedNativeQuery(name);
526
527     sql = nativeQuery.getQuery();
528
529     String JavaDoc resultSetMapping = nativeQuery.getResultSetMapping();
530
531     if (! ((resultSetMapping == null) || "".equals(resultSetMapping)))
532       return createNativeQuery(sql, resultSetMapping);
533
534     String JavaDoc resultClass = nativeQuery.getResultClass();
535
536     AmberEntityHome entityHome
537       = _persistenceUnit.getEntityHome(resultClass);
538
539     EntityType entityType = entityHome.getEntityType();
540
541     try {
542       return createNativeQuery(sql, entityType.getInstanceClass());
543     } catch (Exception JavaDoc e) {
544       throw new IllegalArgumentException JavaDoc(e);
545     }
546   }
547
548   /**
549    * Creates an instance of the named query
550    */

551   public Query createNativeQuery(String JavaDoc sql)
552   {
553     try {
554       QueryImpl query = new QueryImpl(this);
555
556       query.setNativeSql(sql);
557
558       return query;
559     } catch (RuntimeException JavaDoc e) {
560       throw new IllegalArgumentException JavaDoc(e);
561     } catch (Exception JavaDoc e) {
562       throw new EJBExceptionWrapper(e);
563     }
564   }
565
566   /**
567    * Creates an instance of the named query
568    */

569   public Query createNativeQuery(String JavaDoc sql, String JavaDoc map)
570   {
571     // jpa/0y1-
572

573     SqlResultSetMappingConfig resultSet;
574
575     resultSet = _persistenceUnit.getSqlResultSetMapping(map);
576
577     if (resultSet == null)
578       throw new IllegalArgumentException JavaDoc(L.l("createNativeQuery() cannot create a native query for a result set named '{0}'", map));
579
580     return createInternalNativeQuery(sql, resultSet);
581   }
582
583   /**
584    * Creates an instance of the native query
585    */

586   public Query createNativeQuery(String JavaDoc sql, Class JavaDoc type)
587   {
588     SqlResultSetMappingConfig resultSet
589       = new SqlResultSetMappingConfig();
590
591     EntityResultConfig entityResult
592       = new EntityResultConfig();
593
594     entityResult.setEntityClass(type.getName());
595
596     resultSet.addEntityResult(entityResult);
597
598     return createInternalNativeQuery(sql, resultSet);
599   }
600
601   /**
602    * Refresh the state of the instance from the database.
603    */

604   public void refresh(Object JavaDoc entity)
605   {
606     try {
607       if (entity == null)
608         return;
609
610       if (! (entity instanceof Entity))
611         throw new IllegalArgumentException JavaDoc(L.l("refresh() operation can only be applied to an entity instance."));
612
613       checkTransactionRequired("refresh");
614
615       Entity instance = (Entity) entity;
616
617       Object JavaDoc oldEntity = getEntity(instance.getClass().getName(),
618                                    instance.__caucho_getPrimaryKey());
619
620       if (oldEntity != null) {
621         int state = instance.__caucho_getEntityState();
622
623         if (state <= Entity.TRANSIENT || state >= Entity.P_DELETING)
624           oldEntity = null;
625       }
626
627       if (oldEntity == null)
628         throw new IllegalArgumentException JavaDoc(L.l("refresh() operation can only be applied to a managed entity instance."));
629
630       // Reset and refresh state.
631
instance.__caucho_expire();
632       instance.__caucho_makePersistent(this, (EntityType) null);
633       instance.__caucho_retrieve(this);
634     } catch (SQLException JavaDoc e) {
635       throw new AmberRuntimeException(e);
636     }
637   }
638
639   /**
640    * Returns the flush mode.
641    */

642   public FlushModeType getFlushMode()
643   {
644     return FlushModeType.AUTO;
645   }
646
647   /**
648    * Returns the flush mode.
649    */

650   public void setFlushMode(FlushModeType mode)
651   {
652     throw new UnsupportedOperationException JavaDoc();
653   }
654
655   /**
656    * Locks the object.
657    */

658   public void lock(Object JavaDoc entity, LockModeType lockMode)
659   {
660     throw new UnsupportedOperationException JavaDoc();
661   }
662
663   /**
664    * Returns the transaction.
665    */

666   public EntityTransaction getTransaction()
667   {
668     if (_trans == null)
669       _trans = new EntityTransactionImpl();
670
671     return _trans;
672   }
673
674   /**
675    * Returns true if open.
676    */

677   public boolean isOpen()
678   {
679     return _persistenceUnit != null;
680   }
681
682   /**
683    * Registers with the local transaction.
684    */

685   void register()
686   {
687     if (! _isRegistered) {
688       UserTransactionProxy.getInstance().enlistCloseResource(this);
689       UserTransactionProxy.getInstance().enlistBeginResource(this);
690     }
691
692     _isRegistered = true;
693   }
694
695   /**
696    * Joins the transaction.
697    */

698   public void joinTransaction()
699   {
700     throw new UnsupportedOperationException JavaDoc();
701   }
702
703   /**
704    * Gets the delegate.
705    */

706   public Object JavaDoc getDelegate()
707   {
708     throw new UnsupportedOperationException JavaDoc();
709   }
710
711   /**
712    * Closes the context.
713    */

714   public void close()
715   {
716     if (_persistenceUnit == null)
717       return;
718
719     try {
720       if (_isThreadConnection)
721         _persistenceUnit.removeThreadConnection();
722
723       _isRegistered = false;
724
725       cleanup();
726     } finally {
727       _persistenceUnit = null;
728     }
729   }
730
731   /**
732    * Returns the amber manaber.
733    */

734   public AmberPersistenceUnit getAmberManager()
735   {
736     return _persistenceUnit;
737   }
738
739   /**
740    * Registers a collection.
741    */

742   public void register(AmberCollection query)
743   {
744     _queries.add(query);
745   }
746
747   /**
748    * Adds a completion
749    */

750   public void addCompletion(AmberCompletion completion)
751   {
752     if (! _completionList.contains(completion))
753       _completionList.add(completion);
754   }
755
756   /**
757    * Returns true if a transaction is active.
758    */

759   public boolean isInTransaction()
760   {
761     return _isInTransaction;
762   }
763
764   /**
765    * Returns the cache chunk size.
766    */

767   public int getCacheChunkSize()
768   {
769     return 25;
770   }
771
772   /**
773    * Loads the object based on the class and primary key.
774    */

775   public Object JavaDoc load(Class JavaDoc cl,
776                      Object JavaDoc key)
777     throws AmberException
778   {
779     return load(cl, key, null);
780   }
781
782   /**
783    * Loads the object based on the class and primary key.
784    */

785   public Object JavaDoc load(Class JavaDoc cl,
786                      Object JavaDoc key,
787                      Map JavaDoc preloadedProperties)
788     throws AmberException
789   {
790     Entity entity = null;
791
792     if (key == null)
793       return null;
794
795     // ejb/0d01, jpa/0gh0, jpa/0g0k
796
// if (shouldRetrieveFromCache())
797
entity = getEntity(cl.getName(), key);
798
799     if (entity != null)
800       return entity;
801
802     AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl.getName());
803
804     if (entityHome == null)
805       return null;
806     else {
807       try {
808         entityHome.init();
809       } catch (ConfigException e) {
810         throw new AmberException(e);
811       }
812
813       entity = entityHome.load(this, key, preloadedProperties);
814
815       if (entity == null)
816         return null;
817
818       addEntity(entity);
819
820       return entity;
821     }
822   }
823
824   /**
825    * Loads the object based on the class and primary key.
826    */

827   public Object JavaDoc load(String JavaDoc entityName,
828                      Object JavaDoc key)
829     throws AmberException
830   {
831     AmberEntityHome entityHome = _persistenceUnit.getEntityHome(entityName);
832
833     if (entityHome == null)
834       return null;
835
836     Entity entity = null;
837
838     // XXX: ejb/0d01
839
// jpa/0y14 if (shouldRetrieveFromCache())
840
entity = getEntity(entityName, key);
841
842     if (entity != null)
843       return entity;
844
845     try {
846       entityHome.init();
847     } catch (ConfigException e) {
848       throw new AmberException(e);
849     }
850
851     entity = entityHome.load(this, key);
852
853     addEntity(entity);
854
855     return entity;
856   }
857
858   /**
859    * Returns the entity for the connection.
860    */

861   public Entity getEntity(EntityItem item)
862   {
863     return getEntity(item, null);
864   }
865
866   /**
867    * Returns the entity for the connection.
868    */

869   public Entity getEntity(EntityItem item, Map JavaDoc preloadedProperties)
870   {
871     Entity itemEntity = item.getEntity();
872     EntityType entityType = itemEntity.__caucho_getEntityType();
873
874     Entity entity = getEntity(entityType.getBeanClass().getName(),
875                               itemEntity.__caucho_getPrimaryKey());
876
877     if (entity != null)
878       return entity;
879     else {
880       entity = item.copy(this);
881
882       addEntity(entity);
883
884       return entity;
885     }
886   }
887
888   /**
889    * Loads the object based on itself.
890    */

891   public Object JavaDoc makePersistent(Object JavaDoc obj)
892     throws SQLException JavaDoc
893   {
894     Entity entity = (Entity) obj;
895
896     // check to see if exists
897

898     if (entity == null)
899       throw new NullPointerException JavaDoc();
900
901     Class JavaDoc cl = entity.getClass();
902
903     // Entity oldEntity = getEntity(cl, entity.__caucho_getPrimaryKey());
904

905     AmberEntityHome entityHome;
906     entityHome = _persistenceUnit.getEntityHome(entity.getClass().getName());
907
908     if (entityHome == null)
909       throw new AmberException(L.l("entity has no matching home"));
910
911     entityHome.makePersistent(entity, this, false);
912
913     return entity;
914   }
915
916   /**
917    * Loads the object with the given class.
918    */

919   public Entity loadLazy(Class JavaDoc cl, String JavaDoc name, Object JavaDoc key)
920   {
921     return loadLazy(cl.getName(), name, key);
922   }
923
924   /**
925    * Loads the object with the given class.
926    */

927   public Entity loadLazy(String JavaDoc className, String JavaDoc name, Object JavaDoc key)
928   {
929     if (key == null)
930       return null;
931
932     Entity entity = null;
933
934     // XXX: ejb/0d01
935
// jpa/0y14 if (shouldRetrieveFromCache())
936
entity = getEntity(className, key);
937
938     try {
939       AmberEntityHome home = _persistenceUnit.getEntityHome(name);
940
941       if (home == null)
942         throw new RuntimeException JavaDoc(L.l("no matching home for {0}", className));
943
944       home.init();
945
946       Object JavaDoc obj = home.loadLazy(this, key);
947
948       entity = (Entity) obj;
949
950       addEntity(entity);
951
952       return entity;
953     } catch (SQLException JavaDoc e) {
954       log.log(Level.WARNING, e.toString(), e);
955
956       return null;
957     } catch (ConfigException e) {
958       throw new AmberRuntimeException(e);
959     }
960   }
961
962   /**
963    * Loads the object with the given class.
964    */

965   public EntityItem findEntityItem(String JavaDoc name, Object JavaDoc key)
966   {
967     try {
968       AmberEntityHome home = _persistenceUnit.getEntityHome(name);
969
970       if (home == null)
971         throw new RuntimeException JavaDoc(L.l("no matching home for {0}", name));
972
973       home.init();
974
975       return home.findEntityItem(_persistenceUnit.getCacheConnection(), key, false);
976     } catch (RuntimeException JavaDoc e) {
977       throw e;
978     } catch (Exception JavaDoc e) {
979       throw new AmberRuntimeException(e);
980     }
981   }
982
983   /**
984    * Loads the object with the given class.
985    */

986   public EntityItem setEntityItem(String JavaDoc name, Object JavaDoc key, EntityItem item)
987   {
988     try {
989       AmberEntityHome home = _persistenceUnit.getEntityHome(name);
990
991       if (home == null)
992         throw new RuntimeException JavaDoc(L.l("no matching home for {0}", name));
993
994       home.init();
995
996       return home.setEntityItem(key, item);
997     } catch (RuntimeException JavaDoc e) {
998       throw e;
999     } catch (Exception JavaDoc e) {
1000      throw new AmberRuntimeException(e);
1001    }
1002  }
1003
1004  /**
1005   * Loads the object with the given class.
1006   */

1007  public Object JavaDoc loadProxy(String JavaDoc name, Object JavaDoc key)
1008  {
1009    return loadProxy(name, key, null);
1010  }
1011
1012  /**
1013   * Loads the object with the given class.
1014   */

1015  public Object JavaDoc loadProxy(String JavaDoc name,
1016                          Object JavaDoc key,
1017                          Map JavaDoc preloadedProperties)
1018  {
1019    if (key == null)
1020      return null;
1021
1022    AmberEntityHome home = _persistenceUnit.getEntityHome(name);
1023
1024    if (home == null)
1025      throw new RuntimeException JavaDoc(L.l("no matching home for {0}", name));
1026
1027    return loadProxy(home.getEntityType(), key, preloadedProperties);
1028  }
1029
1030  /**
1031   * Loads the object with the given class.
1032   */

1033  public Object JavaDoc loadProxy(EntityType type,
1034                          Object JavaDoc key)
1035  {
1036    return loadProxy(type, key, null);
1037  }
1038
1039  /**
1040   * Loads the object with the given class.
1041   */

1042  public Object JavaDoc loadProxy(EntityType type,
1043                          Object JavaDoc key,
1044                          Map JavaDoc preloadedProperties)
1045  {
1046    if (key == null)
1047      return null;
1048
1049    try {
1050      AmberEntityHome home = type.getHome();
1051
1052      EntityItem item = home.findEntityItem(this, key, false, preloadedProperties);
1053
1054      if (item == null)
1055        return null;
1056
1057      EntityFactory factory = home.getEntityFactory();
1058
1059      Object JavaDoc entity = factory.getEntity(this, item, preloadedProperties);
1060
1061      return entity;
1062    } catch (SQLException JavaDoc e) {
1063      log.log(Level.WARNING, e.toString(), e);
1064
1065      return null;
1066    }
1067  }
1068
1069
1070  /**
1071   * Loads the object based on the class and primary key.
1072   */

1073  public Object JavaDoc load(Class JavaDoc cl, long intKey)
1074    throws AmberException
1075  {
1076    AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl.getName());
1077
1078    if (entityHome == null)
1079      return null;
1080
1081    Object JavaDoc key = entityHome.toObjectKey(intKey);
1082
1083    return load(cl, key);
1084  }
1085
1086  /**
1087   * Loads the object based on the class and primary key.
1088   */

1089  public Object JavaDoc loadLazy(Class JavaDoc cl, long intKey)
1090    throws AmberException
1091  {
1092    AmberEntityHome entityHome = _persistenceUnit.getEntityHome(cl.getName());
1093
1094    if (entityHome == null)
1095      return null;
1096
1097    Object JavaDoc key = entityHome.toObjectKey(intKey);
1098
1099    return loadLazy(cl, cl.getName(), key);
1100  }
1101
1102  /**
1103   * Matches the entity.
1104   */

1105  public Entity getEntity(String JavaDoc className, Object JavaDoc key)
1106  {
1107    for (int i = _entities.size() - 1; i >= 0; i--) {
1108      Entity entity = _entities.get(i);
1109
1110      if (entity.__caucho_match(className, key)) {
1111        return entity;
1112      }
1113    }
1114
1115    return null;
1116  }
1117
1118  private Entity getTransactionEntity(String JavaDoc className, Object JavaDoc key)
1119  {
1120    for (int i = _txEntities.size() - 1; i >= 0; i--) {
1121      Entity entity = _txEntities.get(i);
1122
1123      if (entity.__caucho_match(className, key)) {
1124        return entity;
1125      }
1126    }
1127
1128    return null;
1129  }
1130
1131  /**
1132   * Adds an entity.
1133   */

1134  public boolean addEntity(Entity entity)
1135  {
1136    boolean added = false;
1137
1138    Entity oldEntity = getEntity(entity.getClass().getName(),
1139                                 entity.__caucho_getPrimaryKey());
1140
1141    // jpa/0s2d: if (! _entities.contains(entity)) {
1142
if (oldEntity == null) {
1143      _entities.add(entity);
1144      added = true;
1145    }
1146
1147    // jpa/0g06
1148
if (_isInTransaction) {
1149      oldEntity = getTransactionEntity(entity.getClass().getName(),
1150                                       entity.__caucho_getPrimaryKey());
1151
1152      // jpa/0s2d: if (! _txEntities.contains(entity)) {
1153
if (oldEntity == null) {
1154        _txEntities.add(entity);
1155        added = true;
1156      }
1157    }
1158
1159    return added;
1160  }
1161
1162  /**
1163   * Removes an entity.
1164   */

1165  public boolean removeEntity(Entity entity)
1166  {
1167    _entities.remove(entity);
1168
1169    if (_isInTransaction)
1170      _txEntities.remove(entity);
1171
1172    return true;
1173  }
1174
1175  /**
1176   * Loads the object based on itself.
1177   */

1178  public boolean contains(Object JavaDoc obj)
1179  {
1180    if (obj == null)
1181      return false;
1182
1183    if (! (obj instanceof Entity))
1184      throw new IllegalArgumentException JavaDoc(L.l("contains() operation can only be applied to an entity instance."));
1185
1186    Entity entity = (Entity) obj;
1187
1188    entity = getEntity(entity.getClass().getName(),
1189                       entity.__caucho_getPrimaryKey());
1190
1191    if (entity == null)
1192      return false;
1193
1194    if (entity.__caucho_getEntityState() >= Entity.P_DELETING)
1195      return false;
1196
1197    return true;
1198  }
1199
1200  /**
1201   * Callback when the user transaction begins
1202   */

1203  public void begin(Transaction xa)
1204  {
1205    try {
1206      xa.registerSynchronization(this);
1207
1208      _isInTransaction = true;
1209      _isXA = true;
1210    } catch (Throwable JavaDoc e) {
1211      log.log(Level.WARNING, e.toString(), e);
1212    }
1213  }
1214
1215  /**
1216   * Starts a transaction.
1217   */

1218  public void beginTransaction()
1219    throws SQLException JavaDoc
1220  {
1221    _isInTransaction = true;
1222
1223    if (_conn != null && _isAutoCommit) {
1224      _isAutoCommit = false;
1225      _conn.setAutoCommit(false);
1226    }
1227
1228    // _xid = _factory.getXid();
1229
}
1230
1231  /**
1232   * Sets XA.
1233   */

1234  public void setXA(boolean isXA)
1235  {
1236    _isXA = isXA;
1237    _isInTransaction = isXA;
1238  }
1239
1240  /**
1241   * Commits a transaction.
1242   */

1243  public void commit()
1244    throws SQLException JavaDoc
1245  {
1246    try {
1247      flushInternal();
1248
1249      _xid = 0;
1250      if (_conn != null) {
1251        _conn.commit();
1252      }
1253    }
1254    catch (RuntimeException JavaDoc e) {
1255      throw e;
1256    }
1257    catch (SQLException JavaDoc e) {
1258      throw new IllegalStateException JavaDoc(e);
1259    }
1260    catch (Exception JavaDoc e) {
1261      throw new EJBExceptionWrapper(e);
1262    }
1263    finally {
1264      if (! _isXA)
1265        _isInTransaction = false;
1266
1267      for (int i = 0; i < _txEntities.size(); i++) {
1268        Entity entity = _txEntities.get(i);
1269
1270        entity.__caucho_afterCommit();
1271      }
1272
1273      _txEntities.clear();
1274    }
1275  }
1276
1277  /**
1278   * Callback before a utrans commit.
1279   */

1280  public void beforeCompletion()
1281  {
1282    try {
1283      beforeCommit();
1284    } catch (Exception JavaDoc e) {
1285      log.log(Level.WARNING, e.toString(), e);
1286    }
1287  }
1288
1289  /**
1290   * Callback after a utrans commit.
1291   */

1292  public void afterCompletion(int status)
1293  {
1294    afterCommit(status == Status.STATUS_COMMITTED);
1295    _isXA = false;
1296    _isInTransaction = false;
1297  }
1298
1299  /**
1300   * Commits a transaction.
1301   */

1302  public void beforeCommit()
1303    throws SQLException JavaDoc
1304  {
1305    // jpa/0gh0
1306
for (int i = _txEntities.size() - 1; i >= 0; i--) {
1307      Entity entity = _txEntities.get(i);
1308
1309      entity.__caucho_flush();
1310    }
1311  }
1312
1313  /**
1314   * Commits a transaction.
1315   */

1316  public void afterCommit(boolean isCommit)
1317  {
1318    if (! _isXA)
1319      _isInTransaction = false;
1320
1321    if (isCommit) {
1322      if (_completionList.size() > 0) {
1323        _persistenceUnit.complete(_completionList);
1324      }
1325    }
1326    _completionList.clear();
1327
1328    for (int i = 0; i < _txEntities.size(); i++) {
1329      Entity entity = _txEntities.get(i);
1330
1331      try {
1332        if (isCommit)
1333          entity.__caucho_afterCommit();
1334        else
1335          entity.__caucho_afterRollback();
1336      } catch (Throwable JavaDoc e) {
1337        log.log(Level.WARNING, e.toString(), e);
1338      }
1339    }
1340
1341    _txEntities.clear();
1342
1343    if (! isCommit) {
1344      // jpa/0j5c
1345
_entities.clear();
1346
1347      try {
1348        if (_conn != null)
1349          _conn.rollback();
1350      } catch (SQLException JavaDoc e) {
1351        throw new IllegalStateException JavaDoc(e);
1352      }
1353    }
1354  }
1355
1356  /**
1357   * Rollbacks a transaction.
1358   */

1359  public void rollback()
1360    throws SQLException JavaDoc
1361  {
1362    try {
1363      flushInternal();
1364
1365      _xid = 0;
1366      if (_conn != null) {
1367        _conn.rollback();
1368      }
1369    }
1370    catch (RuntimeException JavaDoc e) {
1371      throw e;
1372    }
1373    catch (SQLException JavaDoc e) {
1374      throw new IllegalStateException JavaDoc(e);
1375    }
1376    catch (Exception JavaDoc e) {
1377      throw new EJBExceptionWrapper(e);
1378    }
1379    finally {
1380      if (! _isXA)
1381        _isInTransaction = false;
1382
1383      _completionList.clear();
1384
1385      for (int i = 0; i < _txEntities.size(); i++) {
1386        Entity entity = _txEntities.get(i);
1387
1388        entity.__caucho_afterRollback();
1389      }
1390
1391      _txEntities.clear();
1392    }
1393  }
1394
1395  /**
1396   * Flushes managed entities.
1397   */

1398  public void flush()
1399  {
1400    try {
1401      checkTransactionRequired("flush");
1402
1403      flushInternal();
1404
1405    } catch (RuntimeException JavaDoc e) {
1406      throw e;
1407    } catch (SQLException JavaDoc e) {
1408      throw new IllegalStateException JavaDoc(e);
1409    } catch (Exception JavaDoc e) {
1410      throw new EJBExceptionWrapper(e);
1411    }
1412  }
1413
1414  /**
1415   * Flushes managed entities.
1416   */

1417  public void flushNoChecks()
1418  {
1419    try {
1420      flushInternal();
1421
1422    } catch (RuntimeException JavaDoc e) {
1423      throw e;
1424    } catch (SQLException JavaDoc e) {
1425      throw new IllegalStateException JavaDoc(e);
1426    } catch (Exception JavaDoc e) {
1427      throw new EJBExceptionWrapper(e);
1428    }
1429  }
1430
1431  /**
1432   * Expires the entities
1433   */

1434  public void expire()
1435    throws SQLException JavaDoc
1436  {
1437    for (int i = 0; i < _entities.size(); i++) {
1438      Entity entity = _entities.get(i);
1439
1440      entity.__caucho_expire();
1441    }
1442  }
1443
1444  /**
1445   * Returns the connection.
1446   */

1447  public Connection JavaDoc getConnection()
1448    throws SQLException JavaDoc
1449  {
1450    DataSource JavaDoc readDataSource = _persistenceUnit.getReadDataSource();
1451
1452    if (! _isXA && ! _isInTransaction && readDataSource != null) {
1453      if (_readConn == null) {
1454        _readConn = readDataSource.getConnection();
1455      }
1456      else if (_readConn.isClosed()) {
1457        closeConnectionImpl();
1458        _readConn = _persistenceUnit.getDataSource().getConnection();
1459      }
1460
1461      return _readConn;
1462    }
1463
1464    if (_conn == null) {
1465      _conn = _persistenceUnit.getDataSource().getConnection();
1466      _isAutoCommit = true;
1467    }
1468    else if (_conn.isClosed()) {
1469      closeConnectionImpl();
1470      _conn = _persistenceUnit.getDataSource().getConnection();
1471      _isAutoCommit = true;
1472    }
1473
1474    if (_isXA) {
1475    }
1476    else if (_isInTransaction && _isAutoCommit) {
1477      _isAutoCommit = false;
1478      _conn.setAutoCommit(false);
1479    }
1480    else if (! _isInTransaction && ! _isAutoCommit) {
1481      _isAutoCommit = true;
1482      _conn.setAutoCommit(true);
1483    }
1484
1485    return _conn;
1486  }
1487
1488  /**
1489   * Prepares a statement.
1490   */

1491  public PreparedStatement JavaDoc prepareStatement(String JavaDoc sql)
1492    throws SQLException JavaDoc
1493  {
1494    try {
1495      Connection JavaDoc conn = getConnection();
1496
1497      PreparedStatement JavaDoc pstmt = _preparedStatementMap.get(sql);
1498
1499      if (pstmt == null) {
1500        pstmt = conn.prepareStatement(sql);
1501
1502        _statements.add(pstmt);
1503
1504        _preparedStatementMap.put(sql, pstmt);
1505      }
1506
1507      return pstmt;
1508    } catch (SQLException JavaDoc e) {
1509      closeConnectionImpl();
1510
1511      throw e;
1512    }
1513  }
1514
1515  /**
1516   * Prepares an insert statement.
1517   */

1518  public PreparedStatement JavaDoc prepareInsertStatement(String JavaDoc sql)
1519    throws SQLException JavaDoc
1520  {
1521    PreparedStatement JavaDoc pstmt = _preparedStatementMap.get(sql);
1522
1523    if (pstmt == null) {
1524      Connection JavaDoc conn = getConnection();
1525
1526      if (_persistenceUnit.hasReturnGeneratedKeys())
1527        pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
1528      else
1529        pstmt = conn.prepareStatement(sql);
1530
1531      _statements.add(pstmt);
1532
1533      _preparedStatementMap.put(sql, pstmt);
1534    }
1535
1536    return pstmt;
1537  }
1538
1539  /**
1540   * Makes the object transactional.
1541   *
1542   * @param obj the object to save
1543   *
1544   * @return the proxy for the saved object
1545   */

1546  public void makeTransactional(Entity entity)
1547  {
1548    // ejb/0600
1549
if (! _persistenceUnit.isJPA())
1550      return;
1551
1552    int state = entity.__caucho_getEntityState();
1553
1554    if (state > Entity.TRANSIENT && state < Entity.P_DELETING) {
1555      // jpa/0g06
1556
addEntity(entity);
1557    }
1558
1559    /*
1560      if (! isInTransaction())
1561      throw new AmberRuntimeException(L.l("makePersistent must be called from within a transaction."));
1562
1563      if (! (obj instanceof Entity)) {
1564      throw new AmberRuntimeException(L.l("`{0}' is not a known entity class.",
1565      obj.getClass().getName()));
1566      }
1567    */

1568  }
1569
1570  /**
1571   * Updates the database with the values in object. If the object does
1572   * not exist, throws an exception.
1573   *
1574   * @param obj the object to update
1575   */

1576  public void update(Object JavaDoc obj)
1577  {
1578    /*
1579      for (int i = _entities.size() - 1; i >= 0; i--) {
1580      Entity entity = _entities.get(i);
1581
1582      if (entity.__caucho_match(obj)) {
1583      entity.__caucho_load(obj);
1584
1585      return entity;
1586      }
1587      }
1588    */

1589
1590    /*
1591      Class cl = obj.getClass();
1592
1593      EntityHome home = _factory.getHome(cl);
1594
1595      if (home == null)
1596      throw new AmberException(L.l("no matching home for {0}", cl.getName()));
1597
1598      Object key = home.getKeyFromEntity(obj);
1599
1600      Entity entity = getEntity(cl, key);
1601
1602      if (entity == null) {
1603      entity = home.load(this, key);
1604
1605      addEntity(entity);
1606      }
1607
1608      entity.__caucho_loadFromObject(obj);
1609
1610      return entity;
1611    */

1612  }
1613
1614  /**
1615   * Saves the object.
1616   *
1617   * @param obj the object to create
1618   */

1619  public void create(Object JavaDoc obj)
1620    throws SQLException JavaDoc
1621  {
1622    // ejb/0g22 exception handling
1623
try {
1624
1625      createInternal(obj);
1626
1627    } catch (RuntimeException JavaDoc e) {
1628      throw e;
1629    } catch (Exception JavaDoc e) {
1630      throw new EJBExceptionWrapper(e);
1631    }
1632  }
1633
1634  /**
1635   * Saves the object.
1636   *
1637   * @param obj the object to create
1638   */

1639  public void create(String JavaDoc homeName, Object JavaDoc obj)
1640    throws SQLException JavaDoc
1641  {
1642    // ejb/0g22 exception handling
1643
try {
1644
1645      createInternal(homeName, obj);
1646
1647    } catch (RuntimeException JavaDoc e) {
1648      throw e;
1649    } catch (Exception JavaDoc e) {
1650      throw new EJBExceptionWrapper(e);
1651    }
1652  }
1653
1654  /**
1655   * Saves the object.
1656   *
1657   * @param obj the object to create
1658   */

1659  public void create(AmberEntityHome home, Object JavaDoc obj)
1660    throws SQLException JavaDoc
1661  {
1662    // ejb/0g22 exception handling
1663
try {
1664
1665      createInternal(home, obj);
1666
1667    } catch (RuntimeException JavaDoc e) {
1668      throw e;
1669    } catch (Exception JavaDoc e) {
1670      throw new EJBExceptionWrapper(e);
1671    }
1672  }
1673
1674  /**
1675   * Updates the object.
1676   */

1677  public void update(Entity entity)
1678  {
1679    if (entity == null)
1680      return;
1681
1682    // jpa/0g0i
1683
if (entity.__caucho_getEntityType() == null)
1684      return;
1685
1686    Table table = entity.__caucho_getEntityType().getTable();
1687
1688    Object JavaDoc key = entity.__caucho_getPrimaryKey();
1689
1690    addCompletion(new RowInvalidateCompletion(table.getName(), key));
1691
1692    if (! _txEntities.contains(entity))
1693      _txEntities.add(entity);
1694  }
1695
1696  /**
1697   * Deletes the object.
1698   *
1699   * @param obj the object to delete
1700   */

1701  public void delete(Entity entity)
1702    throws SQLException JavaDoc
1703  {
1704    Entity oldEntity = getEntity(entity.getClass().getName(),
1705                                 entity.__caucho_getPrimaryKey());
1706
1707    if (oldEntity == null) {
1708
1709      EntityType entityType = entity.__caucho_getEntityType();
1710
1711      if (entityType == null)
1712        return;
1713      // throw new AmberException(L.l("entity has no entityType"));
1714

1715      AmberEntityHome entityHome = entityType.getHome();
1716      //entityHome = _persistenceUnit.getEntityHome(entity.getClass().getName());
1717

1718      if (entityHome == null)
1719        throw new AmberException(L.l("entity has no matching home"));
1720
1721      entityHome.makePersistent(entity, this, true);
1722
1723      addEntity(entity);
1724    }
1725    else {
1726      // XXX: jpa/0k12
1727
oldEntity.__caucho_setConnection(this);
1728
1729      entity = oldEntity;
1730    }
1731
1732    entity.__caucho_delete();
1733  }
1734
1735  /**
1736   * Creates a query object from a query string.
1737   *
1738   * @param query a Hibernate query
1739   */

1740  public AmberQuery prepareQuery(String JavaDoc queryString)
1741    throws AmberException
1742  {
1743    return prepareQuery(queryString, false);
1744  }
1745
1746  /**
1747   * Creates a query object from a query string.
1748   *
1749   * @param query a Hibernate query
1750   */

1751  public AmberQuery prepareLazyQuery(String JavaDoc queryString)
1752    throws AmberException
1753  {
1754    return prepareQuery(queryString, true);
1755  }
1756
1757  /**
1758   * Creates a query object from a query string.
1759   *
1760   * @param query a Hibernate query
1761   */

1762  public AmberQuery prepareUpdate(String JavaDoc queryString)
1763    throws AmberException
1764  {
1765    return prepareQuery(queryString, true);
1766  }
1767
1768  /**
1769   * Creates a query object from a query string.
1770   *
1771   * @param query a Hibernate query
1772   */

1773  private AmberQuery prepareQuery(String JavaDoc queryString, boolean isLazy)
1774    throws AmberException
1775  {
1776    AbstractQuery queryProgram = parseQuery(queryString, isLazy);
1777
1778    UserQuery query = new UserQuery(queryProgram);
1779
1780    query.setSession(this);
1781
1782    return query;
1783  }
1784
1785  /**
1786   * Creates a query object from a query string.
1787   *
1788   * @param query a Hibernate query
1789   */

1790  public AbstractQuery parseQuery(String JavaDoc queryString, boolean isLazy)
1791    throws AmberException
1792  {
1793    try {
1794      _persistenceUnit.initEntityHomes();
1795    } catch (Exception JavaDoc e) {
1796      throw AmberRuntimeException.create(e);
1797    }
1798
1799    QueryParser parser = new QueryParser(queryString);
1800
1801    parser.setAmberManager(_persistenceUnit);
1802    parser.setLazyResult(isLazy);
1803
1804    return parser.parse();
1805  }
1806
1807  /**
1808   * Select a list of objects with a Hibernate query.
1809   *
1810   * @param query the hibernate query
1811   *
1812   * @return the query results.
1813   */

1814  public ResultSet JavaDoc query(String JavaDoc hsql)
1815    throws SQLException JavaDoc
1816  {
1817    AmberQuery query = prepareQuery(hsql);
1818
1819    return query.executeQuery();
1820  }
1821
1822  /**
1823   * Returns the cache chunk.
1824   *
1825   * @param sql the SQL for the cache chunk
1826   * @param args the filled parameters for the cache chunk
1827   * @param startRow the starting row for the cache chunk
1828   */

1829  public ResultSetCacheChunk getQueryCacheChunk(String JavaDoc sql,
1830                                                Object JavaDoc []args,
1831                                                int startRow)
1832  {
1833    _queryKey.init(sql, args, startRow);
1834
1835    return _persistenceUnit.getQueryChunk(_queryKey);
1836  }
1837
1838  /**
1839   * Returns the result set meta data from cache.
1840   */

1841  public ResultSetMetaData JavaDoc getQueryMetaData()
1842  {
1843    return _persistenceUnit.getQueryMetaData(_queryKey);
1844  }
1845
1846  /**
1847   * Sets the cache chunk.
1848   *
1849   * @param sql the SQL for the cache chunk
1850   * @param args the filled parameters for the cache chunk
1851   * @param startRow the starting row for the cache chunk
1852   * @param cacheChunk the new value of the cache chunk
1853   */

1854  public void putQueryCacheChunk(String JavaDoc sql,
1855                                 Object JavaDoc []args,
1856                                 int startRow,
1857                                 ResultSetCacheChunk cacheChunk,
1858                                 ResultSetMetaData JavaDoc cacheMetaData)
1859  {
1860    QueryCacheKey key = new QueryCacheKey();
1861    Object JavaDoc []newArgs = new Object JavaDoc[args.length];
1862
1863    System.arraycopy(args, 0, newArgs, 0, args.length);
1864
1865    key.init(sql, newArgs, startRow);
1866
1867    _persistenceUnit.putQueryChunk(key, cacheChunk);
1868    _persistenceUnit.putQueryMetaData(key, cacheMetaData);
1869  }
1870
1871  /**
1872   * Updates the database with a query
1873   *
1874   * @param query the hibernate query
1875   *
1876   * @return the query results.
1877   */

1878  public int update(String JavaDoc hsql)
1879    throws SQLException JavaDoc
1880  {
1881    AmberQuery query = prepareUpdate(hsql);
1882
1883    return query.executeUpdate();
1884  }
1885
1886  /**
1887   * Select a list of objects with a Hibernate query.
1888   *
1889   * @param query the hibernate query
1890   *
1891   * @return the query results.
1892   */

1893  public List JavaDoc find(String JavaDoc hsql)
1894    throws SQLException JavaDoc
1895  {
1896    AmberQuery query = prepareQuery(hsql);
1897
1898    return query.list();
1899  }
1900
1901  /**
1902   * Cleans up the connection.
1903   */

1904  public void cleanup()
1905  {
1906    try {
1907      flushInternal();
1908    }
1909    catch (RuntimeException JavaDoc e) {
1910      throw e;
1911    }
1912    catch (SQLException JavaDoc e) {
1913      throw new IllegalStateException JavaDoc(e);
1914    }
1915    catch (Exception JavaDoc e) {
1916      throw new EJBExceptionWrapper(e);
1917    }
1918    finally {
1919      _depth = 0;
1920
1921      for (int i = _entities.size() - 1; i >= 0; i--) {
1922        _entities.get(i).__caucho_detach();
1923      }
1924
1925      _entities.clear();
1926      _txEntities.clear();
1927      _completionList.clear();
1928
1929      freeConnection();
1930    }
1931  }
1932
1933  /**
1934   * Pushes the depth.
1935   */

1936  public void pushDepth()
1937  {
1938    // these aren't necessary because the AmberConnection is added as
1939
// a close callback to the UserTransaction
1940
}
1941
1942  /**
1943   * Pops the depth.
1944   */

1945  public void popDepth()
1946  {
1947  }
1948
1949  /**
1950   * Frees the connection.
1951   */

1952  public void freeConnection()
1953  {
1954    closeConnectionImpl();
1955  }
1956
1957  /**
1958   * Frees the connection.
1959   */

1960  private void closeConnectionImpl()
1961  {
1962    Connection JavaDoc conn = _conn;
1963    _conn = null;
1964
1965    Connection JavaDoc readConn = _readConn;
1966    _readConn = null;
1967
1968    boolean isAutoCommit = _isAutoCommit;
1969    _isAutoCommit = true;
1970
1971    try {
1972      if (conn != null && ! isAutoCommit)
1973        conn.setAutoCommit(true);
1974    } catch (SQLException JavaDoc e) {
1975    }
1976
1977    try {
1978      _preparedStatementMap.clear();
1979      _statements.clear();
1980
1981      if (conn != null)
1982        conn.close();
1983
1984      if (readConn != null)
1985        readConn.close();
1986    } catch (Exception JavaDoc e) {
1987      log.log(Level.WARNING, e.toString(), e);
1988    }
1989  }
1990
1991  public String JavaDoc toString()
1992  {
1993    if (_persistenceUnit != null)
1994      return "AmberConnection[" + _persistenceUnit.getName() + "]";
1995    else
1996      return "AmberConnection[closed]";
1997  }
1998
1999  /**
2000   * Finalizer.
2001   */

2002  public void finalize()
2003  {
2004    cleanup();
2005  }
2006
2007  /**
2008   * Returns true when cache items can be used.
2009   */

2010  public boolean shouldRetrieveFromCache()
2011  {
2012    // ejb/0d01
2013
return (! isInTransaction());
2014  }
2015
2016  //
2017
// private
2018
//
2019
// throws Exception (for jpa)
2020
//
2021
// ejb/0g22 (cmp) expects exception handling in
2022
// the public methods. See public void create(Object) above.
2023

2024  /**
2025   * Saves the object.
2026   *
2027   * @param obj the object to create
2028   */

2029  private void createInternal(Object JavaDoc obj)
2030    throws Exception JavaDoc
2031  {
2032    AmberEntityHome home = null;
2033
2034    Class JavaDoc cl = obj.getClass();
2035
2036    for (; home == null && cl != null; cl = cl.getSuperclass()) {
2037      home = _persistenceUnit.getHome(cl);
2038    }
2039
2040    if (home == null)
2041      throw new AmberException(L.l("`{0}' is not a known entity class.",
2042                                   obj.getClass().getName()));
2043
2044    createInternal(home, obj);
2045  }
2046
2047  /**
2048   * Saves the object.
2049   *
2050   * @param obj the object to create
2051   */

2052  private void createInternal(String JavaDoc homeName, Object JavaDoc obj)
2053    throws Exception JavaDoc
2054  {
2055    AmberEntityHome home = _persistenceUnit.getEntityHome(homeName);
2056
2057    if (home == null)
2058      throw new AmberException(L.l("`{0}' is not a known entity class.",
2059                                   obj.getClass().getName()));
2060
2061    createInternal(home, obj);
2062  }
2063
2064  /**
2065   * Saves the object.
2066   *
2067   * @param obj the object to create
2068   */

2069  private void createInternal(AmberEntityHome home, Object JavaDoc obj)
2070    throws Exception JavaDoc
2071  {
2072    // XXX: flushing things like delete might be useful?
2073
// XXX: the issue is a flush can break FK constraints and
2074
// fail prematurely (jpa/0h26).
2075
// commented out: flushInternal();
2076

2077    if (contains(obj))
2078      return;
2079
2080    Entity entity = (Entity) obj;
2081
2082    // jpa/0g0k: cannot call home.save because of jpa exception handling.
2083
if (_persistenceUnit.isJPA())
2084      entity.__caucho_create(this, home.getEntityType());
2085    else
2086      home.save(this, entity);
2087
2088    addEntity(entity);
2089
2090    Table table = home.getEntityType().getTable();
2091    addCompletion(new TableInvalidateCompletion(table.getName()));
2092  }
2093
2094  private void checkTransactionRequired(String JavaDoc operation)
2095    throws TransactionRequiredException
2096  {
2097    // XXX: also needs to check PersistenceContextType.TRANSACTION/EXTENDED.
2098

2099    if (! (_isXA || _isInTransaction))
2100      throw new TransactionRequiredException(L.l("{0}() operation can only be executed in the scope of a transaction.", operation));
2101  }
2102
2103  /**
2104   * Flush managed entities.
2105   */

2106  private void flushInternal()
2107    throws Exception JavaDoc
2108  {
2109    for (int i = _txEntities.size() - 1; i >= 0; i--) {
2110      Entity entity = _txEntities.get(i);
2111
2112      int state = entity.__caucho_getEntityState();
2113
2114      // jpa/0h27: for all entities Y referenced by a *managed*
2115
// entity X, where the relationship has been annotated
2116
// with cascade=PERSIST/ALL, the persist operation is
2117
// applied to Y. It is a lazy cascade as the relationship
2118
// is not always initialized at the time persist(X) was
2119
// called but must be at flush time.
2120
if (state < Entity.P_DELETING) {
2121        entity.__caucho_cascadePrePersist(this);
2122        // entity.__caucho_cascadePostPersist(this);
2123
}
2124    }
2125
2126    for (int i = _txEntities.size() - 1; i >= 0; i--) {
2127      Entity entity = _txEntities.get(i);
2128
2129      entity.__caucho_flush();
2130    }
2131
2132    if (! isInTransaction()) {
2133      if (_completionList.size() > 0) {
2134        _persistenceUnit.complete(_completionList);
2135      }
2136      _completionList.clear();
2137
2138      for (int i = 0; i < _txEntities.size(); i++) {
2139        Entity entity = _txEntities.get(i);
2140
2141        entity.__caucho_afterCommit();
2142      }
2143
2144      _txEntities.clear();
2145    }
2146  }
2147
2148  /**
2149   * Persists the entity.
2150   */

2151  public void persistInternal(Object JavaDoc entity)
2152    throws Exception JavaDoc
2153  {
2154    Entity instance = (Entity) entity;
2155
2156    // jpa/0h24
2157
// Pre-persist child entities.
2158
instance.__caucho_cascadePrePersist(this);
2159
2160    int state = instance.__caucho_getEntityState();
2161
2162    if (state == Entity.TRANSIENT) {
2163      createInternal(instance);
2164    }
2165    else if (state >= Entity.P_DELETING) {
2166      // removed entity instance, reset state and persist.
2167
instance.__caucho_makePersistent(null, (EntityType) null);
2168      createInternal(instance);
2169    }
2170    else // jpa/0ga5
2171
throw new EntityExistsException(L.l("Trying to persist an entity that is detached or already exists. Entity state '{0}'", state));
2172
2173    // jpa/0h27
2174
// Post-persist child entities.
2175
instance.__caucho_cascadePostPersist(this);
2176  }
2177
2178  /**
2179   * Creates an instance of the native query.
2180   */

2181  private Query createInternalNativeQuery(String JavaDoc sql,
2182                                          SqlResultSetMappingConfig map)
2183  {
2184    Query query = createNativeQuery(sql);
2185
2186    QueryImpl queryImpl = (QueryImpl) query;
2187
2188    queryImpl.setSqlResultSetMapping(map);
2189
2190    return query;
2191  }
2192
2193  private class EntityTransactionImpl implements EntityTransaction {
2194    /**
2195     * Starts a resource transaction.
2196     */

2197    public void begin()
2198    {
2199      try {
2200        AmberConnection.this.beginTransaction();
2201      } catch (SQLException JavaDoc e) {
2202        throw new PersistenceException(e);
2203      }
2204    }
2205
2206    /**
2207     * Commits a resource transaction.
2208     */

2209    public void commit()
2210    {
2211      try {
2212        AmberConnection.this.commit();
2213      } catch (SQLException JavaDoc e) {
2214        throw new PersistenceException(e);
2215      }
2216    }
2217
2218    /**
2219     * Rolls the current transaction back.
2220     */

2221    public void rollback()
2222    {
2223      try {
2224        AmberConnection.this.rollback();
2225      } catch (SQLException JavaDoc e) {
2226        throw new PersistenceException(e);
2227      }
2228    }
2229
2230    /**
2231     * Marks the current transaction for rollback only.
2232     */

2233    public void setRollbackOnly()
2234    {
2235    }
2236
2237    /**
2238     * Returns true if the transaction is for rollback only.
2239     */

2240    public boolean getRollbackOnly()
2241    {
2242      return false;
2243    }
2244
2245    /**
2246     * Test if a transaction is in progress.
2247     */

2248    public boolean isActive()
2249    {
2250      return _isInTransaction;
2251    }
2252  }
2253}
2254
Popular Tags