1 package ru.indvdum.jpa.dao
2 import java.sql.Connection
3 import java.sql.SQLException
4 import java.util.Map.Entry
6 import javax.persistence.EntityManager
7 import javax.persistence.EntityManagerFactory
8 import javax.persistence.EntityTransaction
9 import javax.persistence.NoResultException
10 import javax.persistence.Persistence
11 import javax.persistence.Query
12 import javax.persistence.criteria.CriteriaBuilder
13 import javax.persistence.criteria.CriteriaQuery
14 import javax.persistence.criteria.Predicate
15 import javax.persistence.criteria.Root
16 import javax.sql.DataSource
18 import org.apache.commons.configuration.XMLConfiguration
19 import org.apache.openjpa.conf.OpenJPAConfiguration
20 import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI
21 import org.apache.openjpa.persistence.OpenJPAPersistence
22 import org.slf4j.Logger
23 import org.slf4j.LoggerFactory
25 import ru.indvdum.jpa.entities.AbstractEntity
26 import ru.indvdum.jpa.props.Props
29 * @author indvdum (gotoindvdum[at]gmail[dot]com)
30 * @since 08.11.2012 23:35:04
33 public class JPADataAccessObject {
35 protected static Logger log = LoggerFactory.getLogger(JPADataAccessObject.class.getSimpleName());
36 protected static String persistenceUnitName = null;
37 protected static EntityManagerFactory emf = Persistence.createEntityManagerFactory(getPersistenceUnitName(), JPAPropertySelector.select());
38 protected EntityManager em = emf.createEntityManager();
39 protected EntityTransaction tx = null;
41 JPADataAccessObject() {
42 tx = em.getTransaction();
53 if(tx != null && tx.isActive()) {
59 if(tx != null && tx.isActive()) {
64 void detach(Object entity) {
68 protected static String getPersistenceUnitName() {
69 if (persistenceUnitName != null)
70 return persistenceUnitName;
72 if (persistenceUnitName == null)
73 persistenceUnitName = System.getProperty(Props.PERSISTANCE_UNIT_NAME_PROPERTY);
74 if (persistenceUnitName == null) {
76 persistenceUnitName = ResourceBundle.getBundle(Props.JPADAO_PROPERTY_FILE).getString(Props.PERSISTANCE_UNIT_NAME_PROPERTY);
77 } catch (MissingResourceException e) {
78 log.info("Configuration file " + Props.JPADAO_PROPERTY_FILE + ".properties not found");
81 if (persistenceUnitName == null) {
82 XMLConfiguration conf = new XMLConfiguration("META-INF/persistence.xml");
83 persistenceUnitName = conf.getString("persistence-unit[@name]");
85 if (persistenceUnitName == null)
86 persistenceUnitName = "database";
87 return persistenceUnitName;
90 public static Connection getSQLConnection() throws SQLException {
91 OpenJPAEntityManagerFactorySPI openjpaemf = (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.cast(emf);
92 OpenJPAConfiguration conf = openjpaemf.getConfiguration();
93 DataSource ds = (DataSource) conf.getConnectionFactory();
94 return ds.getConnection();
97 public <T> T mergeAndRefresh(T object) {
98 def merged = em.merge(object)
104 public <T extends AbstractEntity> T read(T object) {
105 return find(object.class, object.getIdentifierValue())
108 public <T> T merge(T object) {
112 void refresh(Object ... refreshObjects) {
113 for(object in refreshObjects) {
118 boolean persist(Object ... persistanceQueue) {
119 persistAndRemove(persistanceQueue, new Object[0])
122 boolean persist(Collection entities) {
123 persistAndRemove(entities.toArray(), new Object[0])
126 boolean remove(Object ... removeQueue) {
127 persistAndRemove(new Object[0], removeQueue)
130 boolean remove(Collection entities) {
131 persistAndRemove(new Object[0], entities.toArray())
134 synchronized boolean persistAndRemove(Object[] persistanceQueue, Object[] removeQueue) {
138 if(persistanceQueue != null) {
139 for(object in persistanceQueue) {
146 if(removeQueue != null) {
147 for(object in removeQueue) {
155 log.error("Error while synchronizing with Database: ", t);
162 public <T> List<T> list(Class<T> entityClass) {
163 // TODO: check for AbstractEntity type of T
164 CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(entityClass);
165 query.from(entityClass);
166 return new ArrayList(em.createQuery(query).getResultList());
169 public <T> List<T> list(Class<T> entityClass, Map<String, Object> equalProperties, Map<String, Object> notEqualProperties) {
170 CriteriaBuilder cb = em.getCriteriaBuilder();
171 CriteriaQuery<T> query = cb.createQuery(entityClass);
172 Root<T> root = query.from(entityClass);
173 Collection<Predicate> predicates = new HashSet<Predicate>();
174 if(equalProperties != null) {
175 for(Entry<String, Object> entry: equalProperties.entrySet()){
176 String property = entry.getKey();
177 Object value = entry.getValue();
178 predicates.add(cb.equal(root.get(property), value));
181 if(notEqualProperties != null) {
182 for(Entry<String, Object> entry: equalProperties.entrySet()){
183 String property = entry.getKey();
184 Object value = entry.getValue();
185 predicates.add(cb.notEqual(root.get(property), value));
188 query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
189 return em.createQuery(query).getResultList();
192 public <T> List<T> list(Class<T> entityClass, Object ... equalFieldNamesAndValues) {
193 if (equalFieldNamesAndValues.length % 2 != 0)
194 throw new RuntimeException("Illegal arguments count: ${equalFieldNamesAndValues.length}");
195 Map fieldValues = [:];
196 for (int i = 0; i < equalFieldNamesAndValues.length;) {
197 String field = (String) equalFieldNamesAndValues[i++];
198 Object value = equalFieldNamesAndValues[i++];
199 fieldValues["${field}"] = value;
201 return list(entityClass, fieldValues, null);
204 public List list(String jpql, Object ... paramValues) {
205 Query query = em.createQuery(jpql);
206 for (int i = 0; i < paramValues.length; i++)
207 query.setParameter(i + 1, paramValues[i]);
208 return query.getResultList();
211 public <T> T find(Class<T> entityClass, Object primaryKey) {
212 return em.find(entityClass, primaryKey);
215 public <T> T find(Class<T> entityClass, Map<String, Object> equalProperties, Map<String, Object> notEqualProperties) {
216 CriteriaBuilder cb = em.getCriteriaBuilder();
217 CriteriaQuery<T> query = cb.createQuery(entityClass);
218 Root<T> root = query.from(entityClass);
219 Collection<Predicate> predicates = new HashSet<Predicate>();
220 if(equalProperties != null) {
221 for(Entry<String, Object> entry: equalProperties.entrySet()){
222 String property = entry.getKey();
223 Object value = entry.getValue();
224 predicates.add(cb.equal(root.get(property), value));
227 if(notEqualProperties != null) {
228 for(Entry<String, Object> entry: equalProperties.entrySet()){
229 String property = entry.getKey();
230 Object value = entry.getValue();
231 predicates.add(cb.notEqual(root.get(property), value));
234 query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
237 result = getSingleResult(em.createQuery(query));
238 } catch (NoResultException e) {
239 log.info("Object not found in Database: " + e.getMessage());
244 public <T> T find(Class<T> entityClass, Object ... equalFieldNamesAndValues) {
245 if (equalFieldNamesAndValues.length % 2 != 0)
246 throw new RuntimeException("Illegal arguments count: ${equalFieldNamesAndValues.length}");
247 Map fieldValues = [:];
248 for (int i = 0; i < equalFieldNamesAndValues.length;) {
249 String field = (String) equalFieldNamesAndValues[i++];
250 Object value = equalFieldNamesAndValues[i++];
251 fieldValues["${field}"] = value;
253 return find(entityClass, fieldValues, null);
257 public Object find(String jpql, Object ... paramValues) {
258 Query query = em.createQuery(jpql);
259 for (int i = 0; i < paramValues.length; i++)
260 query.setParameter(i + 1, paramValues[i]);
261 return getSingleResult(query);
264 public boolean contains(Collection entities) {
266 entities.each {res &= contains(it)}
270 public boolean contains(Object entity) {
271 return em.contains(entity);
274 private Object getSingleResult(Query query) {
276 return query.getSingleResult()
278 catch (NoResultException e) {