001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.persistence;
018:
019: import java.util.Map;
020: import javax.persistence.FlushModeType;
021: import javax.persistence.LockModeType;
022: import javax.persistence.Query;
023: import javax.persistence.EntityTransaction;
024: import javax.persistence.EntityManager;
025: import javax.persistence.EntityManagerFactory;
026: import javax.persistence.TransactionRequiredException;
027:
028: /**
029: * The JtaEntityManager is a wrapper around an entity manager that automatically creates and closes entity managers
030: * for each transaction in which it is accessed. This implementation supports both transaction and extended scoped
031: * JTA entity managers.
032: * </p>
033: * It is important that extended scoped entity managers add entity managers to the JtaEntityManagerRegistry when the
034: * component is entered and remove them when exited. If this registration is not preformed, an IllegalStateException
035: * will be thrown when entity manger is used.
036: * It is important that a component adds extended scoped entity managers to the JtaEntityManagerRegistry when the
037: * component is entered and removes them when exited. If this registration is not preformed, an IllegalStateException will
038: * be thrown when entity manger is accessed.
039: */
040: public class JtaEntityManager implements EntityManager {
041: private final JtaEntityManagerRegistry registry;
042: private final EntityManagerFactory entityManagerFactory;
043: private final Map properties;
044: private final boolean extended;
045:
046: public JtaEntityManager(JtaEntityManagerRegistry registry,
047: EntityManagerFactory entityManagerFactory, Map properties) {
048: this (registry, entityManagerFactory, properties, false);
049:
050: }
051:
052: public JtaEntityManager(JtaEntityManagerRegistry registry,
053: EntityManagerFactory entityManagerFactory, Map properties,
054: boolean extended) {
055: if (registry == null)
056: throw new NullPointerException("registry is null");
057: if (entityManagerFactory == null)
058: throw new NullPointerException(
059: "entityManagerFactory is null");
060: this .registry = registry;
061: this .entityManagerFactory = entityManagerFactory;
062: this .properties = properties;
063: this .extended = extended;
064: }
065:
066: private EntityManager getEntityManager() {
067: return registry.getEntityManager(entityManagerFactory,
068: properties, extended);
069: }
070:
071: private boolean isTransactionActive() {
072: return registry.isTransactionActive();
073: }
074:
075: /**
076: * This method assures that a non-extended entity managers has an acive transaction. This is
077: * required for some operations on the entity manager.
078: * @throws TransactionRequiredException if non-extended and a transaction is not active
079: */
080: private void assertTransactionActive()
081: throws TransactionRequiredException {
082: if (!extended && !isTransactionActive()) {
083: throw new TransactionRequiredException();
084: }
085: }
086:
087: /**
088: * Closes a non-extended entity manager if no transaction is active. For methods on an
089: * entity manager that do not require an active transaction, a temp entity manager is created
090: * for the operation and then closed.
091: * @param entityManager the entity manager to close if non-extended and a transaction is not active
092: */
093: private void closeIfNoTx(EntityManager entityManager) {
094: if (!extended && !isTransactionActive()) {
095: entityManager.close();
096: }
097: }
098:
099: public EntityManager getDelegate() {
100: return getEntityManager();
101: }
102:
103: public void persist(Object entity) {
104: assertTransactionActive();
105: getEntityManager().persist(entity);
106: }
107:
108: public <T> T merge(T entity) {
109: assertTransactionActive();
110: return getEntityManager().merge(entity);
111: }
112:
113: public void remove(Object entity) {
114: assertTransactionActive();
115: getEntityManager().remove(entity);
116: }
117:
118: public <T> T find(Class<T> entityClass, Object primaryKey) {
119: EntityManager entityManager = getEntityManager();
120: try {
121: return entityManager.find(entityClass, primaryKey);
122: } finally {
123: closeIfNoTx(entityManager);
124: }
125: }
126:
127: public <T> T getReference(Class<T> entityClass, Object primaryKey) {
128: EntityManager entityManager = getEntityManager();
129: try {
130: return entityManager.getReference(entityClass, primaryKey);
131: } finally {
132: closeIfNoTx(entityManager);
133: }
134: }
135:
136: public void flush() {
137: assertTransactionActive();
138: getEntityManager().flush();
139: }
140:
141: public void setFlushMode(FlushModeType flushMode) {
142: EntityManager entityManager = getEntityManager();
143: try {
144: entityManager.setFlushMode(flushMode);
145: } finally {
146: closeIfNoTx(entityManager);
147: }
148: }
149:
150: public FlushModeType getFlushMode() {
151: EntityManager entityManager = getEntityManager();
152: try {
153: return entityManager.getFlushMode();
154: } finally {
155: closeIfNoTx(entityManager);
156: }
157: }
158:
159: public void lock(Object entity, LockModeType lockMode) {
160: assertTransactionActive();
161: getEntityManager().lock(entity, lockMode);
162: }
163:
164: public void refresh(Object entity) {
165: assertTransactionActive();
166: getEntityManager().refresh(entity);
167: }
168:
169: public void clear() {
170: if (!isTransactionActive()) {
171: return;
172: }
173: getEntityManager().clear();
174: }
175:
176: public boolean contains(Object entity) {
177: return isTransactionActive()
178: && getEntityManager().contains(entity);
179: }
180:
181: public Query createQuery(String qlString) {
182: EntityManager entityManager = getEntityManager();
183: Query query = entityManager.createQuery(qlString);
184: return proxyIfNoTx(entityManager, query);
185: }
186:
187: public Query createNamedQuery(String name) {
188: EntityManager entityManager = getEntityManager();
189: Query query = entityManager.createNamedQuery(name);
190: return proxyIfNoTx(entityManager, query);
191: }
192:
193: public Query createNativeQuery(String sqlString) {
194: EntityManager entityManager = getEntityManager();
195: Query query = entityManager.createNativeQuery(sqlString);
196: return proxyIfNoTx(entityManager, query);
197: }
198:
199: public Query createNativeQuery(String sqlString, Class resultClass) {
200: EntityManager entityManager = getEntityManager();
201: Query query = entityManager.createNativeQuery(sqlString,
202: resultClass);
203: return proxyIfNoTx(entityManager, query);
204: }
205:
206: public Query createNativeQuery(String sqlString,
207: String resultSetMapping) {
208: EntityManager entityManager = getEntityManager();
209: Query query = entityManager.createNativeQuery(sqlString,
210: resultSetMapping);
211: return proxyIfNoTx(entityManager, query);
212: }
213:
214: private Query proxyIfNoTx(EntityManager entityManager, Query query) {
215: if (!extended && !isTransactionActive()) {
216: return new JtaQuery(entityManager, query);
217: }
218: return query;
219: }
220:
221: public void joinTransaction() {
222: }
223:
224: public void close() {
225: }
226:
227: public boolean isOpen() {
228: return true;
229: }
230:
231: public EntityTransaction getTransaction() {
232: throw new IllegalStateException(
233: "A JTA Entity Manager can not use an entity transaction");
234: }
235: }
|