indvdum@8
|
1 |
package ru.indvdum.jpa.dao
|
indvdum@8
|
2 |
import java.sql.Connection
|
indvdum@8
|
3 |
import java.sql.SQLException
|
indvdum@8
|
4 |
import java.util.Map.Entry
|
indvdum@8
|
5 |
|
indvdum@8
|
6 |
import javax.persistence.EntityManager
|
indvdum@8
|
7 |
import javax.persistence.EntityManagerFactory
|
indvdum@8
|
8 |
import javax.persistence.EntityTransaction
|
indvdum@8
|
9 |
import javax.persistence.NoResultException
|
indvdum@8
|
10 |
import javax.persistence.Persistence
|
indvdum@8
|
11 |
import javax.persistence.Query
|
indvdum@8
|
12 |
import javax.persistence.criteria.CriteriaBuilder
|
indvdum@8
|
13 |
import javax.persistence.criteria.CriteriaQuery
|
indvdum@8
|
14 |
import javax.persistence.criteria.Predicate
|
indvdum@8
|
15 |
import javax.persistence.criteria.Root
|
indvdum@8
|
16 |
import javax.sql.DataSource
|
indvdum@8
|
17 |
|
indvdum@8
|
18 |
import org.apache.commons.configuration.XMLConfiguration
|
indvdum@8
|
19 |
import org.apache.openjpa.conf.OpenJPAConfiguration
|
indvdum@8
|
20 |
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI
|
indvdum@8
|
21 |
import org.apache.openjpa.persistence.OpenJPAPersistence
|
indvdum@8
|
22 |
import org.slf4j.Logger
|
indvdum@8
|
23 |
import org.slf4j.LoggerFactory
|
indvdum@8
|
24 |
|
indvdum@19
|
25 |
import ru.indvdum.jpa.entities.AbstractEntity
|
indvdum@8
|
26 |
import ru.indvdum.jpa.props.Props
|
indvdum@8
|
27 |
|
indvdum@2
|
28 |
/**
|
indvdum@2
|
29 |
* @author indvdum (gotoindvdum[at]gmail[dot]com)
|
indvdum@2
|
30 |
* @since 08.11.2012 23:35:04
|
indvdum@2
|
31 |
*
|
indvdum@2
|
32 |
*/
|
indvdum@2
|
33 |
public class JPADataAccessObject {
|
indvdum@8
|
34 |
|
indvdum@8
|
35 |
protected static Logger log = LoggerFactory.getLogger(JPADataAccessObject.class.getSimpleName());
|
indvdum@7
|
36 |
protected static String persistenceUnitName = null;
|
indvdum@5
|
37 |
protected static EntityManagerFactory emf = Persistence.createEntityManagerFactory(getPersistenceUnitName(), JPAPropertySelector.select());
|
indvdum@2
|
38 |
protected EntityManager em = emf.createEntityManager();
|
indvdum@9
|
39 |
protected EntityTransaction tx = null;
|
indvdum@2
|
40 |
|
indvdum@2
|
41 |
JPADataAccessObject() {
|
indvdum@9
|
42 |
tx = em.getTransaction();
|
indvdum@9
|
43 |
tx.begin();
|
indvdum@9
|
44 |
}
|
indvdum@9
|
45 |
|
indvdum@9
|
46 |
void close() {
|
indvdum@9
|
47 |
commit()
|
indvdum@9
|
48 |
em.close()
|
indvdum@9
|
49 |
em = null
|
indvdum@9
|
50 |
}
|
indvdum@9
|
51 |
|
indvdum@9
|
52 |
void commit() {
|
indvdum@9
|
53 |
if(tx != null && tx.isActive()) {
|
indvdum@9
|
54 |
tx.commit()
|
indvdum@9
|
55 |
}
|
indvdum@9
|
56 |
}
|
indvdum@9
|
57 |
|
indvdum@9
|
58 |
void rollback() {
|
indvdum@9
|
59 |
if(tx != null && tx.isActive()) {
|
indvdum@9
|
60 |
tx.rollback()
|
indvdum@9
|
61 |
}
|
indvdum@8
|
62 |
}
|
indvdum@16
|
63 |
|
indvdum@13
|
64 |
void detach(Object entity) {
|
indvdum@13
|
65 |
em.detach(entity);
|
indvdum@13
|
66 |
}
|
indvdum@8
|
67 |
|
indvdum@8
|
68 |
protected static String getPersistenceUnitName() {
|
indvdum@8
|
69 |
if (persistenceUnitName != null)
|
indvdum@8
|
70 |
return persistenceUnitName;
|
indvdum@8
|
71 |
|
indvdum@8
|
72 |
if (persistenceUnitName == null)
|
indvdum@8
|
73 |
persistenceUnitName = System.getProperty(Props.PERSISTANCE_UNIT_NAME_PROPERTY);
|
indvdum@8
|
74 |
if (persistenceUnitName == null) {
|
indvdum@8
|
75 |
try {
|
indvdum@8
|
76 |
persistenceUnitName = ResourceBundle.getBundle(Props.JPADAO_PROPERTY_FILE).getString(Props.PERSISTANCE_UNIT_NAME_PROPERTY);
|
indvdum@8
|
77 |
} catch (MissingResourceException e) {
|
indvdum@8
|
78 |
log.info("Configuration file " + Props.JPADAO_PROPERTY_FILE + ".properties not found");
|
indvdum@8
|
79 |
}
|
indvdum@8
|
80 |
}
|
indvdum@8
|
81 |
if (persistenceUnitName == null) {
|
indvdum@8
|
82 |
XMLConfiguration conf = new XMLConfiguration("META-INF/persistence.xml");
|
indvdum@8
|
83 |
persistenceUnitName = conf.getString("persistence-unit[@name]");
|
indvdum@8
|
84 |
}
|
indvdum@8
|
85 |
if (persistenceUnitName == null)
|
indvdum@8
|
86 |
persistenceUnitName = "database";
|
indvdum@8
|
87 |
return persistenceUnitName;
|
indvdum@8
|
88 |
}
|
indvdum@2
|
89 |
|
indvdum@2
|
90 |
public static Connection getSQLConnection() throws SQLException {
|
indvdum@2
|
91 |
OpenJPAEntityManagerFactorySPI openjpaemf = (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.cast(emf);
|
indvdum@2
|
92 |
OpenJPAConfiguration conf = openjpaemf.getConfiguration();
|
indvdum@2
|
93 |
DataSource ds = (DataSource) conf.getConnectionFactory();
|
indvdum@2
|
94 |
return ds.getConnection();
|
indvdum@2
|
95 |
}
|
indvdum@2
|
96 |
|
indvdum@2
|
97 |
public <T> T mergeAndRefresh(T object) {
|
indvdum@2
|
98 |
def merged = em.merge(object)
|
indvdum@2
|
99 |
em.refresh(merged)
|
indvdum@2
|
100 |
|
indvdum@2
|
101 |
merged
|
indvdum@2
|
102 |
}
|
indvdum@2
|
103 |
|
indvdum@19
|
104 |
public <T extends AbstractEntity> T read(T object) {
|
indvdum@19
|
105 |
return find(object.class, object.getIdentifierValue())
|
indvdum@19
|
106 |
}
|
indvdum@19
|
107 |
|
indvdum@2
|
108 |
public <T> T merge(T object) {
|
indvdum@2
|
109 |
em.merge(object)
|
indvdum@2
|
110 |
}
|
indvdum@2
|
111 |
|
indvdum@2
|
112 |
void refresh(Object ... refreshObjects) {
|
indvdum@2
|
113 |
for(object in refreshObjects) {
|
indvdum@2
|
114 |
em.refresh(object)
|
indvdum@2
|
115 |
}
|
indvdum@2
|
116 |
}
|
indvdum@2
|
117 |
|
indvdum@2
|
118 |
boolean persist(Object ... persistanceQueue) {
|
indvdum@2
|
119 |
persistAndRemove(persistanceQueue, new Object[0])
|
indvdum@2
|
120 |
}
|
indvdum@2
|
121 |
|
indvdum@2
|
122 |
boolean persist(Collection entities) {
|
indvdum@2
|
123 |
persistAndRemove(entities.toArray(), new Object[0])
|
indvdum@2
|
124 |
}
|
indvdum@2
|
125 |
|
indvdum@2
|
126 |
boolean remove(Object ... removeQueue) {
|
indvdum@2
|
127 |
persistAndRemove(new Object[0], removeQueue)
|
indvdum@2
|
128 |
}
|
indvdum@2
|
129 |
|
indvdum@2
|
130 |
boolean remove(Collection entities) {
|
indvdum@2
|
131 |
persistAndRemove(new Object[0], entities.toArray())
|
indvdum@2
|
132 |
}
|
indvdum@2
|
133 |
|
indvdum@2
|
134 |
synchronized boolean persistAndRemove(Object[] persistanceQueue, Object[] removeQueue) {
|
indvdum@2
|
135 |
|
indvdum@2
|
136 |
try {
|
indvdum@2
|
137 |
|
indvdum@2
|
138 |
if(persistanceQueue != null) {
|
indvdum@2
|
139 |
for(object in persistanceQueue) {
|
indvdum@2
|
140 |
if(object != null) {
|
indvdum@2
|
141 |
em.persist(object)
|
indvdum@2
|
142 |
}
|
indvdum@2
|
143 |
}
|
indvdum@2
|
144 |
}
|
indvdum@2
|
145 |
|
indvdum@2
|
146 |
if(removeQueue != null) {
|
indvdum@2
|
147 |
for(object in removeQueue) {
|
indvdum@2
|
148 |
if(object != null) {
|
indvdum@2
|
149 |
em.remove(object)
|
indvdum@2
|
150 |
}
|
indvdum@2
|
151 |
}
|
indvdum@2
|
152 |
}
|
indvdum@2
|
153 |
}
|
indvdum@2
|
154 |
catch(Throwable t) {
|
indvdum@2
|
155 |
log.error("Error while synchronizing with Database: ", t);
|
indvdum@9
|
156 |
return false;
|
indvdum@2
|
157 |
}
|
indvdum@2
|
158 |
|
indvdum@2
|
159 |
return true
|
indvdum@2
|
160 |
}
|
indvdum@2
|
161 |
|
indvdum@16
|
162 |
public <T> List<T> list(Class<T> entityClass) {
|
indvdum@20
|
163 |
// TODO: check for AbstractEntity type of T
|
indvdum@16
|
164 |
CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(entityClass);
|
indvdum@16
|
165 |
query.from(entityClass);
|
indvdum@16
|
166 |
return new ArrayList(em.createQuery(query).getResultList());
|
indvdum@2
|
167 |
}
|
indvdum@2
|
168 |
|
indvdum@2
|
169 |
public <T> List<T> list(Class<T> entityClass, Map<String, Object> equalProperties, Map<String, Object> notEqualProperties) {
|
indvdum@2
|
170 |
CriteriaBuilder cb = em.getCriteriaBuilder();
|
indvdum@2
|
171 |
CriteriaQuery<T> query = cb.createQuery(entityClass);
|
indvdum@2
|
172 |
Root<T> root = query.from(entityClass);
|
indvdum@2
|
173 |
Collection<Predicate> predicates = new HashSet<Predicate>();
|
indvdum@2
|
174 |
if(equalProperties != null) {
|
indvdum@2
|
175 |
for(Entry<String, Object> entry: equalProperties.entrySet()){
|
indvdum@2
|
176 |
String property = entry.getKey();
|
indvdum@2
|
177 |
Object value = entry.getValue();
|
indvdum@2
|
178 |
predicates.add(cb.equal(root.get(property), value));
|
indvdum@2
|
179 |
}
|
indvdum@2
|
180 |
}
|
indvdum@2
|
181 |
if(notEqualProperties != null) {
|
indvdum@2
|
182 |
for(Entry<String, Object> entry: equalProperties.entrySet()){
|
indvdum@2
|
183 |
String property = entry.getKey();
|
indvdum@2
|
184 |
Object value = entry.getValue();
|
indvdum@2
|
185 |
predicates.add(cb.notEqual(root.get(property), value));
|
indvdum@2
|
186 |
}
|
indvdum@2
|
187 |
}
|
indvdum@2
|
188 |
query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
|
indvdum@2
|
189 |
return em.createQuery(query).getResultList();
|
indvdum@2
|
190 |
}
|
indvdum@2
|
191 |
|
indvdum@16
|
192 |
public <T> List<T> list(Class<T> entityClass, Object ... equalFieldNamesAndValues) {
|
indvdum@16
|
193 |
if (equalFieldNamesAndValues.length % 2 != 0)
|
indvdum@16
|
194 |
throw new RuntimeException("Illegal arguments count: ${equalFieldNamesAndValues.length}");
|
indvdum@16
|
195 |
Map fieldValues = [:];
|
indvdum@16
|
196 |
for (int i = 0; i < equalFieldNamesAndValues.length;) {
|
indvdum@16
|
197 |
String field = (String) equalFieldNamesAndValues[i++];
|
indvdum@16
|
198 |
Object value = equalFieldNamesAndValues[i++];
|
indvdum@16
|
199 |
fieldValues["${field}"] = value;
|
indvdum@16
|
200 |
}
|
indvdum@16
|
201 |
return list(entityClass, fieldValues, null);
|
indvdum@16
|
202 |
}
|
indvdum@16
|
203 |
|
indvdum@16
|
204 |
public List list(String jpql, Object ... paramValues) {
|
indvdum@16
|
205 |
Query query = em.createQuery(jpql);
|
indvdum@16
|
206 |
for (int i = 0; i < paramValues.length; i++)
|
indvdum@16
|
207 |
query.setParameter(i + 1, paramValues[i]);
|
indvdum@16
|
208 |
return query.getResultList();
|
indvdum@16
|
209 |
}
|
indvdum@16
|
210 |
|
indvdum@16
|
211 |
public <T> T find(Class<T> entityClass, Object primaryKey) {
|
indvdum@16
|
212 |
return em.find(entityClass, primaryKey);
|
indvdum@16
|
213 |
}
|
indvdum@16
|
214 |
|
indvdum@2
|
215 |
public <T> T find(Class<T> entityClass, Map<String, Object> equalProperties, Map<String, Object> notEqualProperties) {
|
indvdum@2
|
216 |
CriteriaBuilder cb = em.getCriteriaBuilder();
|
indvdum@2
|
217 |
CriteriaQuery<T> query = cb.createQuery(entityClass);
|
indvdum@2
|
218 |
Root<T> root = query.from(entityClass);
|
indvdum@2
|
219 |
Collection<Predicate> predicates = new HashSet<Predicate>();
|
indvdum@2
|
220 |
if(equalProperties != null) {
|
indvdum@2
|
221 |
for(Entry<String, Object> entry: equalProperties.entrySet()){
|
indvdum@2
|
222 |
String property = entry.getKey();
|
indvdum@2
|
223 |
Object value = entry.getValue();
|
indvdum@2
|
224 |
predicates.add(cb.equal(root.get(property), value));
|
indvdum@2
|
225 |
}
|
indvdum@2
|
226 |
}
|
indvdum@2
|
227 |
if(notEqualProperties != null) {
|
indvdum@2
|
228 |
for(Entry<String, Object> entry: equalProperties.entrySet()){
|
indvdum@2
|
229 |
String property = entry.getKey();
|
indvdum@2
|
230 |
Object value = entry.getValue();
|
indvdum@2
|
231 |
predicates.add(cb.notEqual(root.get(property), value));
|
indvdum@2
|
232 |
}
|
indvdum@2
|
233 |
}
|
indvdum@2
|
234 |
query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
|
indvdum@2
|
235 |
T result = null;
|
indvdum@2
|
236 |
try {
|
indvdum@21
|
237 |
result = getSingleResult(em.createQuery(query));
|
indvdum@2
|
238 |
} catch (NoResultException e) {
|
indvdum@11
|
239 |
log.info("Object not found in Database: " + e.getMessage());
|
indvdum@2
|
240 |
}
|
indvdum@2
|
241 |
return result;
|
indvdum@2
|
242 |
}
|
indvdum@2
|
243 |
|
indvdum@16
|
244 |
public <T> T find(Class<T> entityClass, Object ... equalFieldNamesAndValues) {
|
indvdum@16
|
245 |
if (equalFieldNamesAndValues.length % 2 != 0)
|
indvdum@16
|
246 |
throw new RuntimeException("Illegal arguments count: ${equalFieldNamesAndValues.length}");
|
indvdum@16
|
247 |
Map fieldValues = [:];
|
indvdum@16
|
248 |
for (int i = 0; i < equalFieldNamesAndValues.length;) {
|
indvdum@16
|
249 |
String field = (String) equalFieldNamesAndValues[i++];
|
indvdum@16
|
250 |
Object value = equalFieldNamesAndValues[i++];
|
indvdum@16
|
251 |
fieldValues["${field}"] = value;
|
indvdum@16
|
252 |
}
|
indvdum@16
|
253 |
return find(entityClass, fieldValues, null);
|
indvdum@9
|
254 |
}
|
indvdum@19
|
255 |
|
indvdum@19
|
256 |
|
indvdum@16
|
257 |
public Object find(String jpql, Object ... paramValues) {
|
indvdum@16
|
258 |
Query query = em.createQuery(jpql);
|
indvdum@16
|
259 |
for (int i = 0; i < paramValues.length; i++)
|
indvdum@16
|
260 |
query.setParameter(i + 1, paramValues[i]);
|
indvdum@21
|
261 |
return getSingleResult(query);
|
indvdum@2
|
262 |
}
|
indvdum@2
|
263 |
|
indvdum@2
|
264 |
public boolean contains(Collection entities) {
|
indvdum@2
|
265 |
boolean res = true;
|
indvdum@2
|
266 |
entities.each {res &= contains(it)}
|
indvdum@2
|
267 |
return res
|
indvdum@2
|
268 |
}
|
indvdum@2
|
269 |
|
indvdum@2
|
270 |
public boolean contains(Object entity) {
|
indvdum@2
|
271 |
return em.contains(entity);
|
indvdum@2
|
272 |
}
|
indvdum@2
|
273 |
|
indvdum@2
|
274 |
private Object getSingleResult(Query query) {
|
indvdum@2
|
275 |
try {
|
indvdum@2
|
276 |
return query.getSingleResult()
|
indvdum@2
|
277 |
}
|
indvdum@2
|
278 |
catch (NoResultException e) {
|
indvdum@2
|
279 |
return null
|
indvdum@2
|
280 |
}
|
indvdum@2
|
281 |
}
|
indvdum@2
|
282 |
}
|