2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.api
.service
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.List
;
17 import java
.util
.UUID
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.hibernate
.LockOptions
;
21 import org
.hibernate
.Session
;
22 import org
.springframework
.context
.ApplicationContext
;
23 import org
.springframework
.context
.ApplicationContextAware
;
24 import org
.springframework
.dao
.DataAccessException
;
25 import org
.springframework
.transaction
.annotation
.Transactional
;
27 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
28 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
29 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
30 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmEntityDao
;
31 import eu
.etaxonomy
.cdm
.persistence
.dto
.MergeResult
;
32 import eu
.etaxonomy
.cdm
.persistence
.query
.Grouping
;
33 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
35 public abstract class ServiceBase
<T
extends CdmBase
, DAO
extends ICdmEntityDao
<T
>> implements IService
<T
>, ApplicationContextAware
{
36 @SuppressWarnings("unused")
37 private static final Logger logger
= Logger
.getLogger(ServiceBase
.class);
39 //flush after saving this number of objects
40 int flushAfterNo
= 2000;
41 protected ApplicationContext appContext
;
46 @Transactional(readOnly
= true)
47 public void lock(T t
, LockOptions lockOptions
) {
48 dao
.lock(t
, lockOptions
);
52 @Transactional(readOnly
= true)
53 public void refresh(T t
, LockOptions lockOptions
, List
<String
> propertyPaths
) {
54 dao
.refresh(t
, lockOptions
, propertyPaths
);
58 @Transactional(readOnly
= false)
64 @Transactional(readOnly
= true)
65 public int count(Class
<?
extends T
> clazz
) {
66 return dao
.count(clazz
);
70 @Transactional(readOnly
= false)
71 public DeleteResult
delete(UUID persistentObjectUUID
) {
72 T persistentObject
= dao
.findByUuid(persistentObjectUUID
);
73 return delete(persistentObject
);
77 @Transactional(readOnly
= false)
78 public DeleteResult
delete(Collection
<UUID
> persistentObjectUUIDs
) {
79 DeleteResult result
= new DeleteResult();
80 for(UUID persistentObjectUUID
: persistentObjectUUIDs
) {
81 T persistentObject
= dao
.findByUuid(persistentObjectUUID
);
82 DeleteResult dr
= delete(persistentObject
);
83 result
.includeResult(dr
);
89 @Transactional(readOnly
= false)
90 public DeleteResult
delete(T persistentObject
) {
91 DeleteResult result
= new DeleteResult();
93 dao
.delete(persistentObject
);
94 result
.addDeletedObject(persistentObject
);
95 } catch(DataAccessException e
){
97 result
.addException(e
);
105 @Transactional(readOnly
= true)
106 public boolean exists(UUID uuid
) {
107 return dao
.exists(uuid
);
111 @Transactional(readOnly
= true)
112 public List
<T
> find(Set
<UUID
> uuidSet
) {
113 return dao
.list(uuidSet
, null, null, null, null);
117 @Transactional(readOnly
= true)
118 public List
<T
> findById(Set
<Integer
> idSet
) { //can't be called find(Set<Integer>) as this conflicts with find(Set<UUID)
119 return dao
.loadList(idSet
, null);
123 @Transactional(readOnly
= true)
124 public List
<T
> loadByIds(List
<Integer
> idList
, List
<String
> propertyPaths
){
125 return dao
.loadList(idList
, propertyPaths
);
129 @Transactional(readOnly
= true)
130 public T
find(UUID uuid
) {
131 return uuid
== null ?
null : dao
.findByUuid(uuid
);
135 @Transactional(readOnly
= true)
136 public T
findWithoutFlush(UUID uuid
) {
137 return uuid
== null ?
null : dao
.findByUuidWithoutFlush(uuid
);
141 @Transactional(readOnly
= true)
142 public T
find(int id
) {
143 return dao
.findById(id
);
147 @Transactional(readOnly
= true)
148 public Session
getSession() {
149 return dao
.getSession();
153 @Transactional(readOnly
= true)
154 public List
<Object
[]> group(Class
<?
extends T
> clazz
,Integer limit
, Integer start
, List
<Grouping
> groups
, List
<String
> propertyPaths
) {
155 return dao
.group(clazz
, limit
, start
, groups
, propertyPaths
);
159 @Transactional(readOnly
= true)
160 public <S
extends T
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
161 return dao
.list(type
,limit
, start
, orderHints
, propertyPaths
);
165 @Transactional(readOnly
= true)
166 public T
load(UUID uuid
) {
167 return uuid
== null ?
null : dao
.load(uuid
);
171 @Transactional(readOnly
= true)
172 public T
loadWithUpdate(UUID uuid
) {
177 @Transactional(readOnly
= true)
178 public T
load(int id
, List
<String
> propertyPaths
) {
179 return dao
.load(id
, propertyPaths
);
183 @Transactional(readOnly
= true)
184 public T
load(UUID uuid
, List
<String
> propertyPaths
){
185 return uuid
== null ?
null : dao
.load(uuid
, propertyPaths
);
189 @Transactional(readOnly
= true)
190 public List
<T
> load(List
<UUID
> uuids
, List
<String
> propertyPaths
){
195 List
<T
> entities
= new ArrayList
<T
>();
196 for(UUID uuid
: uuids
) {
197 entities
.add(uuid
== null ?
null : dao
.load(uuid
, propertyPaths
));
203 @Transactional(readOnly
= false)
204 public T
merge(T newInstance
) {
205 return dao
.merge(newInstance
);
209 @Transactional(readOnly
= false)
210 public MergeResult
<T
> merge(T newInstance
, boolean returnTransientEntity
) {
211 return dao
.merge(newInstance
, returnTransientEntity
);
215 @Transactional(readOnly
= false)
216 public List
<T
> merge(List
<T
> detachedObjects
) {
217 List
<T
> mergedObjects
= new ArrayList
<T
>();
218 for(T obj
: detachedObjects
) {
219 mergedObjects
.add(dao
.merge(obj
));
221 return mergedObjects
;
225 @Transactional(readOnly
= false)
226 public List
<MergeResult
<T
>> merge(List
<T
> detachedObjects
, boolean returnTransientEntity
) {
227 List
<MergeResult
<T
>> mergedObjects
= new ArrayList
<MergeResult
<T
>>();
228 for(T obj
: detachedObjects
) {
229 mergedObjects
.add(dao
.merge(obj
, returnTransientEntity
));
231 return mergedObjects
;
235 @Transactional(readOnly
= true)
236 public <S
extends T
> Pager
<S
> page(Class
<S
> type
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
){
237 Integer numberOfResults
= dao
.count(type
);
238 List
<S
> results
= new ArrayList
<S
>();
239 pageNumber
= pageNumber
== null ?
0 : pageNumber
;
240 if(numberOfResults
> 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
241 Integer start
= pageSize
== null ?
0 : pageSize
* pageNumber
;
242 results
= dao
.list(type
, pageSize
, start
, orderHints
,propertyPaths
);
244 return new DefaultPagerImpl
<S
>(pageNumber
, numberOfResults
, pageSize
, results
);
248 @Transactional(readOnly
= true)
249 public UUID
refresh(T persistentObject
) {
250 return dao
.refresh(persistentObject
);
254 * FIXME Candidate for harmonization
255 * is this method used, and if so, should it be exposed in the service layer?
256 * it seems a bit incongruous that we use an ORM to hide the fact that there is a
257 * database, then expose a method that talks about "rows" . . .
260 @Transactional(readOnly
= true)
261 public List
<T
> rows(String tableName
, int limit
, int start
) {
262 return dao
.rows(tableName
, limit
, start
);
266 @Transactional(readOnly
= false)
267 public Map
<UUID
, T
> save(Collection
<T
> newInstances
) {
268 return dao
.saveAll(newInstances
);
272 @Transactional(readOnly
= false)
273 public T
save(T newInstance
) {
274 return dao
.save(newInstance
);
278 @Transactional(readOnly
= false)
279 public UUID
saveOrUpdate(T transientObject
) {
280 return dao
.saveOrUpdate(transientObject
);
284 @Transactional(readOnly
= false)
285 public Map
<UUID
, T
> saveOrUpdate(Collection
<T
> transientInstances
) {
286 return dao
.saveOrUpdateAll(transientInstances
);
290 public void setApplicationContext(ApplicationContext appContext
){
291 this.appContext
= appContext
;
295 protected abstract void setDao(DAO dao
);
298 @Transactional(readOnly
= false)
299 public UUID
update(T transientObject
) {
300 return dao
.update(transientObject
);
304 @Transactional(readOnly
= true)
305 public List
<T
> list(T example
, Set
<String
> includeProperties
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
306 return dao
.list(example
, includeProperties
, limit
, start
, orderHints
, propertyPaths
);