1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.kuali.student.r2.common.dao;
18
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.student.r2.common.entity.PersistableEntity;
21 import org.kuali.student.r2.common.exceptions.DoesNotExistException;
22
23 import javax.persistence.EntityManager;
24 import javax.persistence.NoResultException;
25 import javax.persistence.NonUniqueResultException;
26 import javax.persistence.PersistenceContext;
27 import javax.persistence.Query;
28 import javax.persistence.TypedQuery;
29 import java.lang.reflect.ParameterizedType;
30 import java.lang.reflect.Type;
31 import java.util.ArrayList;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Set;
36
37
38
39
40 public class GenericEntityDao<T extends PersistableEntity<String>> implements EntityDao<String,T> {
41
42
43
44
45 protected Class<T> entityClass;
46
47 @PersistenceContext
48 protected EntityManager em;
49
50 protected Boolean enableMaxIdFetch = Boolean.TRUE;
51 protected Integer maxInClauseElements = 1000;
52
53 public GenericEntityDao() {
54 entityClass = getEntityClass();
55 }
56
57 @Override
58 public T find(String primaryKey) {
59 return em.find(entityClass, primaryKey);
60 }
61
62 @Override
63 public List<T> findByIds(String primaryKeyMemberName, List<String> primaryKeys) throws DoesNotExistException {
64
65
66 if (primaryKeys == null || primaryKeys.isEmpty())
67 return new ArrayList<T>();
68
69 Set<String>primaryKeySet = new HashSet<String>(primaryKeys.size());
70
71 primaryKeySet.addAll(primaryKeys);
72
73 StringBuilder queryString = new StringBuilder();
74
75 TypedQuery<T> query = buildQuery(queryString, primaryKeyMemberName, primaryKeySet);
76
77 List<T> resultList = query.getResultList();
78
79 verifyResults(resultList, primaryKeySet);
80
81 return resultList;
82 }
83
84
85
86
87
88
89
90
91
92 protected TypedQuery<T> buildQuery(StringBuilder queryStringRef, String primaryKeyMemberName, Set<String> primaryKeySet) {
93
94 TypedQuery<T> queryRef;
95
96 if (!enableMaxIdFetch || primaryKeySet.size() <= maxInClauseElements) {
97
98 queryStringRef.append("from ").append(entityClass.getSimpleName()).append(" where ").append(primaryKeyMemberName).append(" in (:ids)");
99 queryRef = em.createQuery(queryStringRef.toString(), entityClass).setParameter("ids", primaryKeySet);
100
101 } else {
102
103 List<List<String>> brokenLists = new ArrayList<List<String>>();
104 List<String> lst = new ArrayList<String>();
105
106 queryStringRef.append("from ").append(entityClass.getSimpleName());
107
108 Iterator<String> itr = primaryKeySet.iterator();
109 for (int index = 0; itr.hasNext(); index++) {
110
111 if (index % maxInClauseElements == 0) {
112
113 brokenLists.add(lst);
114
115 if (brokenLists.size() == 1) {
116 queryStringRef.append(" where ").append(primaryKeyMemberName).append(" in (:ids1)");
117 } else {
118 queryStringRef.append(" or ").append(primaryKeyMemberName).append(" in (:ids").append(brokenLists.size()).append(")");
119 }
120
121 }
122 lst.add(itr.next());
123 }
124
125 queryRef = em.createQuery(queryStringRef.toString(), entityClass);
126
127 for (int i = 1; i <= brokenLists.size(); i++) {
128 queryRef.setParameter("ids" + i, brokenLists.get(i - 1));
129 }
130
131 }
132 return queryRef;
133 }
134
135
136
137
138
139
140
141
142 public boolean entityExists (String primaryKey) {
143
144
145 Query q = em.createQuery("select id from " + entityClass.getSimpleName() + " where id = :key").setParameter("key", primaryKey);
146
147 try {
148 q.getSingleResult();
149 }
150 catch (NonUniqueResultException e) {
151
152 return false;
153 }
154 catch (NoResultException e) {
155
156 return false;
157 }
158
159
160 return true;
161
162 }
163
164 protected void verifyResults(List<T> resultList, Set<String> primaryKeys) throws DoesNotExistException {
165
166 if (resultList.size() == 0){
167
168 throw new DoesNotExistException("No data was found for : " + StringUtils.join(primaryKeys, ", "));
169
170 } else if (resultList.size() != primaryKeys.size()) {
171
172 Set<String> unmatchedKeySet = new HashSet<String> ();
173
174 unmatchedKeySet.addAll(primaryKeys);
175
176 for (T t : resultList) {
177
178 unmatchedKeySet.remove(t.getId());
179 }
180
181 throw new DoesNotExistException("Missing data for : " + StringUtils.join(unmatchedKeySet.iterator(), ", "));
182
183 }
184 }
185
186 @Override
187 public List<T> findByIds(List<String> primaryKeys) throws DoesNotExistException {
188
189 return this.findByIds("id", primaryKeys);
190
191 }
192
193 @Override
194 @SuppressWarnings("unchecked")
195 public List<T> findAll() {
196 return (List<T>) em.createQuery("from " + entityClass.getSimpleName()).getResultList();
197 }
198
199 @Override
200 public void persist(T entity) {
201 em.persist(entity);
202 }
203
204 @Override
205 public void update(T entity) {
206 em.merge(entity);
207 }
208
209 @Override
210 public void remove(T entity) {
211 em.remove(entity);
212 }
213
214 @Override
215 public T merge(T entity) {
216
217 if (em.contains(entity))
218 em.detach(entity);
219
220 return em.merge(entity);
221 }
222
223 @SuppressWarnings("unchecked")
224 protected <C extends T> Class<C> getEntityClass() {
225 if (entityClass == null) {
226 entityClass = (Class<T>) getEntityType(this);
227 }
228 return (Class<C>) entityClass;
229 }
230
231 private Type getEntityType(Object object) {
232 Type type = object.getClass().getGenericSuperclass();
233 if (type instanceof ParameterizedType) {
234 ParameterizedType paramType = (ParameterizedType) type;
235 Type result = paramType.getActualTypeArguments()[0];
236 return result;
237 } else {
238 throw new IllegalArgumentException("Could not guess entity type by reflection.");
239 }
240 }
241
242 @Override
243 public void setEm(EntityManager em) {
244 this.em = em;
245 }
246
247 @Override
248 public EntityManager getEm() {
249 return em;
250 }
251
252 public void setEnableMaxIdFetch(Boolean enableMaxIdFetch) {
253 this.enableMaxIdFetch = enableMaxIdFetch;
254 }
255
256 public void setMaxInClauseElements(Integer maxInClauseElements) {
257 this.maxInClauseElements = maxInClauseElements;
258 }
259
260 }