001 // Copyright 2007-2008 Thiago H. de Paula Figueiredo
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // 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
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package br.com.arsmachina.dao.hibernate;
016
017 import java.io.Serializable;
018 import java.lang.reflect.ParameterizedType;
019 import java.lang.reflect.Type;
020 import java.util.List;
021
022 import org.hibernate.Criteria;
023 import org.hibernate.SessionFactory;
024 import org.hibernate.classic.Session;
025 import org.hibernate.criterion.Example;
026 import org.hibernate.metadata.ClassMetadata;
027
028 import br.com.arsmachina.dao.DAO;
029 import br.com.arsmachina.dao.SortCriterion;
030
031 /**
032 * {@link AbstractDAO} implementation using Hibernate. All methods use {@link #getSession()} to get
033 * a {@link Session}. All methods delegate its calls to an internal {@link ReadableDAOImpl} or
034 * {@link WriteableDAOImpl} instance.
035 *
036 * @author Thiago H. de Paula Figueiredo
037 * @param <T> the entity class related to this DAO.
038 * @param <K> the type of the field that represents the entity class' primary key.
039 */
040 public class GenericDAOImpl<T, K extends Serializable> implements DAO<T, K> {
041
042 final private InternalReadableDAOImpl readableDAO;
043
044 final private InternalWriteableDAOImpl writeableDAO;
045
046 /**
047 * Single public constructor.
048 *
049 * @param sessionFactory a {@link SessionFactory}. It cannot be null.
050 */
051 @SuppressWarnings("unchecked")
052 public GenericDAOImpl(SessionFactory sessionFactory) {
053
054 if (sessionFactory == null) {
055 throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
056 }
057
058 final Type genericSuperclass = getClass().getGenericSuperclass();
059 final ParameterizedType parameterizedType = ((ParameterizedType) genericSuperclass);
060 Class clasz = (Class<T>) parameterizedType.getActualTypeArguments()[0];
061
062 readableDAO = new InternalReadableDAOImpl(clasz, sessionFactory);
063 writeableDAO = new InternalWriteableDAOImpl(clasz, sessionFactory);
064
065 }
066
067 /**
068 * Constructor made specifically for {@link ConcreteDAOImpl}. It shouldn't be used in
069 * any other class.
070 *
071 * @param clasz the entity class. It cannot be null.
072 * @param sessionFactory a {@link SessionFactory}. It cannot be null.
073 */
074 GenericDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
075
076 if (clasz == null) {
077 throw new IllegalArgumentException("Parameter clasz cannot be null");
078 }
079
080 if (sessionFactory == null) {
081 throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
082 }
083
084 readableDAO = new InternalReadableDAOImpl(clasz, sessionFactory);
085 writeableDAO = new InternalWriteableDAOImpl(clasz, sessionFactory);
086
087 }
088
089 public int countAll() {
090 return readableDAO.countAll();
091 }
092
093 public List<T> findAll() {
094 return readableDAO.findAll();
095 }
096
097 public List<T> findAll(int firstResult, int maximumResults, SortCriterion... sortingConstraints) {
098 return readableDAO.findAll(firstResult, maximumResults, sortingConstraints);
099 }
100
101 public List<T> findByExample(T example) {
102 return readableDAO.findByExample(example);
103 }
104
105 public T findById(K id) {
106 return readableDAO.findById(id);
107 }
108
109 public List<T> findByIds(K... ids) {
110 return readableDAO.findByIds(ids);
111 }
112
113 public void refresh(T object) {
114 readableDAO.refresh(object);
115 }
116
117 public void delete(T object) {
118 writeableDAO.delete(object);
119 }
120
121 public void delete(K id) {
122 writeableDAO.delete(id);
123 }
124
125 public void evict(T object) {
126 writeableDAO.evict(object);
127 }
128
129 public boolean isPersistent(T object) {
130 return writeableDAO.isPersistent(object);
131 }
132
133 public void save(T object) {
134 writeableDAO.save(object);
135 }
136
137 public T update(T object) {
138 return writeableDAO.update(object);
139 }
140
141 public T reattach(T object) {
142 return readableDAO.reattach(object);
143 }
144
145 public SortCriterion[] getDefaultSortCriteria() {
146 return readableDAO.getDefaultSortCriteria();
147 }
148
149 /**
150 * Invokes <code>readableDAO.addSortCriteria()<code>.
151 * @param criteria
152 * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#addSortCriteria(org.hibernate.Criteria)
153 */
154 protected void addSortCriteria(Criteria criteria) {
155 readableDAO.addSortCriteria(criteria);
156 }
157
158
159
160 /**
161 * Invokes <code>delegate.addSortCriteria()<code>.
162 * @param criteria
163 * @param sortCriteria
164 * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#addSortCriteria(org.hibernate.Criteria, br.com.arsmachina.dao.SortCriterion[])
165 */
166 public final void addSortCriteria(Criteria criteria, SortCriterion... sortCriteria) {
167 readableDAO.addSortCriteria(criteria, sortCriteria);
168 }
169
170 /**
171 * Invokes <code>readableDAO.createCriteria()<code>.
172 * @return
173 * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria()
174 */
175 protected Criteria createCriteria() {
176 return readableDAO.createCriteria();
177 }
178
179
180
181 /**
182 * Invokes <code>delegate.createCriteria()<code>.
183 * @param sortCriteria
184 * @return
185 * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria(br.com.arsmachina.dao.SortCriterion[])
186 */
187 protected Criteria createCriteria(SortCriterion... sortCriteria) {
188 return readableDAO.createCriteria(sortCriteria);
189 }
190
191
192
193 /**
194 * Invokes <code>delegate.createCriteria()<code>.
195 * @param firstIndex
196 * @param maximumResults
197 * @param sortCriteria
198 * @return
199 * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria(int, int, br.com.arsmachina.dao.SortCriterion[])
200 */
201 public Criteria createCriteria(int firstIndex, int maximumResults,
202 SortCriterion... sortCriteria) {
203 return readableDAO.createCriteria(firstIndex, maximumResults, sortCriteria);
204 }
205
206 /**
207 * Invokes <code>readableDAO.createExample()<code>.
208 * @param entity
209 * @return
210 * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createExample(java.lang.Object)
211 */
212 protected Example createExample(T entity) {
213 return readableDAO.createExample(entity);
214 }
215
216 /**
217 * Returns the entity class handled by this DAO.
218 *
219 * @return a {@link Class<T>}.
220 */
221 protected final Class<T> getEntityClass() {
222 return readableDAO.getEntityClass();
223 }
224
225 /**
226 * Returns a {@link Session}. This implementation returns
227 * {@link SessionFactory#getCurrentSession()} and can be overriden if needed.
228 *
229 * @return a {@link Session}.
230 */
231 protected Session getSession() {
232 return getSessionFactory().getCurrentSession();
233 }
234
235 /**
236 * Returns this DAO's {@link SessionFactory}.
237 *
238 * @return a {@link SessionFactory}.
239 */
240 protected final SessionFactory getSessionFactory() {
241 return readableDAO.getSessionFactory();
242 }
243
244 /**
245 * Returns the {@link ClassMetadata} for the corresponding entity class.
246 *
247 * @return a {@link ClassMetadata}.
248 */
249 final protected ClassMetadata getClassMetadata() {
250 return readableDAO.getClassMetadata();
251 }
252
253 /**
254 * Returns the name of the property.
255 *
256 * @return a {@link String}.
257 */
258 public String getPrimaryKeyPropertyName() {
259 return readableDAO.getPrimaryKeyPropertyName();
260 }
261
262 /**
263 * Concrete {@link ReadableDAOImpl} subclass.
264 *
265 * @author Thiago H. de Paula Figueiredo
266 * @param <T>
267 * @param <K>
268 */
269 private final class InternalReadableDAOImpl extends ReadableDAOImpl<T, K> {
270
271 public InternalReadableDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
272 super(clasz, sessionFactory);
273 }
274
275 }
276
277 /**
278 * Concrete {@link WriteableDAOImpl} subclass.
279 *
280 * @author Thiago H. de Paula Figueiredo
281 * @param <T>
282 * @param <K>
283 */
284 private final class InternalWriteableDAOImpl extends WriteableDAOImpl<T, K> {
285
286 public InternalWriteableDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
287 super(clasz, sessionFactory);
288 }
289
290 }
291
292 }