src/main/java/ru/indvdum/jpa/dao/JPADataAccessObject.groovy
author indvdum (gotoindvdum[at]gmail[dot]com)
Wed, 26 Dec 2012 01:01:24 +0400
changeset 21 bba4a82be921
parent 20 a05948e9458c
child 23 da78c32e3dcb
permissions -rw-r--r--
Single result fix
     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 		// 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());
   167 	}
   168 
   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));
   179 			}
   180 		}
   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));
   186 			}
   187 		}
   188 		query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
   189 		return em.createQuery(query).getResultList();
   190 	}
   191 
   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;
   200 		}
   201 		return list(entityClass, fieldValues, null);
   202 	}
   203 
   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();
   209 	}
   210 
   211 	public <T> T find(Class<T> entityClass, Object primaryKey) {
   212 		return em.find(entityClass, primaryKey);
   213 	}
   214 
   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));
   225 			}
   226 		}
   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));
   232 			}
   233 		}
   234 		query.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
   235 		T result = null;
   236 		try {
   237 			result = getSingleResult(em.createQuery(query));
   238 		} catch (NoResultException e) {
   239 			log.info("Object not found in Database: " + e.getMessage());
   240 		}
   241 		return result;
   242 	}
   243 
   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;
   252 		}
   253 		return find(entityClass, fieldValues, null);
   254 	}
   255 
   256 
   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);
   262 	}
   263 
   264 	public boolean contains(Collection entities) {
   265 		boolean res = true;
   266 		entities.each {res &= contains(it)}
   267 		return res
   268 	}
   269 
   270 	public boolean contains(Object entity) {
   271 		return em.contains(entity);
   272 	}
   273 
   274 	private Object getSingleResult(Query query) {
   275 		try {
   276 			return query.getSingleResult()
   277 		}
   278 		catch (NoResultException e) {
   279 			return null
   280 		}
   281 	}
   282 }