/**
   * 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();
      }
    }
  }
Beispiel #2
0
 /** Returns the correct JPAConfig used to manage this entity-class */
 public static JPAConfig getJPAConfig(Class clazz) {
   return JPA.getJPAConfig(Entity2JPAConfigResolver.getJPAConfigNameForEntityClass(clazz));
 }
Beispiel #3
0
 protected JPAContext getJPAContext() {
   if (_jpaConfig == null) {
     _jpaConfig = JPA.getJPAConfig(jpaConfigName);
   }
   return _jpaConfig.getJPAContext();
 }
Beispiel #4
0
 @Override
 public void afterFixtureLoad() {
   JPA.clear();
 }
Beispiel #5
0
 /**
  * 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);
   }
 }
Beispiel #6
0
 /**
  * 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);
 }
Beispiel #7
0
 @Override
 public void beforeInvocation() {
   // just to be safe we must clear all possible previous
   // JPAContexts in this thread
   JPA.clearJPAContext();
 }
Beispiel #8
0
 @Override
 public void onApplicationStop() {
   JPA.close();
 }
Beispiel #9
0
  @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?");
      }
    }
  }
Beispiel #10
0
  /**
   * 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;
    }
  }
 public boolean isPersistent() {
   return JPA.em().contains(this);
 }
 /**
  * Retrieve the current entityManager
  *
  * @return the current entityManager
  */
 public static EntityManager em() {
   return JPA.em();
 }