001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.examples.rest.petstore;
014
015import java.util.*;
016
017import javax.persistence.*;
018
019import org.apache.juneau.utils.*;
020
021/**
022 * Superclass for DAOs that use the JPA entity manager.
023 *
024 * <ul class='seealso'>
025 *    <li class='extlink'>{@source}
026 * </ul>
027 */
028public class AbstractPersistenceService {
029
030   private final EntityManagerFactory entityManagerFactory;
031
032   /**
033    * Constructor.
034    */
035   public AbstractPersistenceService() {
036      entityManagerFactory = Persistence.createEntityManagerFactory("test");
037   }
038
039   /**
040    * Retrieves an entity manager session.
041    *
042    * @return The entity manager session.
043    */
044   protected EntityManager getEntityManager() {
045      return entityManagerFactory.createEntityManager();
046   }
047
048   /**
049    * Retrieves the specified JPA bean from the repository.
050    *
051    * @param em The entity manager to use to retrieve the bean.
052    * @param t The bean type to retrieve.
053    * @param id The primary key value.
054    * @return The JPA bean, or null if not found.
055    */
056   protected <T> T find(EntityManager em, Class<T> t, Object id) {
057      return em.find(t, id);
058   }
059
060   /**
061    * Same as {@link #find(EntityManager, Class, Object)} but uses a new entity manager.
062    *
063    * @param t The bean type to retrieve.
064    * @param id The primary key value.
065    * @return The JPA bean, or null if not found.
066    */
067   protected <T> T find(Class<T> t, Object id) {
068      return find(getEntityManager(), t, id);
069   }
070
071   /**
072    * Store the specified JPA bean in the repository.
073    *
074    * @param em The entity manager to use to store and merge the bean.
075    * @param t The bean to store.
076    * @return The merged JPA bean returned by the {@link EntityManager#merge(Object)} method, or null if the bean was null.
077    */
078   protected <T> T merge(EntityManager em, T t) {
079      if (t == null)
080         return null;
081      try {
082         EntityTransaction et = em.getTransaction();
083         et.begin();
084         t = em.merge(t);
085         et.commit();
086         return t;
087      } finally {
088         em.close();
089      }
090   }
091
092   /**
093    * Same as {@link #merge(EntityManager, Object)} but uses a new entity manager.
094    *
095    * @param t The bean to store.
096    * @return The merged JPA bean returned by the {@link EntityManager#merge(Object)} method, or null if the bean was null.
097    */
098   protected <T> T merge(T t) {
099      return merge(getEntityManager(), t);
100   }
101
102   /**
103    * Store the specified JPA beans in the repository.
104    *
105    * All values are persisted in the same transaction.
106    *
107    * @param em The entity manager to use to store and merge the beans.
108    * @param c The collection of beans to store.
109    * @return The merged JPA beans returned by the {@link EntityManager#merge(Object)} method.
110    */
111   protected <T> Collection<T> merge(EntityManager em, Collection<T> c) {
112      Collection<T> c2 = new ArrayList<>();
113      try {
114         EntityTransaction et = em.getTransaction();
115         et.begin();
116         for (T t : c)
117            c2.add(em.merge(t));
118         et.commit();
119         return c2;
120      } finally {
121         em.close();
122      }
123   }
124
125   /**
126    * Same as {@link #merge(EntityManager, Collection)} but uses a new entity manager.
127    *
128    * @param c The collection of beans to store.
129    * @return The merged JPA beans returned by the {@link EntityManager#merge(Object)} method.
130    */
131   protected <T> Collection<T> merge(Collection<T> c) {
132      return merge(getEntityManager(), c);
133   }
134
135   /**
136    * Remove the specified JPA bean from the repository.
137    *
138    * @param t The bean type to remove.
139    * @param id The primary key value.
140    */
141   protected <T> void remove(Class<T> t, Object id) {
142      EntityManager em = getEntityManager();
143      remove(em, find(em, t, id));
144   }
145
146   /**
147    * Remove the specified JPA bean from the repository.
148    *
149    * @param em The entity manager used to retrieve the bean.
150    * @param t The bean to remove.  Can be null.
151    */
152   protected <T> void remove(EntityManager em, T t) {
153      if (t == null)
154         return;
155      try {
156         EntityTransaction et = em.getTransaction();
157         et.begin();
158         em.remove(t);
159         et.commit();
160      } finally {
161         em.close();
162      }
163   }
164
165   /**
166    * Runs a JPA query and returns the results.
167    *
168    * @param <T> The bean type.
169    * @param em The entity manager to use to retrieve the beans.
170    * @param query The JPA query.
171    * @param t The bean type.
172    * @param searchArgs Optional search arguments.
173    * @return The results.
174    */
175   protected <T> List<T> query(EntityManager em, String query, Class<T> t, SearchArgs searchArgs) {
176      TypedQuery<T> q = em.createQuery(query, t);
177      if (searchArgs != null) {
178         q.setMaxResults(searchArgs.getLimit() == 0 ? 100 : searchArgs.getLimit());
179         q.setFirstResult(searchArgs.getPosition());
180      }
181      return em.createQuery(query, t).getResultList();
182   }
183
184   /**
185    * Same as {@link #query(EntityManager,String,Class,SearchArgs)} but uses a new entity manager.
186    *
187    * @param <T> The bean type.
188    * @param query The JPA query.
189    * @param t The bean type.
190    * @param searchArgs Optional search arguments.
191    * @return The results.
192    */
193   protected <T> List<T> query(String query, Class<T> t, SearchArgs searchArgs) {
194      return query(getEntityManager(), query, t, searchArgs);
195   }
196
197   /**
198    * Runs a JPA parameterized query and returns the results.
199    *
200    * @param em The entity manager to use to retrieve the beans.
201    * @param query The JPA query.
202    * @param t The bean type.
203    * @param params The query parameter values.
204    * @return The results.
205    */
206   protected <T> List<T> query(EntityManager em, String query, Class<T> t, Map<String,Object> params) {
207      TypedQuery<T> tq = em.createQuery(query, t);
208      for (Map.Entry<String,Object> e : params.entrySet()) {
209         tq.setParameter(e.getKey(), e.getValue());
210      }
211      return tq.getResultList();
212   }
213
214   /**
215    * Same as {@link #query(EntityManager,String,Class,Map)} but uses a new entity manager.
216    *
217    * @param query The JPA query.
218    * @param t The bean type.
219    * @param params The query parameter values.
220    * @return The results.
221    */
222   protected <T> List<T> query(String query, Class<T> t, Map<String,Object> params) {
223      return query(getEntityManager(), query, t, params);
224   }
225
226   /**
227    * Runs a JPA update statement.
228    *
229    * @param em The entity manager to use to run the statement.
230    * @param query The JPA update statement.
231    * @return The number of rows modified.
232    */
233   protected int update(EntityManager em, String query) {
234      return em.createQuery(query).executeUpdate();
235   }
236
237   /**
238    * Same as {@link #update(EntityManager,String)} but uses a new entity manager.
239    *
240    * @param query The JPA update statement.
241    * @return The number of rows modified.
242    */
243   protected int update(String query) {
244      return update(getEntityManager(), query);
245   }
246
247   /**
248    * Runs a JPA parameterized update statement.
249    *
250    * @param em The entity manager to use to run the statement.
251    * @param query The JPA update statement.
252    * @param params The query parameter values.
253    * @return The number of rows modified.
254    */
255   protected int update(EntityManager em, String query, Map<String,Object> params) {
256      Query q = em.createQuery(query);
257      for (Map.Entry<String,Object> e : params.entrySet()) {
258         q.setParameter(e.getKey(), e.getValue());
259      }
260      return q.executeUpdate();
261   }
262
263   /**
264    * Same as {@link #update(EntityManager,String,Map)} but uses a new entity manager.
265    *
266    * @param query The JPA update statement.
267    * @param params The query parameter values.
268    * @return The number of rows modified.
269    */
270   protected int update(String query, Map<String,Object> params) {
271      return update(getEntityManager(), query, params);
272   }
273}