1 package ch.elca.el4j.services.persistence.hibernate.dao;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.List;
7
8 import org.apache.lucene.analysis.standard.StandardAnalyzer;
9 import org.apache.lucene.queryParser.MultiFieldQueryParser;
10 import org.apache.lucene.queryParser.ParseException;
11 import org.hibernate.Criteria;
12 import org.hibernate.HibernateException;
13 import org.hibernate.Query;
14 import org.hibernate.Session;
15 import org.hibernate.SessionFactory;
16 import org.hibernate.criterion.DetachedCriteria;
17 import org.hibernate.criterion.Projections;
18 import org.hibernate.search.FullTextSession;
19 import org.hibernate.search.Search;
20 import org.springframework.dao.DataAccessException;
21 import org.springframework.dao.DataRetrievalFailureException;
22 import org.springframework.dao.OptimisticLockingFailureException;
23 import org.springframework.orm.hibernate3.HibernateCallback;
24 import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException;
25 import org.springframework.orm.hibernate3.HibernateTemplate;
26 import org.springframework.util.Assert;
27
28 import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
29 import ch.elca.el4j.services.monitoring.notification.PersistenceNotificationHelper;
30 import ch.elca.el4j.services.search.QueryObject;
31 import ch.elca.el4j.util.codingsupport.Reject;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class ConvenienceHibernateTemplate extends HibernateTemplate {
48
49
50
51
52
53 public ConvenienceHibernateTemplate(SessionFactory sessionFactory) {
54 super(sessionFactory);
55 }
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public Object getByIdStrong(Class<?> entityClass, Serializable id, final String objectName)
77 throws DataAccessException, DataRetrievalFailureException {
78
79 Reject.ifNull(id, "The identifier must not be null.");
80 Reject.ifEmpty(objectName, "The name of the persistent object type "
81 + "must not be empty.");
82 Object result = get(entityClass, id);
83
84 if (result == null || !(entityClass.isInstance(result))) {
85 PersistenceNotificationHelper.notifyObjectRetrievalFailure(entityClass, id, objectName);
86 }
87 return result;
88 }
89
90
91
92
93
94 public Object getByIdStrongLazy(Class<?> entityClass, Serializable id, final String objectName)
95 throws DataAccessException, DataRetrievalFailureException {
96
97 Reject.ifNull(id, "The identifier must not be null.");
98 Reject.ifEmpty(objectName, "The name of the persistent object type "
99 + "must not be empty.");
100 Object result = load(entityClass, id);
101
102 if (result == null || !(entityClass.isInstance(result))) {
103 PersistenceNotificationHelper.notifyObjectRetrievalFailure(entityClass, id, objectName);
104 }
105 return result;
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public Object findByNamedParamStrong(String queryString, String paramName, Object value, final String objectName)
134 throws DataAccessException, DataRetrievalFailureException {
135
136 Reject.ifEmpty(paramName);
137 Reject.ifNull(value);
138 Reject.ifEmpty(objectName, "The name of the persistent object type "
139 + "must not be empty.");
140 List<?> result = findByNamedParam(queryString, paramName, value);
141 if (result.size() != 1) {
142 String message = "";
143 if (result.isEmpty()) {
144 message = "The desired " + objectName
145 + " does not exist.";
146 } else if (result.size() > 1) {
147 message = "The query resulted in more than one persistent "
148 + " instance.";
149 }
150 PersistenceNotificationHelper.notifyDataRetrievalFailure(message,
151 objectName);
152 }
153 return result.get(0);
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public void saveOrUpdateStrong(Object entity, final String objectName)
173 throws DataAccessException, OptimisticLockingFailureException {
174
175 Reject.ifNull(entity);
176 Reject.ifEmpty(objectName, "The name of the persistent object type "
177 + "must not be empty.");
178 try {
179 saveOrUpdate(entity);
180 } catch (HibernateOptimisticLockingFailureException holfe) {
181 String message = "The current " + objectName + " was modified or"
182 + " deleted in the meantime.";
183 PersistenceNotificationHelper.notifyOptimisticLockingFailure(
184 message, objectName, holfe);
185 }
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public void deleteStrong(Class<?> entityClass, Serializable id, final String objectName)
205 throws DataRetrievalFailureException {
206
207 Reject.ifEmpty(objectName, "The name of the persistent object type "
208 + "must not be empty.");
209 Object toDelete = null;
210 try {
211 toDelete = getByIdStrong(entityClass, id, objectName);
212 } catch (DataRetrievalFailureException e) {
213 String message = "The current " + objectName + " was "
214 + "deleted in the meantime.";
215 PersistenceNotificationHelper.notifyOptimisticLockingFailure(
216 message, objectName, null);
217 }
218 delete(toDelete);
219 }
220
221
222
223
224
225
226
227 int m_firstResult = QueryObject.NO_CONSTRAINT;
228
229
230
231
232
233
234
235
236
237 @Override
238 protected void prepareQuery(Query queryObject) {
239 super.prepareQuery(queryObject);
240
241 if (getFirstResult() != QueryObject.NO_CONSTRAINT) {
242 queryObject.setFirstResult(getFirstResult());
243 }
244
245 }
246
247
248
249
250 @Override
251 protected void prepareCriteria(Criteria criteria) {
252 super.prepareCriteria(criteria);
253
254 if (getFirstResult() != QueryObject.NO_CONSTRAINT) {
255 criteria.setFirstResult(getFirstResult());
256 }
257
258 }
259
260
261
262
263
264
265
266
267 public int findCountByCriteria(final DetachedCriteria criteria) throws DataAccessException {
268
269 Assert.notNull(criteria, "DetachedCriteria must not be null");
270 Object result = executeWithNativeSession(new HibernateCallback() {
271 public Object doInHibernate(Session session) throws HibernateException {
272 Criteria executableCriteria = criteria.getExecutableCriteria(session);
273 executableCriteria.setProjection(Projections.rowCount());
274
275 prepareCriteria(executableCriteria);
276
277 return executableCriteria.uniqueResult();
278 }
279 });
280 if (result == null) {
281 result = 0;
282 }
283
284 if (result instanceof Long) { result = ((Long) result).intValue(); }
285
286 return (Integer) result;
287 }
288
289
290
291
292
293 public int getFirstResult() {
294 return m_firstResult;
295 }
296
297
298
299
300
301 public void setFirstResult(int firstResult) {
302 m_firstResult = firstResult;
303 }
304
305
306
307
308
309
310
311
312
313
314 public void createHibernateSearchIndex(final Collection<?> objects)
315 throws DataAccessException, DataRetrievalFailureException {
316
317 Assert.notNull(objects, "Objects to index by Hibernate Search must not be null");
318 executeWithNativeSession(new HibernateCallback() {
319 public Object doInHibernate(Session session) throws HibernateException {
320 FullTextSession fullTextSession = Search.getFullTextSession(session);
321
322
323 for (Object object : objects) {
324 fullTextSession.index(object);
325 }
326
327
328 return null;
329 }
330 });
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344 @SuppressWarnings("unchecked")
345 public <T> List<T> search(final Class<T> entityClass, final String[] fields, final String searchString)
346 throws DataAccessException, DataRetrievalFailureException {
347
348 Reject.ifEmpty(searchString);
349 return (List) executeWithNativeSession(new HibernateCallback() {
350 public Object doInHibernate(Session session) throws HibernateException {
351 FullTextSession fullTextSession = Search.getFullTextSession(session);
352
353 MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
354 org.apache.lucene.search.Query luceneQuery;
355 try {
356 luceneQuery = parser.parse(searchString);
357 } catch (ParseException e) {
358 return new ArrayList(0);
359 }
360 org.hibernate.Query query = fullTextSession.createFullTextQuery(luceneQuery, entityClass);
361
362 List result = (List) query.list();
363 return result;
364 }
365 });
366 }
367 }