/framework/src/play/db/jpa/JPQL.java

https://bitbucket.org/ripper234/play · Java · 305 lines · 266 code · 33 blank · 6 comment · 110 complexity · df1e332d96e5a8805d1fed4b63489f05 MD5 · raw file

  1. package play.db.jpa;
  2. import java.util.List;
  3. import java.util.Map;
  4. import javax.persistence.EntityManager;
  5. import javax.persistence.Query;
  6. import play.Play;
  7. import play.data.binding.ParamNode;
  8. import play.data.binding.RootParamNode;
  9. import play.db.DBConfig;
  10. import play.db.jpa.GenericModel.JPAQuery;
  11. import play.mvc.Scope.Params;
  12. public class JPQL {
  13. /**
  14. * Use JPAConfig.jpql instead
  15. */
  16. @Deprecated
  17. public static JPQL instance = null;
  18. private final JPAConfig jpaConfig;
  19. protected JPQL() {
  20. // get the default config
  21. jpaConfig = JPA.getJPAConfig( DBConfig.defaultDbConfigName);
  22. }
  23. protected JPQL(JPAConfig jpaConfig) {
  24. this.jpaConfig = jpaConfig;
  25. }
  26. protected static void createSingleton() {
  27. instance = new JPQL();
  28. }
  29. public EntityManager em() {
  30. return jpaConfig.getJPAContext().em();
  31. }
  32. public long count(String entity) {
  33. return Long.parseLong(em().createQuery("select count(*) from " + entity + " e").getSingleResult().toString());
  34. }
  35. public long count(String entity, String query, Object[] params) {
  36. return Long.parseLong(
  37. bindParameters(em().createQuery(
  38. createCountQuery(entity, entity, query, params)), params).getSingleResult().toString());
  39. }
  40. public List findAll(String entity) {
  41. return em().createQuery("select e from " + entity + " e").getResultList();
  42. }
  43. public JPABase findById(String entity, Object id) throws Exception {
  44. return (JPABase) em().find(Play.classloader.loadClass(entity), id);
  45. }
  46. public List findBy(String entity, String query, Object[] params) {
  47. Query q = em().createQuery(
  48. createFindByQuery(entity, entity, query, params));
  49. return bindParameters(q, params).getResultList();
  50. }
  51. public JPAQuery find(String entity, String query, Object[] params) {
  52. Query q = em().createQuery(
  53. createFindByQuery(entity, entity, query, params));
  54. return new JPAQuery(
  55. createFindByQuery(entity, entity, query, params), bindParameters(q, params));
  56. }
  57. public JPAQuery find(String entity) {
  58. Query q = em().createQuery(
  59. createFindByQuery(entity, entity, null));
  60. return new JPAQuery(
  61. createFindByQuery(entity, entity, null), bindParameters(q));
  62. }
  63. public JPAQuery all(String entity) {
  64. Query q = em().createQuery(
  65. createFindByQuery(entity, entity, null));
  66. return new JPAQuery(
  67. createFindByQuery(entity, entity, null), bindParameters(q));
  68. }
  69. public int delete(String entity, String query, Object[] params) {
  70. Query q = em().createQuery(
  71. createDeleteQuery(entity, entity, query, params));
  72. return bindParameters(q, params).executeUpdate();
  73. }
  74. public int deleteAll(String entity) {
  75. Query q = em().createQuery(
  76. createDeleteQuery(entity, entity, null));
  77. return bindParameters(q).executeUpdate();
  78. }
  79. public JPABase findOneBy(String entity, String query, Object[] params) {
  80. Query q = em().createQuery(
  81. createFindByQuery(entity, entity, query, params));
  82. List results = bindParameters(q, params).getResultList();
  83. if (results.size() == 0) {
  84. return null;
  85. }
  86. return (JPABase) results.get(0);
  87. }
  88. public JPABase create(String entity, String name, Params params) throws Exception {
  89. Object o = Play.classloader.loadClass(entity).newInstance();
  90. RootParamNode rootParamNode = ParamNode.convert(params.all());
  91. return ((GenericModel) o).edit(rootParamNode, name);
  92. }
  93. public String createFindByQuery(String entityName, String entityClass, String query, Object... params) {
  94. if (query == null || query.trim().length() == 0) {
  95. return "from " + entityName;
  96. }
  97. if (query.matches("^by[A-Z].*$")) {
  98. return "from " + entityName + " where " + findByToJPQL(query);
  99. }
  100. if (query.trim().toLowerCase().startsWith("select ")) {
  101. return query;
  102. }
  103. if (query.trim().toLowerCase().startsWith("from ")) {
  104. return query;
  105. }
  106. if (query.trim().toLowerCase().startsWith("order by ")) {
  107. return "from " + entityName + " " + query;
  108. }
  109. if (query.trim().indexOf(' ') == -1 && query.trim().indexOf('=') == -1 && params != null && params.length == 1) {
  110. query += " = ?1";
  111. }
  112. if (query.trim().indexOf(' ') == -1 && query.trim().indexOf('=') == -1 && params == null) {
  113. query += " = null";
  114. }
  115. return "from " + entityName + " where " + query;
  116. }
  117. public String createDeleteQuery(String entityName, String entityClass, String query, Object... params) {
  118. if (query == null) {
  119. return "delete from " + entityName;
  120. }
  121. if (query.trim().toLowerCase().startsWith("delete ")) {
  122. return query;
  123. }
  124. if (query.trim().toLowerCase().startsWith("from ")) {
  125. return "delete " + query;
  126. }
  127. if (query.trim().indexOf(' ') == -1 && query.trim().indexOf('=') == -1 && params != null && params.length == 1) {
  128. query += " = ?1";
  129. }
  130. if (query.trim().indexOf(' ') == -1 && query.trim().indexOf('=') == -1 && params == null) {
  131. query += " = null";
  132. }
  133. return "delete from " + entityName + " where " + query;
  134. }
  135. public String createCountQuery(String entityName, String entityClass, String query, Object... params) {
  136. if (query.trim().toLowerCase().startsWith("select ")) {
  137. return query;
  138. }
  139. if (query.matches("^by[A-Z].*$")) {
  140. return "select count(*) from " + entityName + " where " + findByToJPQL(query);
  141. }
  142. if (query.trim().toLowerCase().startsWith("from ")) {
  143. return "select count(*) " + query;
  144. }
  145. if (query.trim().toLowerCase().startsWith("order by ")) {
  146. return "select count(*) from " + entityName;
  147. }
  148. if (query.trim().indexOf(' ') == -1 && query.trim().indexOf('=') == -1 && params != null && params.length == 1) {
  149. query += " = ?1";
  150. }
  151. if (query.trim().indexOf(' ') == -1 && query.trim().indexOf('=') == -1 && params == null) {
  152. query += " = null";
  153. }
  154. if (query.trim().length() == 0) {
  155. return "select count(*) from " + entityName;
  156. }
  157. return "select count(*) from " + entityName + " e where " + query;
  158. }
  159. @SuppressWarnings("unchecked")
  160. public Query bindParameters(Query q, Object... params) {
  161. if (params == null) {
  162. return q;
  163. }
  164. if (params.length == 1 && params[0] instanceof Map) {
  165. return bindParameters(q, (Map<String, Object>) params[0]);
  166. }
  167. for (int i = 0; i < params.length; i++) {
  168. q.setParameter(i + 1, params[i]);
  169. }
  170. return q;
  171. }
  172. public Query bindParameters(Query q, Map<String,Object> params) {
  173. if (params == null) {
  174. return q;
  175. }
  176. for (String key : params.keySet()) {
  177. q.setParameter(key, params.get(key));
  178. }
  179. return q;
  180. }
  181. public String findByToJPQL(String findBy) {
  182. findBy = findBy.substring(2);
  183. StringBuilder jpql = new StringBuilder();
  184. String subRequest;
  185. if (findBy.contains("OrderBy"))
  186. subRequest = findBy.split("OrderBy")[0];
  187. else subRequest = findBy;
  188. String[] parts = subRequest.split("And");
  189. int index = 1;
  190. for (int i = 0; i < parts.length; i++) {
  191. String part = parts[i];
  192. if (part.endsWith("NotEqual")) {
  193. String prop = extractProp(part, "NotEqual");
  194. jpql.append(prop).append(" <> ?").append(index++);
  195. } else if (part.endsWith("Equal")) {
  196. String prop = extractProp(part, "Equal");
  197. jpql.append(prop).append(" = ?").append(index++);
  198. } else if (part.endsWith("IsNotNull")) {
  199. String prop = extractProp(part, "IsNotNull");
  200. jpql.append(prop).append(" is not null");
  201. } else if (part.endsWith("IsNull")) {
  202. String prop = extractProp(part, "IsNull");
  203. jpql.append(prop).append(" is null");
  204. } else if (part.endsWith("LessThan")) {
  205. String prop = extractProp(part, "LessThan");
  206. jpql.append(prop).append(" < ?").append(index++);
  207. } else if (part.endsWith("LessThanEquals")) {
  208. String prop = extractProp(part, "LessThanEquals");
  209. jpql.append(prop).append(" <= ?").append(index++);
  210. } else if (part.endsWith("GreaterThan")) {
  211. String prop = extractProp(part, "GreaterThan");
  212. jpql.append(prop).append(" > ?").append(index++);
  213. } else if (part.endsWith("GreaterThanEquals")) {
  214. String prop = extractProp(part, "GreaterThanEquals");
  215. jpql.append(prop).append(" >= ?").append(index++);
  216. } else if (part.endsWith("Between")) {
  217. String prop = extractProp(part, "Between");
  218. jpql.append(prop).append(" < ?").append(index++).append(" AND ").append(prop).append(" > ?").append(index++);
  219. } else if (part.endsWith("Like")) {
  220. String prop = extractProp(part, "Like");
  221. // HSQL -> LCASE, all other dbs lower
  222. if (isHSQL()) {
  223. jpql.append("LCASE(").append(prop).append(") like ?").append(index++);
  224. } else {
  225. jpql.append("LOWER(").append(prop).append(") like ?").append(index++);
  226. }
  227. } else if (part.endsWith("Ilike")) {
  228. String prop = extractProp(part, "Ilike");
  229. if (isHSQL()) {
  230. jpql.append("LCASE(").append(prop).append(") like LCASE(?").append(index++).append(")");
  231. } else {
  232. jpql.append("LOWER(").append(prop).append(") like LOWER(?").append(index++).append(")");
  233. }
  234. } else if (part.endsWith("Elike")) {
  235. String prop = extractProp(part, "Elike");
  236. jpql.append(prop).append(" like ?").append(index++);
  237. } else {
  238. String prop = extractProp(part, "");
  239. jpql.append(prop).append(" = ?").append(index++);
  240. }
  241. if (i < parts.length - 1) {
  242. jpql.append(" AND ");
  243. }
  244. }
  245. // ORDER BY clause
  246. if (findBy.contains("OrderBy")) {
  247. jpql.append(" ORDER BY ");
  248. String orderQuery = findBy.split("OrderBy")[1];
  249. parts = orderQuery.split("And");
  250. for (int i = 0; i < parts.length; i++) {
  251. String part = parts[i];
  252. String orderProp;
  253. if (part.endsWith("Desc"))
  254. orderProp = extractProp(part, "Desc") + " DESC";
  255. else orderProp = part.toLowerCase();
  256. if (i > 0)
  257. jpql.append(", ");
  258. jpql.append(orderProp);
  259. }
  260. }
  261. return jpql.toString();
  262. }
  263. private boolean isHSQL() {
  264. String db = Play.configuration.getProperty("db");
  265. return ("mem".equals(db) || "fs".equals(db) || "org.hsqldb.jdbcDriver".equals(Play.configuration.getProperty("db.driver")));
  266. }
  267. protected static String extractProp(String part, String end) {
  268. String prop = part.substring(0, part.length() - end.length());
  269. prop = (prop.charAt(0) + "").toLowerCase() + prop.substring(1);
  270. return prop;
  271. }
  272. }