@Test public void testPaging() { JPA.bootstrap(path()); int total = 15; JPA.transaction( () -> { for (int i = 0; i < total; i++) { Book book = JPA.insert(new Book("b" + i)); notNull(book.getId()); } }); JPA.transaction( () -> { eq(JPA.getAllEntities().size(), total); eq(JPA.count(Book.class), total); eq(JPA.of(Book.class).all().size(), total); List<Book> first3 = JPA.of(Book.class).page(0, 3); eq(first3.size(), 3); eq(Do.map(first3).to(Book::getTitle), U.list("b0", "b1", "b2")); List<Book> next5 = JPA.of(Book.class).page(3, 5); eq(Do.map(next5).to(Book::getTitle), U.list("b3", "b4", "b5", "b6", "b7")); List<Book> last2 = JPA.of(Book.class).page(13, 2); eq(Do.map(last2).to(Book::getTitle), U.list("b13", "b14")); }); }
/** * initialize the JPA context and starts a JPA transaction * * @param readonly true for a readonly transaction */ public static void startTx(boolean readonly) { if (!JPA.isEnabled()) { return; } EntityManager manager = JPA.entityManagerFactory.createEntityManager(); // if(Play.configuration.getProperty("future.bindJPAObjects", "false").equals("true")) { manager.setFlushMode(FlushModeType.COMMIT); manager.setProperty("org.hibernate.readOnly", readonly); // } if (autoTxs) { manager.getTransaction().begin(); } JPA.createContext(manager, readonly); }
/** * Run a block of code in a JPA transaction. * * @param name The persistence unit name * @param readOnly Is the transaction read-only? * @param block Block of code to execute */ public <T> T withTransaction(String name, boolean readOnly, Supplier<T> block) { EntityManager entityManager = null; EntityTransaction tx = null; try { entityManager = em(name); if (entityManager == null) { throw new RuntimeException("No JPA entity manager defined for '" + name + "'"); } JPA.bindForSync(entityManager); if (!readOnly) { tx = entityManager.getTransaction(); tx.begin(); } T result = block.get(); if (tx != null) { if (tx.getRollbackOnly()) { tx.rollback(); } else { tx.commit(); } } return result; } catch (Throwable t) { if (tx != null) { try { tx.rollback(); } catch (Throwable e) { } } throw t; } finally { JPA.bindForSync(null); if (entityManager != null) { entityManager.close(); } } }
public Model findById(Object id) { if (id == null) { return null; } try { return JPA.em() .find( clazz, Binder.directBind(id.toString(), Model.Manager.factoryFor(clazz).keyType())); } catch (Exception e) { // Key is invalid, thus nothing was found return null; } }
@Test public void storeLoad() throws Exception { UserTransaction tx = TM.getUserTransaction(); try { tx.begin(); EntityManager em = JPA.createEntityManager(); Long DEPARTMENT_ID; { Department department = new Department("Sales"); em.persist(department); UserId id = new UserId("johndoe", null); // Null? User user = new User(id); user.setDepartment(department); // Required! em.persist(user); DEPARTMENT_ID = department.getId(); } tx.commit(); em.close(); tx.begin(); em = JPA.createEntityManager(); { UserId id = new UserId("johndoe", DEPARTMENT_ID); User user = em.find(User.class, id); assertEquals(user.getDepartment().getName(), "Sales"); } tx.commit(); em.close(); } finally { TM.rollback(); } }
/** * clear current JPA context and transaction * * @param rollback shall current transaction be committed (false) or cancelled (true) */ public static void closeTx(boolean rollback) { if (!JPA.isEnabled() || JPA.local.get() == null) { return; } EntityManager manager = JPA.get().entityManager; try { if (autoTxs) { if (manager.getTransaction().isActive()) { if (JPA.get().readonly || rollback || manager.getTransaction().getRollbackOnly()) { manager.getTransaction().rollback(); } else { try { if (autoTxs) { manager.getTransaction().commit(); } } catch (Throwable e) { for (int i = 0; i < 10; i++) { if (e instanceof PersistenceException && e.getCause() != null) { e = e.getCause(); break; } e = e.getCause(); if (e == null) { break; } } throw new JPAException("Cannot commit", e); } } } } } finally { manager.close(); JPA.clearContext(); } }
/** * Starts the transaction on the specified database. * * @param factory * @param readOnly */ public static void startTx(String dbKey, boolean readOnly) { EntityManagerFactory factory = factoryMap.get(dbKey); log.debug("Starting transaction with factory" + factory + " on DB: " + dbKey); if (dbKey == null || factory == null) { log.warn("No database found for key: '" + dbKey + "'. Skipping database connection."); return; } EntityManager manager = factory.createEntityManager(); manager.setFlushMode(FlushModeType.COMMIT); if (autoTxs) { manager.getTransaction().begin(); } log.debug("Creating JPA context: " + manager + " for db: " + dbKey); JPA.createContext(manager, readOnly); }
public Long count(List<String> searchFields, String keywords, String where) { String q = "select count(e) from " + clazz.getName() + " e"; if (keywords != null && !keywords.equals("")) { String searchQuery = getSearchQuery(searchFields); if (!searchQuery.equals("")) { q += " where (" + searchQuery + ")"; } q += (where != null ? " and " + where : ""); } else { q += (where != null ? " where " + where : ""); } Query query = JPA.em().createQuery(q); if (keywords != null && !keywords.equals("") && q.indexOf("?1") != -1) { query.setParameter(1, "%" + keywords.toLowerCase() + "%"); } return Long.decode(query.getSingleResult().toString()); }
@SuppressWarnings("unchecked") public List<Model> fetch( int offset, int size, String orderBy, String order, List<String> searchFields, String keywords, String where) { String q = "from " + clazz.getName(); if (keywords != null && !keywords.equals("")) { String searchQuery = getSearchQuery(searchFields); if (!searchQuery.equals("")) { q += " where (" + searchQuery + ")"; } q += (where != null ? " and " + where : ""); } else { q += (where != null ? " where " + where : ""); } if (orderBy == null && order == null) { orderBy = "id"; order = "ASC"; } if (orderBy == null && order != null) { orderBy = "id"; } if (order == null || (!order.equals("ASC") && !order.equals("DESC"))) { order = "ASC"; } q += " order by " + orderBy + " " + order; Query query = JPA.em().createQuery(q); if (keywords != null && !keywords.equals("") && q.indexOf("?1") != -1) { query.setParameter(1, "%" + keywords.toLowerCase() + "%"); } query.setFirstResult(offset); query.setMaxResults(size); return query.getResultList(); }
@Override @SuppressWarnings("unchecked") public Object bind( String name, Class clazz, java.lang.reflect.Type type, Annotation[] annotations, Map<String, String[]> params) { // TODO need to be more generic in order to work with JPASupport if (JPABase.class.isAssignableFrom(clazz)) { String keyName = Model.Manager.factoryFor(clazz).keyName(); String idKey = name + "." + keyName; if (params.containsKey(idKey) && params.get(idKey).length > 0 && params.get(idKey)[0] != null && params.get(idKey)[0].trim().length() > 0) { String id = params.get(idKey)[0]; try { Query query = JPA.em().createQuery("from " + clazz.getName() + " o where o." + keyName + " = ?"); query.setParameter( 1, play.data.binding.Binder.directBind( name, annotations, id + "", Model.Manager.factoryFor(clazz).keyType())); Object o = query.getSingleResult(); return GenericModel.edit(o, name, params, annotations); } catch (NoResultException e) { // ok } catch (Exception e) { throw new UnexpectedException(e); } } return GenericModel.create(clazz, name, params, annotations); } return super.bind(name, clazz, type, annotations, params); }
/** * initialize the JPA context and starts a JPA transaction if not already started. * * <p>This method is not needed since transaction is created automatically on first use. * * <p>It is better to specify readonly like this: @Transactional(readOnly=true) * * @param readonly true for a readonly transaction * @deprecated use @Transactional with readOnly-property instead */ @Deprecated public static void startTx(boolean readonly) { // Create new transaction by getting the JPAContext JPA.getJPAConfig(DBConfig.defaultDbConfigName).getJPAContext(readonly); }
/** * clear current JPA context and transaction if JPAPlugin.autoTxs is true When using multiple * databases in the same request this method tries to commit/rollback as many transactions as * possible, but there is not guaranteed that all transactions are committed. * * @param rollback shall current transaction be committed (false) or cancelled (true) */ public static void closeTx(boolean rollback) { if (autoTxs) { JPA.closeTx(rollback); } }
@Override public void onApplicationStop() { JPA.close(); }
@Override public void beforeInvocation() { // just to be safe we must clear all possible previous // JPAContexts in this thread JPA.clearJPAContext(); }
/** Delete this member. */ public void delete() { JPA.em().remove(this); }
@Override public void onApplicationStart() { // must check and configure JPA for each DBConfig for (DBConfig dbConfig : DB.getDBConfigs()) { // check and enable JPA on this config // is JPA already configured? String configName = dbConfig.getDBConfigName(); if (JPA.getJPAConfig(configName, true) == null) { // must configure it // resolve prefix for hibernate config.. // should be nothing for default, and db_<name> for others String propPrefix = ""; if (!DBConfig.defaultDbConfigName.equalsIgnoreCase(configName)) { propPrefix = "db_" + configName + "."; } List<Class> classes = findEntityClassesForThisConfig(configName, propPrefix); if (classes == null) continue; // we're ready to configure this instance of JPA final String hibernateDataSource = Play.configuration.getProperty(propPrefix + "hibernate.connection.datasource"); if (StringUtils.isEmpty(hibernateDataSource) && dbConfig == null) { throw new JPAException( "Cannot start a JPA manager without a properly configured database" + getConfigInfoString(configName), new NullPointerException("No datasource configured")); } Ejb3Configuration cfg = new Ejb3Configuration(); if (dbConfig.getDatasource() != null) { cfg.setDataSource(dbConfig.getDatasource()); } if (!Play.configuration .getProperty(propPrefix + "jpa.ddl", Play.mode.isDev() ? "update" : "none") .equals("none")) { cfg.setProperty( "hibernate.hbm2ddl.auto", Play.configuration.getProperty(propPrefix + "jpa.ddl", "update")); } String driver = null; if (StringUtils.isEmpty(propPrefix)) { driver = Play.configuration.getProperty("db.driver"); } else { driver = Play.configuration.getProperty(propPrefix + "driver"); } cfg.setProperty("hibernate.dialect", getDefaultDialect(propPrefix, driver)); cfg.setProperty("javax.persistence.transaction", "RESOURCE_LOCAL"); cfg.setInterceptor(new PlayInterceptor()); // This setting is global for all JPAs - only configure if configuring default JPA if (StringUtils.isEmpty(propPrefix)) { if (Play.configuration.getProperty(propPrefix + "jpa.debugSQL", "false").equals("true")) { org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.ALL); } else { org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.OFF); } } // inject additional hibernate.* settings declared in Play! configuration Properties additionalProperties = (Properties) Utils.Maps.filterMap(Play.configuration, "^" + propPrefix + "hibernate\\..*"); // We must remove prefix from names Properties transformedAdditionalProperties = new Properties(); for (Map.Entry<Object, Object> entry : additionalProperties.entrySet()) { Object key = entry.getKey(); if (!StringUtils.isEmpty(propPrefix)) { key = ((String) key).substring(propPrefix.length()); // chop off the prefix } transformedAdditionalProperties.put(key, entry.getValue()); } cfg.addProperties(transformedAdditionalProperties); try { // nice hacking :) I like it.. Field field = cfg.getClass().getDeclaredField("overridenClassLoader"); field.setAccessible(true); field.set(cfg, Play.classloader); } catch (Exception e) { Logger.error( e, "Error trying to override the hibernate classLoader (new hibernate version ???)"); } for (Class<?> clazz : classes) { cfg.addAnnotatedClass(clazz); if (Logger.isTraceEnabled()) { Logger.trace("JPA Model : %s", clazz); } } String[] moreEntities = Play.configuration.getProperty(propPrefix + "jpa.entities", "").split(", "); for (String entity : moreEntities) { if (entity.trim().equals("")) { continue; } try { cfg.addAnnotatedClass(Play.classloader.loadClass(entity)); } catch (Exception e) { Logger.warn("JPA -> Entity not found: %s", entity); } } for (ApplicationClass applicationClass : Play.classes.all()) { if (applicationClass.isClass() || applicationClass.javaPackage == null) { continue; } Package p = applicationClass.javaPackage; Logger.info("JPA -> Adding package: %s", p.getName()); cfg.addPackage(p.getName()); } String mappingFile = Play.configuration.getProperty(propPrefix + "jpa.mapping-file", ""); if (mappingFile != null && mappingFile.length() > 0) { cfg.addResource(mappingFile); } if (Logger.isTraceEnabled()) { Logger.trace("Initializing JPA" + getConfigInfoString(configName) + " ..."); } try { JPA.addConfiguration(configName, cfg); } catch (PersistenceException e) { throw new JPAException( e.getMessage() + getConfigInfoString(configName), e.getCause() != null ? e.getCause() : e); } } } // must look for Entity-objects referring to none-existing JPAConfig List<Class> allEntityClasses = Play.classloader.getAnnotatedClasses(Entity.class); for (Class clazz : allEntityClasses) { String configName = Entity2JPAConfigResolver.getJPAConfigNameForEntityClass(clazz); if (JPA.getJPAConfig(configName, true) == null) { throw new JPAException( "Found Entity-class (" + clazz.getName() + ") referring to none-existing JPAConfig" + getConfigInfoString(configName) + ". " + "Is JPA properly configured?"); } } }
/** * Run a block of asynchronous code in a JPA transaction. * * @param name The persistence unit name * @param readOnly Is the transaction read-only? * @param block Block of code to execute. * @deprecated This may cause deadlocks */ @Deprecated public <T> F.Promise<T> withTransactionAsync( String name, boolean readOnly, Supplier<F.Promise<T>> block) { EntityManager entityManager = null; EntityTransaction tx = null; try { entityManager = em(name); if (entityManager == null) { throw new RuntimeException("No JPA entity manager defined for '" + name + "'"); } JPA.bindForAsync(entityManager); if (!readOnly) { tx = entityManager.getTransaction(); tx.begin(); } F.Promise<T> result = block.get(); final EntityManager fem = entityManager; final EntityTransaction ftx = tx; F.Promise<T> committedResult = (ftx == null) ? result : result.map( t -> { if (ftx.getRollbackOnly()) { ftx.rollback(); } else { ftx.commit(); } return t; }); committedResult.onFailure( t -> { if (ftx != null) { try { if (ftx.isActive()) { ftx.rollback(); } } catch (Throwable e) { } } try { fem.close(); } finally { JPA.bindForAsync(null); } }); committedResult.onRedeem( t -> { try { fem.close(); } finally { JPA.bindForAsync(null); } }); return committedResult; } catch (Throwable t) { if (tx != null) { try { tx.rollback(); } catch (Throwable e) { } } if (entityManager != null) { try { entityManager.close(); } finally { JPA.bindForAsync(null); } } throw t; } }
/** Insert this new member. */ public void save() { JPA.em().persist(this); }
@Override public void afterFixtureLoad() { if (JPA.isEnabled()) { JPA.em().clear(); } }
/** * Run the given task inside a transaction that is committed after the task is completed. * * @param task the task to run */ protected void inTransaction(Runnable task) { JPA.runInTransaction(task); }
/** Returns the correct JPAConfig used to manage this entity-class */ public static JPAConfig getJPAConfig(Class clazz) { return JPA.getJPAConfig(Entity2JPAConfigResolver.getJPAConfigNameForEntityClass(clazz)); }
@Override public void afterFixtureLoad() { JPA.clear(); }
public void deleteAll() { JPA.em().createQuery("delete from " + clazz.getName()).executeUpdate(); }
protected JPAContext getJPAContext() { if (_jpaConfig == null) { _jpaConfig = JPA.getJPAConfig(jpaConfigName); } return _jpaConfig.getJPAContext(); }
/** * Retrieve the current entityManager * * @return the current entityManager */ public static EntityManager em() { return JPA.em(); }
/** Get the instance of current {@link EntityManager}. */ protected EntityManager getEntityManager() { return JPA.em(); }
public boolean isPersistent() { return JPA.em().contains(this); }
/** * Perform JDBC related task using the {@link Connection} managed by the current {@link * EntityManager}. * * @param task The task to be performed * @throws PersistenceException Generally indicates wrapped {@link SQLException} */ protected void jdbcTask(JDBCTask task) { JPA.jdbcWork(task); }
public CompletionStage<Result> call(final Context ctx) { return JPA.withTransaction( configuration.value(), configuration.readOnly(), () -> delegate.call(ctx)); }