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 */
024public class AbstractPersistenceService {
025
026   private final EntityManagerFactory entityManagerFactory;
027
028   public AbstractPersistenceService() {
029      entityManagerFactory = Persistence.createEntityManagerFactory("test");
030   }
031
032   /**
033    * Retrieves an entity manager session.
034    */
035   protected EntityManager getEntityManager() {
036      return entityManagerFactory.createEntityManager();
037   }
038
039   /**
040    * Retrieves the specified JPA bean from the repository.
041    *
042    * @param em The entity manager to use to retrieve the bean.
043    * @param t The bean type to retrieve.
044    * @param id The primary key value.
045    * @return The JPA bean, or null if not found.
046    */
047   protected <T> T find(EntityManager em, Class<T> t, Object id) {
048      return em.find(t, id);
049   }
050
051   /**
052    * Same as {@link #find(EntityManager, Class, Object)} but uses a new entity manager.
053    *
054    * @param t The bean type to retrieve.
055    * @param id The primary key value.
056    * @return The JPA bean, or null if not found.
057    */
058   protected <T> T find(Class<T> t, Object id) {
059      return find(getEntityManager(), t, id);
060   }
061
062   /**
063    * Store the specified JPA bean in the repository.
064    *
065    * @param em The entity manager to use to store and merge the bean.
066    * @param t The bean to store.
067    * @return The merged JPA bean returned by the {@link EntityManager#merge(Object)} method, or null if the bean was null.
068    */
069   protected <T> T merge(EntityManager em, T t) {
070      if (t == null)
071         return null;
072      try {
073         EntityTransaction et = em.getTransaction();
074         et.begin();
075         t = em.merge(t);
076         et.commit();
077         return t;
078      } finally {
079         em.close();
080      }
081   }
082
083   /**
084    * Same as {@link #merge(EntityManager, Object)} but uses a new entity manager.
085    *
086    * @param t The bean to store.
087    * @return The merged JPA bean returned by the {@link EntityManager#merge(Object)} method, or null if the bean was null.
088    */
089   protected <T> T merge(T t) {
090      return merge(getEntityManager(), t);
091   }
092
093   /**
094    * Store the specified JPA beans in the repository.
095    *
096    * All values are persisted in the same transaction.
097    *
098    * @param em The entity manager to use to store and merge the beans.
099    * @param c The collection of beans to store.
100    * @return The merged JPA beans returned by the {@link EntityManager#merge(Object)} method.
101    */
102   protected <T> Collection<T> merge(EntityManager em, Collection<T> c) {
103      Collection<T> c2 = new ArrayList<>();
104      try {
105         EntityTransaction et = em.getTransaction();
106         et.begin();
107         for (T t : c)
108            c2.add(em.merge(t));
109         et.commit();
110         return c2;
111      } finally {
112         em.close();
113      }
114   }
115
116   /**
117    * Same as {@link #merge(EntityManager, Collection)} but uses a new entity manager.
118    *
119    * @param c The collection of beans to store.
120    * @return The merged JPA beans returned by the {@link EntityManager#merge(Object)} method.
121    */
122   protected <T> Collection<T> merge(Collection<T> c) {
123      return merge(getEntityManager(), c);
124   }
125
126   /**
127    * Remove the specified JPA bean from the repository.
128    *
129    * @param t The bean type to remove.
130    * @param id The primary key value.
131    */
132   protected <T> void remove(Class<T> t, Object id) {
133      EntityManager em = getEntityManager();
134      remove(em, find(em, t, id));
135   }
136
137   /**
138    * Remove the specified JPA bean from the repository.
139    *
140    * @param em The entity manager used to retrieve the bean.
141    * @param t The bean to remove.  Can be null.
142    */
143   protected <T> void remove(EntityManager em, T t) {
144      if (t == null)
145         return;
146      try {
147         EntityTransaction et = em.getTransaction();
148         et.begin();
149         em.remove(t);
150         et.commit();
151      } finally {
152         em.close();
153      }
154   }
155
156   /**
157    * Runs a JPA query and returns the results.
158    *
159    * @param em The entity manager to use to retrieve the beans.
160    * @param query The JPA query.
161    * @param t The bean type.
162    */
163   protected <T> List<T> query(EntityManager em, String query, Class<T> t, SearchArgs searchArgs) {
164      TypedQuery<T> q = em.createQuery(query, t);
165      if (searchArgs != null) {
166         q.setMaxResults(searchArgs.getLimit() == 0 ? 100 : searchArgs.getLimit());
167         q.setFirstResult(searchArgs.getPosition());
168      }
169      return em.createQuery(query, t).getResultList();
170   }
171
172   /**
173    * Same as {@link #query(EntityManager,String,Class,SearchArgs)} but uses a new entity manager.
174    *
175    * @param query The JPA query.
176    * @param t The bean type.
177    */
178   protected <T> List<T> query(String query, Class<T> t, SearchArgs searchArgs) {
179      return query(getEntityManager(), query, t, searchArgs);
180   }
181
182   /**
183    * Runs a JPA parameterized query and returns the results.
184    *
185    * @param em The entity manager to use to retrieve the beans.
186    * @param query The JPA query.
187    * @param t The bean type.
188    * @param params The query parameter values.
189    */
190   protected <T> List<T> query(EntityManager em, String query, Class<T> t, Map<String,Object> params) {
191      TypedQuery<T> tq = em.createQuery(query, t);
192      for (Map.Entry<String,Object> e : params.entrySet()) {
193         tq.setParameter(e.getKey(), e.getValue());
194      }
195      return tq.getResultList();
196   }
197
198   /**
199    * Same as {@link #query(EntityManager,String,Class,Map)} but uses a new entity manager.
200    *
201    * @param query The JPA query.
202    * @param t The bean type.
203    * @param params The query parameter values.
204    */
205   protected <T> List<T> query(String query, Class<T> t, Map<String,Object> params) {
206      return query(getEntityManager(), query, t, params);
207   }
208
209   /**
210    * Runs a JPA update statement.
211    *
212    * @param em The entity manager to use to run the statement.
213    * @param query The JPA update statement.
214    * @return The number of rows modified.
215    */
216   protected int update(EntityManager em, String query) {
217      return em.createQuery(query).executeUpdate();
218   }
219
220   /**
221    * Same as {@link #update(EntityManager,String)} but uses a new entity manager.
222    *
223    * @param query The JPA update statement.
224    * @return The number of rows modified.
225    */
226   protected int update(String query) {
227      return update(getEntityManager(), query);
228   }
229
230   /**
231    * Runs a JPA parameterized update statement.
232    *
233    * @param em The entity manager to use to run the statement.
234    * @param query The JPA update statement.
235    * @param params The query parameter values.
236    * @return The number of rows modified.
237    */
238   protected int update(EntityManager em, String query, Map<String,Object> params) {
239      Query q = em.createQuery(query);
240      for (Map.Entry<String,Object> e : params.entrySet()) {
241         q.setParameter(e.getKey(), e.getValue());
242      }
243      return q.executeUpdate();
244   }
245
246   /**
247    * Same as {@link #update(EntityManager,String,Map)} but uses a new entity manager.
248    *
249    * @param query The JPA update statement.
250    * @param params The query parameter values.
251    * @return The number of rows modified.
252    */
253   protected int update(String query, Map<String,Object> params) {
254      return update(getEntityManager(), query, params);
255   }
256}