src/main/java/ru/indvdum/jpa/dao/JPADataAccessObject.groovy
author indvdum (gotoindvdum[at]gmail[dot]com)
Thu, 20 Dec 2012 19:59:53 +0400
changeset 19 39381427da3f
parent 16 409046072775
child 20 a05948e9458c
permissions -rw-r--r--
Method read() added
     1 package ru.indvdum.jpa.dao
     2 import java.sql.Connection
     3 import java.sql.SQLException
     4 import java.util.Map.Entry
     5 
     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
    17 
    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
    24 
    25 import ru.indvdum.jpa.entities.AbstractEntity
    26 import ru.indvdum.jpa.props.Props
    27 
    28 /**
    29  * @author indvdum (gotoindvdum[at]gmail[dot]com)
    30  * @since 08.11.2012 23:35:04
    31  *
    32  */
    33 public class JPADataAccessObject {
    34 
    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;
    40 
    41 	JPADataAccessObject() {
    42 		tx = em.getTransaction();
    43 		tx.begin();
    44 	}
    45 
    46 	void close() {
    47 		commit()
    48 		em.close()
    49 		em = null
    50 	}
    51 
    52 	void commit() {
    53 		if(tx != null && tx.isActive()) {
    54 			tx.commit()
    55 		}
    56 	}
    57 
    58 	void rollback() {
    59 		if(tx != null && tx.isActive()) {
    60 			tx.rollback()
    61 		}
    62 	}
    63 
    64 	void detach(Object entity) {
    65 		em.detach(entity);
    66 	}
    67 
    68 	protected static String getPersistenceUnitName() {
    69 		if (persistenceUnitName != null)
    70 			return persistenceUnitName;
    71 
    72 		if (persistenceUnitName == null)
    73 			persistenceUnitName = System.getProperty(Props.PERSISTANCE_UNIT_NAME_PROPERTY);
    74 		if (persistenceUnitName == null) {
    75 			try {
    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");
    79 			}
    80 		}
    81 		if (persistenceUnitName == null) {
    82 			XMLConfiguration conf = new XMLConfiguration("META-INF/persistence.xml");
    83 			persistenceUnitName = conf.getString("persistence-unit[@name]");
    84 		}
    85 		if (persistenceUnitName == null)
    86 			persistenceUnitName = "database";
    87 		return persistenceUnitName;
    88 	}
    89 
    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();
    95 	}
    96 
    97 	public <T> T mergeAndRefresh(T object) {
    98 		def merged = em.merge(object)
    99 		em.refresh(merged)
   100 
   101 		merged
   102 	}
   103 
   104 	public <T extends AbstractEntity> T read(T object) {
   105 		return find(object.class, object.getIdentifierValue())
   106 	}
   107 
   108 	public <T> T merge(T object) {
   109 		em.merge(object)
   110 	}
   111 
   112 	void refresh(Object ... refreshObjects) {
   113 		for(object in refreshObjects) {
   114 			em.refresh(object)
   115 		}
   116 	}
   117 
   118 	boolean persist(Object ... persistanceQueue) {
   119 		persistAndRemove(persistanceQueue, new Object[0])
   120 	}
   121 
   122 	boolean persist(Collection entities) {
   123 		persistAndRemove(entities.toArray(), new Object[0])
   124 	}
   125 
   126 	boolean remove(Object ... removeQueue) {
   127 		persistAndRemove(new Object[0], removeQueue)
   128 	}
   129 
   130 	boolean remove(Collection entities) {
   131 		persistAndRemove(new Object[0], entities.toArray())
   132 	}
   133 
   134 	synchronized boolean persistAndRemove(Object[] persistanceQueue, Object[] removeQueue) {
   135 
   136 		try {
   137 
   138 			if(persistanceQueue != null) {
   139 				for(object in persistanceQueue) {
   140 					if(object != null) {
   141 						em.persist(object)
   142 					}
   143 				}
   144 			}
   145 
   146 			if(removeQueue != null) {
   147 				for(object in removeQueue) {
   148 					if(object != null) {
   149 						em.remove(object)
   150 					}
   151 				}
   152 			}
   153 		}
   154 		catch(Throwable t) {
   155 			log.error("Error while synchronizing with Database: ", t);
   156 			return false;
   157 		}
   158 
   159 		return true
   160 	}
   161 
   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());
   166 	}
   167 
   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));
   178 			}
   179 		}
   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));
   185 			}
   186 		}
   187 		query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
   188 		return em.createQuery(query).getResultList();
   189 	}
   190 
   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;
   199 		}
   200 		return list(entityClass, fieldValues, null);
   201 	}
   202 
   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();
   208 	}
   209 
   210 	public <T> T find(Class<T> entityClass, Object primaryKey) {
   211 		return em.find(entityClass, primaryKey);
   212 	}
   213 
   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));
   224 			}
   225 		}
   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));
   231 			}
   232 		}
   233 		query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
   234 		T result = null;
   235 		try {
   236 			result = em.createQuery(query).getSingleResult();
   237 		} catch (NoResultException e) {
   238 			log.info("Object not found in Database: " + e.getMessage());
   239 		}
   240 		return result;
   241 	}
   242 
   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;
   251 		}
   252 		return find(entityClass, fieldValues, null);
   253 	}
   254 
   255 
   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();
   261 	}
   262 
   263 	public boolean contains(Collection entities) {
   264 		boolean res = true;
   265 		entities.each {res &= contains(it)}
   266 		return res
   267 	}
   268 
   269 	public boolean contains(Object entity) {
   270 		return em.contains(entity);
   271 	}
   272 
   273 	private Object getSingleResult(Query query) {
   274 		try {
   275 			return query.getSingleResult()
   276 		}
   277 		catch (NoResultException e) {
   278 			return null
   279 		}
   280 	}
   281 }