1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.dao.impl;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23
24 import javax.persistence.EntityManager;
25 import javax.persistence.EntityNotFoundException;
26 import javax.persistence.PersistenceContext;
27 import javax.persistence.PersistenceException;
28
29 import org.hibernate.FlushMode;
30 import org.hibernate.Session;
31 import org.hibernate.ejb.HibernateEntityManager;
32 import org.hibernate.proxy.HibernateProxy;
33 import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
34 import org.kuali.rice.core.framework.persistence.jpa.criteria.Criteria;
35 import org.kuali.rice.core.framework.persistence.jpa.criteria.QueryByCriteria;
36 import org.kuali.rice.core.framework.persistence.jpa.criteria.QueryByCriteria.QueryByCriteriaType;
37 import org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager;
38 import org.kuali.rice.krad.bo.BusinessObject;
39 import org.kuali.rice.krad.bo.PersistableBusinessObject;
40 import org.kuali.rice.krad.bo.PersistableBusinessObjectExtension;
41 import org.kuali.rice.krad.dao.BusinessObjectDao;
42 import org.kuali.rice.krad.service.PersistenceStructureService;
43 import org.kuali.rice.krad.util.KRADPropertyConstants;
44 import org.kuali.rice.krad.util.OjbCollectionHelper;
45 import org.springframework.dao.DataAccessException;
46
47
48
49
50 @SuppressWarnings("unchecked")
51 public class BusinessObjectDaoJpa implements BusinessObjectDao {
52
53 @PersistenceContext
54 private EntityManager entityManager;
55
56 private PersistenceStructureService persistenceStructureService;
57
58 private OjbCollectionHelper ojbCollectionHelper;
59
60 public BusinessObjectDaoJpa(EntityManager entityManager, PersistenceStructureService persistenceStructureService) {
61 this.entityManager = entityManager;
62 this.persistenceStructureService = persistenceStructureService;
63 }
64
65
66
67
68 public <T extends BusinessObject> T findBySinglePrimaryKey(Class<T> clazz, Object primaryKey) {
69 return (T) entityManager.find(clazz, primaryKey);
70 }
71
72
73
74
75
76 public <T extends BusinessObject> T findByPrimaryKey(Class<T> clazz, Map<String, ?> primaryKeys) {
77 if (primaryKeys == null || primaryKeys.isEmpty()) {
78 return null;
79 }
80 T bo = null;
81 try {
82 bo = (T) new QueryByCriteria(entityManager, buildJpaCriteria(clazz, primaryKeys)).toQuery().getSingleResult();
83 } catch (PersistenceException e) {}
84 return bo;
85 }
86
87
88
89
90
91
92
93
94 public <T extends BusinessObject> T findByPrimaryKeyUsingKeyObject(Class<T> clazz, Object pkObject) {
95 if (pkObject == null) {
96 return null;
97 }
98 T bo = null;
99 try {
100 bo = (T) entityManager.find(clazz, pkObject);
101 } catch (PersistenceException e) {}
102 return bo;
103 }
104
105
106
107
108
109
110
111
112
113
114 public <T extends BusinessObject> Collection<T> findAll(Class<T> clazz) {
115 return (Collection<T>) new QueryByCriteria(entityManager, new Criteria(clazz.getName())).toQuery().getResultList();
116 }
117
118
119
120
121
122 public <T extends BusinessObject> Collection<T> findAllOrderBy(Class<T> clazz, String sortField, boolean sortAscending) {
123 Criteria criteria = new Criteria(clazz.getName());
124 criteria.orderBy(sortField, sortAscending);
125 return new QueryByCriteria(entityManager, criteria).toQuery().getResultList();
126 }
127
128
129
130
131
132
133
134 public <T extends BusinessObject> Collection<T> findMatching(Class<T> clazz, Map<String, ?> fieldValues) {
135 return (Collection<T>)new QueryByCriteria(entityManager, buildJpaCriteria(clazz, fieldValues)).toQuery().getResultList();
136 }
137
138
139
140
141
142 public <T extends BusinessObject> Collection<T> findMatching(Criteria criteria) {
143 return (List<T>)new QueryByCriteria(entityManager, criteria).toQuery().getResultList();
144 }
145
146
147
148
149 public <T extends BusinessObject> Collection<T> findAllActive(Class<T> clazz) {
150 return (Collection<T>)new QueryByCriteria(entityManager, buildActiveJpaCriteria(clazz)).toQuery().getResultList();
151 }
152
153
154
155
156 public <T extends BusinessObject> Collection<T> findAllInactive(Class<T> clazz) {
157 return (Collection<T>)new QueryByCriteria(entityManager, buildInactiveJpaCriteria(clazz)).toQuery().getResultList();
158 }
159
160
161
162
163
164 public <T extends BusinessObject> Collection<T> findAllActiveOrderBy(Class<T> clazz, String sortField, boolean sortAscending) {
165 Criteria criteria = buildActiveJpaCriteria(clazz);
166 criteria.orderBy(sortField, sortAscending);
167 return (Collection<T>)new QueryByCriteria(entityManager, criteria).toQuery().getResultList();
168 }
169
170
171
172
173
174 public <T extends BusinessObject> Collection<T> findMatchingActive(Class<T> clazz, Map<String, ?> fieldValues) {
175 Criteria criteria = buildJpaCriteria(clazz, fieldValues);
176 criteria.and(buildActiveJpaCriteria(clazz));
177 return (Collection<T>)new QueryByCriteria(entityManager, criteria).toQuery().getResultList();
178 }
179
180
181
182
183
184
185
186 public int countMatching(Class clazz, Map<String, ?> fieldValues) {
187 return ((Long) new QueryByCriteria(entityManager, buildJpaCriteria(clazz, fieldValues)).toCountQuery().getSingleResult()).intValue();
188 }
189
190
191
192
193
194
195
196 public int countMatching(Class clazz, Map<String, ?> positiveFieldValues, Map<String, ?> negativeFieldValues) {
197 Criteria criteria = buildJpaCriteria(clazz, positiveFieldValues);
198 criteria.and(buildNegativeJpaCriteria(clazz, negativeFieldValues));
199 return ((Long) new QueryByCriteria(entityManager, criteria).toCountQuery().getSingleResult()).intValue();
200 }
201
202
203
204
205
206
207
208 public <T extends BusinessObject> Collection<T> findMatchingOrderBy(Class<T> clazz, Map<String, ?> fieldValues, String sortField, boolean sortAscending) {
209 Criteria criteria = buildJpaCriteria(clazz, fieldValues);
210 criteria.orderBy(sortField, sortAscending);
211 return (Collection<T>)new QueryByCriteria(entityManager, criteria).toQuery().getResultList();
212 }
213
214
215
216
217
218
219 public PersistableBusinessObject save(PersistableBusinessObject bo) throws DataAccessException {
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 if (entityManager.contains(bo) && ((HibernateEntityManager)entityManager).getSession().isReadOnly(bo)) {
237 ((HibernateEntityManager)entityManager).getSession().setReadOnly(bo, false);
238 }
239 return reattachAndSave(bo);
240 }
241
242
243
244
245
246
247
248
249 public List<? extends PersistableBusinessObject> save(List businessObjects) throws DataAccessException {
250 List<PersistableBusinessObject> savedBOs = new ArrayList<PersistableBusinessObject>();
251 for (Iterator i = businessObjects.iterator(); i.hasNext();) {
252 Object bo = i.next();
253 final PersistableBusinessObject savedBusinessObject = reattachAndSave((PersistableBusinessObject) bo);
254 savedBOs.add(savedBusinessObject);
255 }
256 return savedBOs;
257 }
258
259
260
261
262
263
264
265
266 public void delete(PersistableBusinessObject bo) {
267 final PersistableBusinessObject realPBO = materialize(bo);
268 if (realPBO != null) {
269 if (realPBO.getExtension() != null) {
270 delete(realPBO.getExtension());
271 }
272 if (entityManager.contains(realPBO)) {
273 entityManager.remove(realPBO);
274 } else {
275 final PersistableBusinessObject foundBO = (PersistableBusinessObject)entityManager.find(realPBO.getClass(), MetadataManager.getEntityPrimaryKeyObject(realPBO));
276 if (foundBO != null) {
277 entityManager.remove(foundBO);
278 }
279 }
280 }
281 }
282
283
284
285
286
287
288
289 protected PersistableBusinessObject materialize(PersistableBusinessObject bo) {
290 try {
291 if (bo instanceof HibernateProxy) {
292 return (PersistableBusinessObject)((HibernateProxy)bo).getHibernateLazyInitializer().getImplementation();
293 }
294 return bo;
295 } catch (EntityNotFoundException enfe) {
296 return null;
297 }
298 }
299
300
301
302
303 public void delete(List<? extends PersistableBusinessObject> boList) {
304 for (PersistableBusinessObject bo : boList) {
305 delete(bo);
306 }
307 }
308
309
310
311
312
313 public void deleteMatching(Class clazz, Map<String, ?> fieldValues) {
314
315 new QueryByCriteria(entityManager, buildJpaCriteria(clazz, fieldValues), QueryByCriteriaType.DELETE).toQuery().executeUpdate();
316 }
317
318
319
320
321 public PersistableBusinessObject retrieve(PersistableBusinessObject object) {
322 PersistableBusinessObject pbo = null;
323 Object pkObject = MetadataManager.getEntityPrimaryKeyObject(object);
324 if (pkObject != null) {
325 pbo = (PersistableBusinessObject) entityManager.find(object.getClass(), pkObject);
326 if (pbo != null && pbo.getExtension() != null) {
327 pbo.setExtension((PersistableBusinessObjectExtension) entityManager.find(pbo.getExtension().getClass(), MetadataManager.getPersistableBusinessObjectPrimaryKeyObjectWithValuesForExtension(pbo, pbo.getExtension())));
328 }
329 }
330 return pbo;
331 }
332
333 private Criteria buildJpaCriteria(Class clazz, Map<String, ?> fieldValues) {
334 Criteria criteria = new Criteria(clazz.getName());
335 for (Iterator i = fieldValues.entrySet().iterator(); i.hasNext();) {
336 Map.Entry<String, ?> e = (Map.Entry<String, ?>) i.next();
337
338 String key = e.getKey();
339 Object value = e.getValue();
340 String alias = "";
341 String[] keySplit = key.split("\\.");
342 if (keySplit.length > 1) {
343 alias = keySplit[keySplit.length-2];
344 String variableKey = keySplit[keySplit.length-1];
345 for (int j = 0; j < keySplit.length - 1; j++) {
346 if (criteria.getAliasIndex(keySplit[j]) == -1) {
347 criteria.join(keySplit[j], keySplit[j], false, true);
348 }
349 }
350 key = "__JPA_ALIAS[['" + alias + "']]__." + variableKey;
351 }
352 if (value == null) {
353 continue;
354 } else if (value instanceof Collection) {
355 criteria.in(key, (Collection)value);
356 } else {
357 criteria.eq(key, value);
358 }
359 }
360 return criteria;
361 }
362
363 private Criteria buildActiveJpaCriteria(Class clazz) {
364 Criteria criteria = new Criteria(clazz.getName());
365 criteria.eq(KRADPropertyConstants.ACTIVE, true);
366 return criteria;
367 }
368
369 private Criteria buildInactiveJpaCriteria(Class clazz) {
370 Criteria criteria = new Criteria(clazz.getName());
371 criteria.eq(KRADPropertyConstants.ACTIVE, false);
372 return criteria;
373 }
374
375 private Criteria buildNegativeJpaCriteria(Class clazz, Map negativeFieldValues) {
376 Criteria criteria = new Criteria(clazz.getName());
377 for (Iterator i = negativeFieldValues.entrySet().iterator(); i.hasNext();) {
378 Map.Entry e = (Map.Entry) i.next();
379
380 String key = (String) e.getKey();
381 Object value = e.getValue();
382 if (value instanceof Collection) {
383 criteria.notIn(key, (List) value);
384 } else {
385 criteria.ne(key, value);
386 }
387 }
388
389 return criteria;
390 }
391
392
393
394
395 public PersistableBusinessObject manageReadOnly(PersistableBusinessObject bo) {
396 Session session = ((HibernateEntityManager)entityManager).getSession();
397 FlushMode currentFlushMode = session.getFlushMode();
398 session.setFlushMode(FlushMode.MANUAL);
399 PersistableBusinessObject managedBO = entityManager.merge(bo);
400 session.setReadOnly(managedBO, true);
401 session.setFlushMode(currentFlushMode);
402 return managedBO;
403 }
404
405
406
407
408
409
410 protected PersistenceStructureService getPersistenceStructureService() {
411 return persistenceStructureService;
412 }
413
414
415
416
417
418
419
420 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
421 this.persistenceStructureService = persistenceStructureService;
422 }
423
424 private PersistableBusinessObject reattachAndSave(PersistableBusinessObject bo) {
425 PersistableBusinessObject attachedBo = findByPrimaryKey(bo.getClass(), MetadataManager.getEntityPrimaryKeyValuePairs(bo));
426 PersistableBusinessObject newBo = attachedBo;
427 if (attachedBo == null) {
428 newBo = entityManager.merge(bo);
429 if (bo.getExtension() != null) {
430 entityManager.merge(bo.getExtension());
431 }
432 } else {
433
434
435
436
437
438
439 OrmUtils.reattach(bo, attachedBo);
440 newBo = entityManager.merge(attachedBo);
441 }
442 return newBo;
443 }
444
445
446
447
448 public EntityManager getEntityManager() {
449 return this.entityManager;
450 }
451
452
453
454
455 public void setEntityManager(EntityManager entityManager) {
456 this.entityManager = entityManager;
457 }
458
459 }