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 CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(entityClass);
164 query.from(entityClass);
165 return new ArrayList(em.createQuery(query).getResultList());
168 public <T> List<T> list(Class<T> entityClass, Map<String, Object> equalProperties, Map<String, Object> notEqualProperties) {
169 CriteriaBuilder cb = em.getCriteriaBuilder();
170 CriteriaQuery<T> query = cb.createQuery(entityClass);
171 Root<T> root = query.from(entityClass);
172 Collection<Predicate> predicates = new HashSet<Predicate>();
173 if(equalProperties != null) {
174 for(Entry<String, Object> entry: equalProperties.entrySet()){
175 String property = entry.getKey();
176 Object value = entry.getValue();
177 predicates.add(cb.equal(root.get(property), value));
180 if(notEqualProperties != null) {
181 for(Entry<String, Object> entry: equalProperties.entrySet()){
182 String property = entry.getKey();
183 Object value = entry.getValue();
184 predicates.add(cb.notEqual(root.get(property), value));
187 query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
188 return em.createQuery(query).getResultList();
191 public <T> List<T> list(Class<T> entityClass, Object ... equalFieldNamesAndValues) {
192 if (equalFieldNamesAndValues.length % 2 != 0)
193 throw new RuntimeException("Illegal arguments count: ${equalFieldNamesAndValues.length}");
194 Map fieldValues = [:];
195 for (int i = 0; i < equalFieldNamesAndValues.length;) {
196 String field = (String) equalFieldNamesAndValues[i++];
197 Object value = equalFieldNamesAndValues[i++];
198 fieldValues["${field}"] = value;
200 return list(entityClass, fieldValues, null);
203 public List list(String jpql, Object ... paramValues) {
204 Query query = em.createQuery(jpql);
205 for (int i = 0; i < paramValues.length; i++)
206 query.setParameter(i + 1, paramValues[i]);
207 return query.getResultList();
210 public <T> T find(Class<T> entityClass, Object primaryKey) {
211 return em.find(entityClass, primaryKey);
214 public <T> T find(Class<T> entityClass, Map<String, Object> equalProperties, Map<String, Object> notEqualProperties) {
215 CriteriaBuilder cb = em.getCriteriaBuilder();
216 CriteriaQuery<T> query = cb.createQuery(entityClass);
217 Root<T> root = query.from(entityClass);
218 Collection<Predicate> predicates = new HashSet<Predicate>();
219 if(equalProperties != null) {
220 for(Entry<String, Object> entry: equalProperties.entrySet()){
221 String property = entry.getKey();
222 Object value = entry.getValue();
223 predicates.add(cb.equal(root.get(property), value));
226 if(notEqualProperties != null) {
227 for(Entry<String, Object> entry: equalProperties.entrySet()){
228 String property = entry.getKey();
229 Object value = entry.getValue();
230 predicates.add(cb.notEqual(root.get(property), value));
233 query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
236 result = em.createQuery(query).getSingleResult();
237 } catch (NoResultException e) {
238 log.info("Object not found in Database: " + e.getMessage());
243 public <T> T find(Class<T> entityClass, Object ... equalFieldNamesAndValues) {
244 if (equalFieldNamesAndValues.length % 2 != 0)
245 throw new RuntimeException("Illegal arguments count: ${equalFieldNamesAndValues.length}");
246 Map fieldValues = [:];
247 for (int i = 0; i < equalFieldNamesAndValues.length;) {
248 String field = (String) equalFieldNamesAndValues[i++];
249 Object value = equalFieldNamesAndValues[i++];
250 fieldValues["${field}"] = value;
252 return find(entityClass, fieldValues, null);
256 public Object find(String jpql, Object ... paramValues) {
257 Query query = em.createQuery(jpql);
258 for (int i = 0; i < paramValues.length; i++)
259 query.setParameter(i + 1, paramValues[i]);
260 return query.getSingleResult();
263 public boolean contains(Collection entities) {
265 entities.each {res &= contains(it)}
269 public boolean contains(Object entity) {
270 return em.contains(entity);
273 private Object getSingleResult(Query query) {
275 return query.getSingleResult()
277 catch (NoResultException e) {