Advertisement
Guest User

Untitled

a guest
May 21st, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.55 KB | None | 0 0
  1. package play.db.jpa;
  2.  
  3. import java.io.Serializable;
  4. import java.lang.annotation.Annotation;
  5. import java.lang.reflect.Field;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Properties;
  9. import javax.persistence.Entity;
  10. import javax.persistence.EntityManager;
  11. import javax.persistence.FlushModeType;
  12. import javax.persistence.PersistenceException;
  13. import javax.persistence.Query;
  14. import org.apache.log4j.Level;
  15. import org.hibernate.CallbackException;
  16. import org.hibernate.EmptyInterceptor;
  17. import org.hibernate.collection.PersistentCollection;
  18. import org.hibernate.ejb.Ejb3Configuration;
  19. import org.hibernate.type.Type;
  20. import play.Logger;
  21. import play.Play;
  22. import play.PlayPlugin;
  23. import play.db.DB;
  24. import play.exceptions.JPAException;
  25. import play.utils.Utils;
  26.  
  27. /**
  28. * JPA Plugin
  29. */
  30. public class JPAPlugin extends PlayPlugin {
  31.  
  32. public static boolean autoTxs = true;
  33.  
  34. @Override
  35. public Object bind(String name, Class clazz, java.lang.reflect.Type type, Annotation[] annotations, Map<String, String[]> params) {
  36. // TODO need to be more generic in order to work with JPASupport
  37. if(JPASupport.class.isAssignableFrom(clazz)) {
  38. String idKey = name + ".id";
  39. if(params.containsKey(idKey) && params.get(idKey).length > 0 && params.get(idKey)[0] != null && params.get(idKey)[0].trim().length() > 0) {
  40. String id = params.get(idKey)[0];
  41. try {
  42. Query query = JPA.em().createQuery("from " + clazz.getName() + " o where o.id = ?");
  43. query.setParameter(1, play.data.binding.Binder.directBind(annotations, id + "", play.db.jpa.JPASupport.findKeyType(clazz)));
  44. Object o = query.getSingleResult();
  45. return JPASupport.edit(o, name, params, annotations);
  46. } catch(Exception e) {
  47. return null;
  48. }
  49. }
  50. return JPASupport.create(clazz, name, params, annotations);
  51. }
  52. return super.bind(name, clazz, type, annotations, params);
  53. }
  54.  
  55. @Override
  56. public void onApplicationStart() {
  57. if (JPA.entityManagerFactory == null) {
  58. List<Class> classes = Play.classloader.getAnnotatedClasses(Entity.class);
  59. if (classes.isEmpty() && Play.configuration.getProperty("jpa.entities", "").equals("")) {
  60. return;
  61. }
  62. if (DB.datasource == null) {
  63. throw new JPAException("Cannot start a JPA manager without a properly configured database", new NullPointerException("No datasource"));
  64. }
  65. Ejb3Configuration cfg = new Ejb3Configuration();
  66. cfg.setDataSource(DB.datasource);
  67. if (!Play.configuration.getProperty("jpa.ddl", "update").equals("none")) {
  68. cfg.setProperty("hibernate.hbm2ddl.auto", Play.configuration.getProperty("jpa.ddl", "update"));
  69. }
  70. cfg.setProperty("hibernate.dialect", getDefaultDialect(Play.configuration.getProperty("db.driver")));
  71. cfg.setProperty("javax.persistence.transaction", "RESOURCE_LOCAL");
  72.  
  73. // Explicit SAVE for JPASupport is implemented here
  74. // ~~~~~~
  75. // We've hacked the org.hibernate.event.def.AbstractFlushingEventListener line 271, to flush collection update,remove,recreation
  76. // only if the owner will be saved.
  77. // As is:
  78. // if (session.getInterceptor().onCollectionUpdate(coll, ce.getLoadedKey())) {
  79. // actionQueue.addAction(...);
  80. // }
  81. //
  82. // This is really hacky. We should move to something better than Hibernate like EBEAN
  83. cfg.setInterceptor(new EmptyInterceptor() {
  84.  
  85. @Override
  86. public int[] findDirty(Object o, Serializable id, Object[] arg2, Object[] arg3, String[] arg4, Type[] arg5) {
  87. if (o instanceof JPASupport && !((JPASupport) o).willBeSaved) {
  88. return new int[0];
  89. }
  90. return null;
  91. }
  92.  
  93. @Override
  94. public boolean onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
  95. if (collection instanceof PersistentCollection) {
  96. Object o = ((PersistentCollection) collection).getOwner();
  97. if (o instanceof JPASupport) {
  98. return ((JPASupport) o).willBeSaved;
  99. }
  100. } else {
  101. System.out.println("HOO: Case not handled !!!");
  102. }
  103. return super.onCollectionUpdate(collection, key);
  104. }
  105.  
  106. @Override
  107. public boolean onCollectionRecreate(Object collection, Serializable key) throws CallbackException {
  108. if (collection instanceof PersistentCollection) {
  109. Object o = ((PersistentCollection) collection).getOwner();
  110. if (o instanceof JPASupport) {
  111. return ((JPASupport) o).willBeSaved;
  112. }
  113. } else {
  114. System.out.println("HOO: Case not handled !!!");
  115. }
  116. return super.onCollectionRecreate(collection, key);
  117. }
  118.  
  119. @Override
  120. public boolean onCollectionRemove(Object collection, Serializable key) throws CallbackException {
  121. if (collection instanceof PersistentCollection) {
  122. Object o = ((PersistentCollection) collection).getOwner();
  123. if (o instanceof JPASupport) {
  124. return ((JPASupport) o).willBeSaved;
  125. }
  126. } else {
  127. System.out.println("HOO: Case not handled !!!");
  128. }
  129. return super.onCollectionRemove(collection, key);
  130. }
  131. });
  132. if (Play.configuration.getProperty("jpa.debugSQL", "false").equals("true")) {
  133. org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.ALL);
  134. } else {
  135. org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.OFF);
  136. }
  137. // inject additional hibernate.* settings declared in Play! configuration
  138. cfg.addProperties((Properties) Utils.Maps.filterMap(Play.configuration, "^hibernate\\..*"));
  139.  
  140. try {
  141. Field field = cfg.getClass().getDeclaredField("overridenClassLoader");
  142. field.setAccessible(true);
  143. field.set(cfg, Play.classloader);
  144. } catch (Exception e) {
  145. Logger.error(e, "Error trying to override the hibernate classLoader (new hibernate version ???)");
  146. }
  147.  
  148. String[] packages = Play.configuration.getProperty("jpa.packages", "").split(", ");
  149. for(String pack : packages) {
  150. if(pack.trim().equals("")) continue;
  151. cfg.addPackage(pack);
  152. Logger.warn("Package configuration loaded: %s", pack);
  153. }
  154.  
  155. for (Class clazz : classes) {
  156. if (clazz.isAnnotationPresent(Entity.class)) {
  157. cfg.addAnnotatedClass(clazz);
  158. Logger.trace("JPA Model : %s", clazz);
  159. }
  160. }
  161. String[] moreEntities = Play.configuration.getProperty("jpa.entities", "").split(", ");
  162. for(String entity : moreEntities) {
  163. if(entity.trim().equals("")) continue;
  164. try {
  165. cfg.addAnnotatedClass(Play.classloader.loadClass(entity));
  166. } catch(Exception e) {
  167. Logger.warn("JPA -> Entity not found: %s", entity);
  168. }
  169. }
  170. Logger.trace("Initializing JPA ...");
  171. try {
  172. JPA.entityManagerFactory = cfg.buildEntityManagerFactory();
  173. } catch (PersistenceException e) {
  174. throw new JPAException(e.getMessage(), e.getCause() != null ? e.getCause() : e);
  175. }
  176. JPQL.instance = new JPQL();
  177. }
  178. }
  179.  
  180. static String getDefaultDialect(String driver) {
  181. if (driver.equals("org.hsqldb.jdbcDriver")) {
  182. return "org.hibernate.dialect.HSQLDialect";
  183. } else if (driver.equals("com.mysql.jdbc.Driver")) {
  184. return "play.db.jpa.MySQLDialect";
  185. } else {
  186. String dialect = Play.configuration.getProperty("jpa.dialect");
  187. if (dialect != null) {
  188. return dialect;
  189. }
  190. throw new UnsupportedOperationException("I do not know which hibernate dialect to use with " +
  191. driver + ", use the property jpa.dialect in config file");
  192. }
  193. }
  194.  
  195. @Override
  196. public void onApplicationStop() {
  197. if (JPA.entityManagerFactory != null) {
  198. JPA.entityManagerFactory.close();
  199. JPA.entityManagerFactory = null;
  200. }
  201. }
  202.  
  203. @Override
  204. public void beforeInvocation() {
  205. startTx(false);
  206. }
  207.  
  208. @Override
  209. public void afterInvocation() {
  210. closeTx(false);
  211. }
  212.  
  213. @Override
  214. public void afterActionInvocation() {
  215. closeTx(false);
  216. }
  217.  
  218. @Override
  219. public void onInvocationException(Throwable e) {
  220. closeTx(true);
  221. }
  222.  
  223. @Override
  224. public void invocationFinally() {
  225. closeTx(true);
  226. }
  227.  
  228. /**
  229. * initialize the JPA context and starts a JPA transaction
  230. *
  231. * @param readonly true for a readonly transaction
  232. */
  233. public static void startTx(boolean readonly) {
  234. if (!JPA.isEnabled()) {
  235. return;
  236. }
  237. EntityManager manager = JPA.entityManagerFactory.createEntityManager();
  238. //if(Play.configuration.getProperty("future.bindJPAObjects", "false").equals("true")) {
  239. manager.setFlushMode(FlushModeType.COMMIT);
  240. //}
  241. if (autoTxs) {
  242. manager.getTransaction().begin();
  243. }
  244. JPA.createContext(manager, readonly);
  245. }
  246.  
  247. /**
  248. * clear current JPA context and transaction
  249. * @param rollback shall current transaction be committed (false) or cancelled (true)
  250. */
  251. public static void closeTx(boolean rollback) {
  252. if (!JPA.isEnabled() || JPA.local.get() == null) {
  253. return;
  254. }
  255. EntityManager manager = JPA.get().entityManager;
  256. try {
  257. if (autoTxs) {
  258. if (manager.getTransaction().isActive()) {
  259. if (JPA.get().readonly || rollback || manager.getTransaction().getRollbackOnly()) {
  260. manager.getTransaction().rollback();
  261. } else {
  262. try {
  263. if (autoTxs) {
  264. manager.getTransaction().commit();
  265. }
  266. } catch (Throwable e) {
  267. for (int i = 0; i < 10; i++) {
  268. if (e instanceof PersistenceException && e.getCause() != null) {
  269. e = e.getCause();
  270. break;
  271. }
  272. e = e.getCause();
  273. if (e == null) {
  274. break;
  275. }
  276. }
  277. throw new JPAException("Cannot commit", e);
  278. }
  279. }
  280. }
  281. }
  282. } finally {
  283. manager.close();
  284. JPA.clearContext();
  285. }
  286. }
  287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement