diff --git a/.gitignore b/.gitignore
index ec28e920ca..95da09e28b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,6 +84,7 @@ support/textmate
samples-and-tests/yabe/logs
samples-and-tests/yabe/test-result
samples-and-tests/yabe/tmp
+samples-and-tests/yabe/modules
*.ser
modules/cobertura/lib
modules/scala/lib/play-scala.jar
diff --git a/.travis.yml b/.travis.yml
index 61f45d91df..7951a6671c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,13 +13,12 @@ addons:
hosts:
- myshorthost
hostname: myshorthost
+
script: ant -buildfile ./framework/build.xml test
-after_failure:
- cat ./samples-and-tests/just-test-cases/test-result/*.failed.html
- cat ./samples-and-tests/forum/test-result/*.failed.html
- cat ./samples-and-tests/zencontact/test-result/*.failed.html
- cat ./samples-and-tests/jobboard/test-result/*.failed.html
- cat ./samples-and-tests/yabe/test-result/*.failed.html
+
+after_failure:
+ find samples-and-tests -name '*.failed.html' -exec echo {} \; -exec cat {} \;
+
notifications:
webhooks:
urls:
diff --git a/documentation/manual/releases/release1.0.x/releasenotes-1.0.1.textile b/documentation/manual/releases/release1.0.x/releasenotes-1.0.1.textile
index 8f3587fe7d..7b6fbd1283 100644
--- a/documentation/manual/releases/release1.0.x/releasenotes-1.0.1.textile
+++ b/documentation/manual/releases/release1.0.x/releasenotes-1.0.1.textile
@@ -12,7 +12,7 @@ Now all dynamic expressions are escaped by the template engine to avoid XSS secu
bc. ${title} --> <h1>Title</h1>
-If you really want to display it in an unescaped way, you need to explicitely call the @raw()@ method:
+If you really want to display it in an unescaped way, you need to explicitly call the @raw()@ method:
bc. ${title.raw()} -->
Title
@@ -119,7 +119,7 @@ bc. public class User {
h2. Test runner update
-We’ve updated Selenium to the 1.0.1 final version and improved the UI. Selenium tests now run in fullscreen. And some new functionality like the "Run all tests" have been added.
+We’ve updated Selenium to the 1.0.1 final version and improved the UI. Selenium tests now run in full screen. And some new functionality like the "Run all tests" have been added.
!images/selenium-fullscreen!
diff --git a/documentation/manual/releases/release1.0.x/releasenotes.textile b/documentation/manual/releases/release1.0.x/releasenotes.textile
index c0f1a43f1d..b192ba9c86 100644
--- a/documentation/manual/releases/release1.0.x/releasenotes.textile
+++ b/documentation/manual/releases/release1.0.x/releasenotes.textile
@@ -12,7 +12,7 @@ Now all dynamic expressions are escaped by the template engine to avoid XSS secu
bc. ${title} --> <h1>Title</h1>
-If you really want to display it in an unescaped way, you need to explicitely call the **raw()** method:
+If you really want to display it in an unescaped way, you need to explicitly call the **raw()** method:
bc. ${title.raw()} --> Title
@@ -71,7 +71,7 @@ bc. public static void save(User user) {
user.save(); // ok with 1.0.1
}
-Of course as this feature can break existing applications it is not enabled by default. You can enable it by adding the followin line to your **application.conf** file:
+Of course as this feature can break existing applications it is not enabled by default. You can enable it by adding the following line to your **application.conf** file:
bc. future.bindJPAObjects=true
@@ -119,7 +119,7 @@ bc. public class User {
h2. Test runner update
-We've updated selenium to the 1.0.1 final version and improved the UI. Selenium tests now run in fullscreen. And some new functionalities like the "Run all tests" have been added.
+We've updated selenium to the 1.0.1 final version and improved the UI. Selenium tests now run in full screen. And some new functionalities like the "Run all tests" have been added.
!images/selenium-fullscreen!
diff --git a/documentation/manual/templates.textile b/documentation/manual/templates.textile
index fdc3929436..90e5270227 100644
--- a/documentation/manual/templates.textile
+++ b/documentation/manual/templates.textile
@@ -80,7 +80,7 @@ All dynamic expressions are escaped by the template engine to avoid XSS security
bc. ${title} --> <h1>Title</h1>
-If you really want to display it in an unescaped way, you need to explicitely call the @raw()@ method:
+If you really want to display it in an unescaped way, you need to explicitly call the @raw()@ method:
bc. ${title.raw()} --> Title
diff --git a/framework/dependencies.yml b/framework/dependencies.yml
index 924fcff4fd..39227487a5 100644
--- a/framework/dependencies.yml
+++ b/framework/dependencies.yml
@@ -45,15 +45,16 @@ require: &allDependencies
- org.bouncycastle -> bcprov-jdk15 1.46
- org.codehaus.groovy -> groovy-all 2.4.11
- org.eclipse.jdt.core 3.12.3
- - org.hibernate -> hibernate-core 4.2.19.Final
- - org.hibernate -> hibernate-commons-annotations 4.0.2.Final
- - org.hibernate -> hibernate-entitymanager 4.2.19.Final
- - org.hibernate -> hibernate-validator 4.1.0.Final
- - org.hibernate -> jboss-logging 3.1.0.GA
- - org.hibernate -> jboss-transaction-api_1.1_spec 1.0.1.Final
- - org.hibernate.javax.persistence -> hibernate-jpa-2.0-api 1.0.1.Final
- - org.hibernate -> hibernate-c3p0 4.2.19.Final
- - org.hibernate -> hibernate-ehcache 4.2.19.Final
+ - org.hibernate -> hibernate-core 5.2.10.patched
+ - org.hibernate.common -> hibernate-commons-annotations 5.0.1.Final
+ - org.hibernate -> hibernate-entitymanager 5.2.10.Final
+ - org.hibernate -> hibernate-validator 5.4.1.Final
+ - org.jboss.logging -> jboss-logging 3.3.0.Final
+ - org.jboss.spec.javax.transaction -> jboss-transaction-api_1.2_spec 1.0.1.Final
+ - org.hibernate.javax.persistence -> hibernate-jpa-2.1-api 1.0.0.Final
+ - com.fasterxml -> classmate 1.3.3
+ - org.hibernate -> hibernate-c3p0 5.2.10.Final
+ - org.hibernate -> hibernate-ehcache 5.2.10.Final
- com.mchange -> mchange-commons-java 0.2.12
- org.javassist -> javassist 3.21.0-GA
- io.netty -> netty 3.10.6.Final
diff --git a/framework/lib/classmate-1.3.3.jar b/framework/lib/classmate-1.3.3.jar
new file mode 100644
index 0000000000..d44873ea54
Binary files /dev/null and b/framework/lib/classmate-1.3.3.jar differ
diff --git a/framework/lib/hibernate-c3p0-4.2.19.Final.jar b/framework/lib/hibernate-c3p0-4.2.19.Final.jar
deleted file mode 100644
index 984d327a6e..0000000000
Binary files a/framework/lib/hibernate-c3p0-4.2.19.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-c3p0-5.2.10.Final.jar b/framework/lib/hibernate-c3p0-5.2.10.Final.jar
new file mode 100644
index 0000000000..9416da0e1a
Binary files /dev/null and b/framework/lib/hibernate-c3p0-5.2.10.Final.jar differ
diff --git a/framework/lib/hibernate-commons-annotations-4.0.2.Final.jar b/framework/lib/hibernate-commons-annotations-4.0.2.Final.jar
deleted file mode 100644
index c26aba4ed5..0000000000
Binary files a/framework/lib/hibernate-commons-annotations-4.0.2.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-commons-annotations-5.0.1.Final.jar b/framework/lib/hibernate-commons-annotations-5.0.1.Final.jar
new file mode 100644
index 0000000000..82e425dc2e
Binary files /dev/null and b/framework/lib/hibernate-commons-annotations-5.0.1.Final.jar differ
diff --git a/framework/lib/hibernate-core-4.2.19.Final.jar b/framework/lib/hibernate-core-4.2.19.Final.jar
deleted file mode 100644
index 54b3fea2d7..0000000000
Binary files a/framework/lib/hibernate-core-4.2.19.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-core-5.2.10.patched.jar b/framework/lib/hibernate-core-5.2.10.patched.jar
new file mode 100644
index 0000000000..65249ba583
Binary files /dev/null and b/framework/lib/hibernate-core-5.2.10.patched.jar differ
diff --git a/framework/lib/hibernate-ehcache-4.2.19.Final.jar b/framework/lib/hibernate-ehcache-4.2.19.Final.jar
deleted file mode 100644
index 1ce3f341c3..0000000000
Binary files a/framework/lib/hibernate-ehcache-4.2.19.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-ehcache-5.2.10.Final.jar b/framework/lib/hibernate-ehcache-5.2.10.Final.jar
new file mode 100644
index 0000000000..4be83a7700
Binary files /dev/null and b/framework/lib/hibernate-ehcache-5.2.10.Final.jar differ
diff --git a/framework/lib/hibernate-entitymanager-4.2.19.Final.jar b/framework/lib/hibernate-entitymanager-4.2.19.Final.jar
deleted file mode 100644
index 5700709aed..0000000000
Binary files a/framework/lib/hibernate-entitymanager-4.2.19.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-entitymanager-5.2.10.Final.jar b/framework/lib/hibernate-entitymanager-5.2.10.Final.jar
new file mode 100644
index 0000000000..0e328fd5f5
Binary files /dev/null and b/framework/lib/hibernate-entitymanager-5.2.10.Final.jar differ
diff --git a/framework/lib/hibernate-jpa-2.0-api-1.0.1.Final.jar b/framework/lib/hibernate-jpa-2.0-api-1.0.1.Final.jar
deleted file mode 100644
index 1e9f71b8c1..0000000000
Binary files a/framework/lib/hibernate-jpa-2.0-api-1.0.1.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar b/framework/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar
new file mode 100644
index 0000000000..e2f2c59287
Binary files /dev/null and b/framework/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar differ
diff --git a/framework/lib/hibernate-validator-4.1.0.Final.jar b/framework/lib/hibernate-validator-4.1.0.Final.jar
deleted file mode 100644
index abf87e4b41..0000000000
Binary files a/framework/lib/hibernate-validator-4.1.0.Final.jar and /dev/null differ
diff --git a/framework/lib/hibernate-validator-5.4.1.Final.jar b/framework/lib/hibernate-validator-5.4.1.Final.jar
new file mode 100644
index 0000000000..1975846ff4
Binary files /dev/null and b/framework/lib/hibernate-validator-5.4.1.Final.jar differ
diff --git a/framework/lib/jboss-logging-3.1.0.GA.jar b/framework/lib/jboss-logging-3.1.0.GA.jar
deleted file mode 100644
index 72113b0f84..0000000000
Binary files a/framework/lib/jboss-logging-3.1.0.GA.jar and /dev/null differ
diff --git a/framework/lib/jboss-logging-3.3.0.Final.jar b/framework/lib/jboss-logging-3.3.0.Final.jar
new file mode 100644
index 0000000000..ea45d4d341
Binary files /dev/null and b/framework/lib/jboss-logging-3.3.0.Final.jar differ
diff --git a/framework/lib/jboss-transaction-api_1.1_spec-1.0.1.Final.jar b/framework/lib/jboss-transaction-api_1.1_spec-1.0.1.Final.jar
deleted file mode 100644
index 981f8f9910..0000000000
Binary files a/framework/lib/jboss-transaction-api_1.1_spec-1.0.1.Final.jar and /dev/null differ
diff --git a/framework/lib/jboss-transaction-api_1.2_spec-1.0.1.Final.jar b/framework/lib/jboss-transaction-api_1.2_spec-1.0.1.Final.jar
new file mode 100644
index 0000000000..2113cc0279
Binary files /dev/null and b/framework/lib/jboss-transaction-api_1.2_spec-1.0.1.Final.jar differ
diff --git a/framework/patches/hibernate-4.2.19-patch-play.README b/framework/patches/hibernate-4.2.19-patch-play.README
deleted file mode 100644
index c78e35d3ac..0000000000
--- a/framework/patches/hibernate-4.2.19-patch-play.README
+++ /dev/null
@@ -1,6 +0,0 @@
-----
-Download Hibernate 4.2.19.Final source code, apply the patch, and build with gradle (tip use export GRADLE_OPTS=-Xmx1G -XX:MaxPermSize=512m)
-----
-
-DRY RUN -> patch --dry-run -p1 -i hibernate-4.2.19-patch-play.patch
-APPLY -> patch -p1 -i hibernate-4.2.19-patch-play.patch
diff --git a/framework/patches/hibernate-5.2.10-patch-play.README b/framework/patches/hibernate-5.2.10-patch-play.README
new file mode 100644
index 0000000000..5898a0f527
--- /dev/null
+++ b/framework/patches/hibernate-5.2.10-patch-play.README
@@ -0,0 +1,6 @@
+----
+Download Hibernate 5.2.10.Final source code, apply the patch, and build with gradle (tip use export GRADLE_OPTS=-Xmx1G -XX:MaxPermSize=512m)
+----
+
+DRY RUN -> patch --dry-run -p1 -i hibernate-5.2.10-patch-play.patch
+APPLY -> patch -p1 -i hibernate-5.2.10-patch-play.patch
diff --git a/framework/patches/hibernate-4.2.19-patch-play.patch.patch b/framework/patches/hibernate-5.2.10-patch-play.patch
similarity index 100%
rename from framework/patches/hibernate-4.2.19-patch-play.patch.patch
rename to framework/patches/hibernate-5.2.10-patch-play.patch
diff --git a/framework/src/play/classloading/ApplicationClassloader.java b/framework/src/play/classloading/ApplicationClassloader.java
index f9f686ba66..920f59da24 100644
--- a/framework/src/play/classloading/ApplicationClassloader.java
+++ b/framework/src/play/classloading/ApplicationClassloader.java
@@ -255,15 +255,21 @@ public InputStream getResourceAsStream(String name) {
@Override
public URL getResource(String name) {
- for (VirtualFile vf : Play.javaPath) {
- VirtualFile res = vf.child(name);
- if (res != null && res.exists()) {
- try {
+ try {
+ for (VirtualFile vf : Play.javaPath) {
+ VirtualFile res = vf.child(name);
+ if (res != null && res.exists()) {
return res.getRealFile().toURI().toURL();
- } catch (MalformedURLException ex) {
- throw new UnexpectedException(ex);
}
}
+ if (Play.configuration.getProperty("play.bytecodeCache", "true").equals("true")) {
+ File f = new File(Play.tmpDir, "classes/" + name);
+ if (f.exists()) {
+ return f.toURI().toURL();
+ }
+ }
+ } catch (MalformedURLException ex) {
+ throw new UnexpectedException(ex);
}
return super.getResource(name);
}
diff --git a/framework/src/play/db/DB.java b/framework/src/play/db/DB.java
index ce043bcf6c..b538b8a242 100644
--- a/framework/src/play/db/DB.java
+++ b/framework/src/play/db/DB.java
@@ -15,6 +15,7 @@
import javax.sql.RowSet;
import javax.sql.rowset.CachedRowSet;
+import org.hibernate.jpa.HibernateEntityManager;
import org.hibernate.internal.SessionImpl;
import com.sun.rowset.CachedRowSetImpl;
@@ -177,7 +178,7 @@ public static void close(String name) {
public static Connection getConnection(String name) {
try {
if (JPA.isEnabled()) {
- return ((SessionImpl) ((org.hibernate.ejb.EntityManagerImpl) JPA.em(name)).getSession()).connection();
+ return ((SessionImpl) ((HibernateEntityManager) JPA.em(name)).getSession()).connection();
}
Connection localConnection = getLocalConnection(name);
diff --git a/framework/src/play/db/jpa/Blob.java b/framework/src/play/db/jpa/Blob.java
index 4945d0f295..f29c503245 100644
--- a/framework/src/play/db/jpa/Blob.java
+++ b/framework/src/play/db/jpa/Blob.java
@@ -11,6 +11,7 @@
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.StringType;
import org.hibernate.usertype.UserType;
@@ -114,17 +115,17 @@ public int hashCode(Object o) throws HibernateException {
}
@Override
- public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object o) throws HibernateException, SQLException {
- String val = (String) StringType.INSTANCE.nullSafeGet(resultSet, names[0], sessionImplementor, o);
+ public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
+ String val = (String) StringType.INSTANCE.nullSafeGet(rs, names[0], session, owner);
return new Blob(val);
}
@Override
- public void nullSafeSet(PreparedStatement ps, Object o, int i, SessionImplementor sessionImplementor) throws HibernateException, SQLException {
- if(o != null) {
- ps.setString(i, encode((Blob) o));
+ public void nullSafeSet(PreparedStatement ps, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
+ if (value != null) {
+ ps.setString(index, encode((Blob) value));
} else {
- ps.setNull(i, Types.VARCHAR);
+ ps.setNull(index, Types.VARCHAR);
}
}
diff --git a/framework/src/play/db/jpa/JPAPlugin.java b/framework/src/play/db/jpa/JPAPlugin.java
index 1941adc2d1..0f9a343916 100644
--- a/framework/src/play/db/jpa/JPAPlugin.java
+++ b/framework/src/play/db/jpa/JPAPlugin.java
@@ -1,8 +1,9 @@
package play.db.jpa;
import org.apache.log4j.Level;
-import org.hibernate.ejb.Ejb3Configuration;
-
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
+import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
import play.Logger;
import play.Play;
import play.PlayPlugin;
@@ -10,27 +11,24 @@
import play.data.binding.Binder;
import play.data.binding.ParamNode;
import play.data.binding.RootParamNode;
+import play.db.Configuration;
import play.db.DB;
import play.db.Model;
-import play.db.Configuration;
import play.exceptions.JPAException;
import play.exceptions.UnexpectedException;
import javax.persistence.*;
+import javax.persistence.spi.PersistenceUnitInfo;
import java.lang.annotation.Annotation;
import java.util.*;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
-/**
- * JPA Plugin
- */
public class JPAPlugin extends PlayPlugin {
-
-
public static boolean autoTxs = true;
-
@Override
public Object bind(RootParamNode rootParamNode, String name, Class clazz, java.lang.reflect.Type type, Annotation[] annotations) {
@@ -110,74 +108,12 @@ public EntityManager em(String key) {
*/
@Override
public void onApplicationStart() {
- org.hibernate.ejb.HibernatePersistence persistence = new org.hibernate.ejb.HibernatePersistence();
org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.OFF);
Set dBNames = Configuration.getDbNames();
for (String dbName : dBNames) {
Configuration dbConfig = new Configuration(dbName);
- Ejb3Configuration cfg = new Ejb3Configuration();
- List classes = Play.classloader.getAnnotatedClasses(Entity.class);
- for (Class> clazz : classes) {
- if (clazz.isAnnotationPresent(Entity.class)) {
- // Do we have a transactional annotation matching our dbname?
- PersistenceUnit pu = clazz.getAnnotation(PersistenceUnit.class);
- if (pu != null && pu.name().equals(dbName)) {
- cfg.addAnnotatedClass(clazz);
- Logger.debug("Add JPA Model : %s to db %s", clazz, dbName);
- } else if (pu == null && JPA.DEFAULT.equals(dbName)) {
- cfg.addAnnotatedClass(clazz);
- Logger.debug("Add JPA Model : %s to db %s", clazz, dbName);
- }
- }
- }
-
- // Add entities
- String[] moreEntities = Play.configuration.getProperty("jpa.entities", "").split(", ");
- for (String entity : moreEntities) {
- if (entity.trim().equals("")) {
- continue;
- }
- try {
- Class> clazz = Play.classloader.loadClass(entity);
- // Do we have a transactional annotation matching our dbname?
- PersistenceUnit pu = clazz.getAnnotation(PersistenceUnit.class);
- if (pu != null && pu.name().equals(dbName)) {
- cfg.addAnnotatedClass(clazz);
- Logger.debug("Add JPA Model : %s to db %s", clazz, dbName);
- } else if (pu == null && JPA.DEFAULT.equals(dbName)) {
- cfg.addAnnotatedClass(clazz);
- Logger.debug("Add JPA Model : %s to db %s", clazz, dbName);
- }
- } catch (Exception e) {
- Logger.warn(e, "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 = dbConfig.getProperty("jpa.mapping-file", "");
- if (mappingFile != null && mappingFile.length() > 0) {
- cfg.addResource(mappingFile);
- }
-
- if (!dbConfig.getProperty("jpa.ddl", Play.mode.isDev() ? "update" : "none").equals("none")) {
- cfg.setProperty("hibernate.hbm2ddl.auto", dbConfig.getProperty("jpa.ddl", "update"));
- }
-
- Map properties = dbConfig.getProperties();
- properties.put("javax.persistence.transaction", "RESOURCE_LOCAL");
- properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
- properties.put("hibernate.dialect", getDefaultDialect(dbConfig, dbConfig.getProperty("db.driver")));
-
if (dbConfig.getProperty("jpa.debugSQL", "false").equals("true")) {
org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.ALL);
}
@@ -186,22 +122,92 @@ public void onApplicationStart() {
ClassLoader contextClassLoader = thread.getContextClassLoader();
thread.setContextClassLoader(Play.classloader);
try {
- cfg.configure(properties);
- cfg.setDataSource(DB.getDataSource(dbName));
-
- cfg.setInterceptor(new HibernateInterceptor());
if (Logger.isTraceEnabled()) {
Logger.trace("Initializing JPA for %s...", dbName);
}
-
- JPA.emfs.put(dbName, cfg.buildEntityManagerFactory());
+
+ JPA.emfs.put(dbName, newEntityManagerFactory(dbName, dbConfig));
} finally {
- if (thread != null) thread.setContextClassLoader(contextClassLoader);
+ thread.setContextClassLoader(contextClassLoader);
}
}
JPQL.instance = new JPQL();
}
+
+ private List entityClasses(String dbName) {
+ List entityClasses = new ArrayList<>();
+
+ List classes = Play.classloader.getAnnotatedClasses(Entity.class);
+ for (Class> clazz : classes) {
+ if (clazz.isAnnotationPresent(Entity.class)) {
+ // Do we have a transactional annotation matching our dbname?
+ PersistenceUnit pu = clazz.getAnnotation(PersistenceUnit.class);
+ if (pu != null && pu.name().equals(dbName)) {
+ entityClasses.add(clazz.getName());
+ } else if (pu == null && JPA.DEFAULT.equals(dbName)) {
+ entityClasses.add(clazz.getName());
+ }
+ }
+ }
+
+ // Add entities
+ String[] moreEntities = Play.configuration.getProperty("jpa.entities", "").split(", ");
+ for (String entity : moreEntities) {
+ if (entity.trim().equals("")) {
+ continue;
+ }
+ try {
+ Class> clazz = Play.classloader.loadClass(entity);
+ // Do we have a transactional annotation matching our dbname?
+ PersistenceUnit pu = clazz.getAnnotation(PersistenceUnit.class);
+ if (pu != null && pu.name().equals(dbName)) {
+ entityClasses.add(clazz.getName());
+ } else if (pu == null && JPA.DEFAULT.equals(dbName)) {
+ entityClasses.add(clazz.getName());
+ }
+ } catch (Exception e) {
+ Logger.warn(e, "JPA -> Entity not found: %s", entity);
+ }
+ }
+ return entityClasses;
+ }
+
+ protected EntityManagerFactory newEntityManagerFactory(String dbName, Configuration dbConfig) {
+ PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo(dbName, dbConfig);
+ Map configuration = new HashMap<>();
+ configuration.put(AvailableSettings.INTERCEPTOR, new HibernateInterceptor());
+
+ return new EntityManagerFactoryBuilderImpl(
+ new PersistenceUnitInfoDescriptor(persistenceUnitInfo), configuration
+ ).build();
+ }
+
+ protected PersistenceUnitInfoImpl persistenceUnitInfo(String dbName, Configuration dbConfig) {
+ return new PersistenceUnitInfoImpl(dbName,
+ entityClasses(dbName), mappingFiles(dbConfig), properties(dbName, dbConfig));
+ }
+
+ private List mappingFiles(Configuration dbConfig) {
+ String mappingFile = dbConfig.getProperty("jpa.mapping-file", "");
+ return mappingFile != null && mappingFile.length() > 0 ? singletonList(mappingFile) : emptyList();
+
+ }
+
+ protected Properties properties(String dbName, Configuration dbConfig) {
+ Properties properties = new Properties();
+ properties.putAll(dbConfig.getProperties());
+ properties.put("javax.persistence.transaction", "RESOURCE_LOCAL");
+ properties.put("javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence");
+ properties.put("hibernate.dialect", getDefaultDialect(dbConfig, dbConfig.getProperty("db.driver")));
+
+ if (!dbConfig.getProperty("jpa.ddl", Play.mode.isDev() ? "update" : "none").equals("none")) {
+ properties.setProperty("hibernate.hbm2ddl.auto", dbConfig.getProperty("jpa.ddl", "update"));
+ }
+
+ properties.put("hibernate.connection.datasource", DB.getDataSource(dbName));
+ return properties;
+ }
public static String getDefaultDialect(String driver) {
return getDefaultDialect(new Configuration("default"), driver);
@@ -257,15 +263,18 @@ public static String getDefaultDialect(Configuration dbConfig, String driver) {
@Override
public void onApplicationStop() {
- // Close all presistence units
- for(EntityManagerFactory emf: JPA.emfs.values()) {
- if(emf.isOpen()){
+ closeAllPersistenceUnits();
+ }
+
+ private void closeAllPersistenceUnits() {
+ for (EntityManagerFactory emf : JPA.emfs.values()) {
+ if (emf.isOpen()) {
emf.close();
}
}
- JPA.emfs.clear();
+ JPA.emfs.clear();
}
-
+
@Override
public void afterFixtureLoad() {
if (JPA.isEnabled()) {
diff --git a/framework/src/play/db/jpa/PersistenceUnitInfoImpl.java b/framework/src/play/db/jpa/PersistenceUnitInfoImpl.java
new file mode 100644
index 0000000000..1394fe1b0d
--- /dev/null
+++ b/framework/src/play/db/jpa/PersistenceUnitInfoImpl.java
@@ -0,0 +1,141 @@
+package play.db.jpa;
+
+import org.hibernate.jpa.HibernatePersistenceProvider;
+
+import javax.persistence.SharedCacheMode;
+import javax.persistence.ValidationMode;
+import javax.persistence.spi.ClassTransformer;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Vlad Mihalcea
+ *
+ * Taken from https://vladmihalcea.com/2015/11/26/how-to-bootstrap-hibernate-without-the-persistence-xml-file/
+ */
+public class PersistenceUnitInfoImpl implements PersistenceUnitInfo {
+
+ private final String persistenceUnitName;
+
+ private PersistenceUnitTransactionType transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
+
+ private final List managedClassNames;
+ private final List mappingFileNames;
+
+ private final Properties properties;
+
+ private DataSource jtaDataSource;
+
+ private DataSource nonJtaDataSource;
+
+ public PersistenceUnitInfoImpl(String persistenceUnitName, List managedClassNames, List mappingFileNames, Properties properties) {
+ this.persistenceUnitName = persistenceUnitName;
+ this.managedClassNames = managedClassNames;
+ this.mappingFileNames = mappingFileNames;
+ this.properties = properties;
+ }
+
+ @Override
+ public String getPersistenceUnitName() {
+ return persistenceUnitName;
+ }
+
+ @Override
+ public String getPersistenceProviderClassName() {
+ return HibernatePersistenceProvider.class.getName();
+ }
+
+ @Override
+ public PersistenceUnitTransactionType getTransactionType() {
+ return transactionType;
+ }
+
+ @Override
+ public DataSource getJtaDataSource() {
+ return jtaDataSource;
+ }
+
+ public PersistenceUnitInfoImpl setJtaDataSource(DataSource jtaDataSource) {
+ this.jtaDataSource = jtaDataSource;
+ this.nonJtaDataSource = null;
+ transactionType = PersistenceUnitTransactionType.JTA;
+ return this;
+ }
+
+ @Override
+ public DataSource getNonJtaDataSource() {
+ return nonJtaDataSource;
+ }
+
+ public PersistenceUnitInfoImpl setNonJtaDataSource(DataSource nonJtaDataSource) {
+ this.nonJtaDataSource = nonJtaDataSource;
+ this.jtaDataSource = null;
+ transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
+ return this;
+ }
+
+ @Override
+ public List getMappingFileNames() {
+ return mappingFileNames;
+ }
+
+ @Override
+ public List getJarFileUrls() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public URL getPersistenceUnitRootUrl() {
+ return null;
+ }
+
+ @Override
+ public List getManagedClassNames() {
+ return managedClassNames;
+ }
+
+ @Override
+ public boolean excludeUnlistedClasses() {
+ return false;
+ }
+
+ @Override
+ public SharedCacheMode getSharedCacheMode() {
+ return SharedCacheMode.UNSPECIFIED;
+ }
+
+ @Override
+ public ValidationMode getValidationMode() {
+ return ValidationMode.AUTO;
+ }
+
+ @Override
+ public Properties getProperties() {
+ return properties;
+ }
+
+ @Override
+ public String getPersistenceXMLSchemaVersion() {
+ return "2.1";
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+
+ @Override
+ public void addTransformer(ClassTransformer transformer) {
+
+ }
+
+ @Override
+ public ClassLoader getNewTempClassLoader() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/samples-and-tests/forum/app/models/Forum.java b/samples-and-tests/forum/app/models/Forum.java
index 558afb73e7..e51903d44d 100644
--- a/samples-and-tests/forum/app/models/Forum.java
+++ b/samples-and-tests/forum/app/models/Forum.java
@@ -46,7 +46,7 @@ public List getTopics(int page, int pageSize) {
}
public Post getLastPost() {
- return Post.find("topic.forum = ? order by postedAt desc", this).first();
+ return Post.find("topic.forum = ?1 order by postedAt desc", this).first();
}
}
diff --git a/samples-and-tests/forum/app/models/Topic.java b/samples-and-tests/forum/app/models/Topic.java
index 2de5867b01..95d6f47d17 100644
--- a/samples-and-tests/forum/app/models/Topic.java
+++ b/samples-and-tests/forum/app/models/Topic.java
@@ -50,7 +50,7 @@ public Long getVoicesCount() {
}
public Post getLastPost() {
- return Post.find("topic = ? order by postedAt desc", this).first();
+ return Post.find("topic = ?1 order by postedAt desc", this).first();
}
}
diff --git a/samples-and-tests/forum/app/models/User.java b/samples-and-tests/forum/app/models/User.java
index 9a323aa4cb..7b859fb7a4 100644
--- a/samples-and-tests/forum/app/models/User.java
+++ b/samples-and-tests/forum/app/models/User.java
@@ -46,7 +46,7 @@ public boolean isAdmin() {
// ~~~~~~~~~~~~
public List getRecentsPosts() {
- return Post.find("postedBy = ? order by postedAt", this).fetch(1, 10);
+ return Post.find("postedBy = ?1 order by postedAt", this).fetch(1, 10);
}
public Long getPostsCount() {
diff --git a/samples-and-tests/just-test-cases/test/SimpleJPATest.java b/samples-and-tests/just-test-cases/test/SimpleJPATest.java
index bca2e1fe9c..fb274e50b2 100644
--- a/samples-and-tests/just-test-cases/test/SimpleJPATest.java
+++ b/samples-and-tests/just-test-cases/test/SimpleJPATest.java
@@ -103,13 +103,13 @@ public void simpleFinders() {
User b = users.get(1);
//
assertEquals(a, User.find("name", "A").first());
- assertEquals(a, User.find("name = ?", "A").first());
- assertEquals(a, User.find("name=?", "A").first());
- assertEquals(b, User.find("name = ? and c = ?", "B", true).first());
- assertNull(User.find("name = ? and c = ?", "B", false).first());
- assertEquals(a, User.find("name like ? and j = ?", "%A%", 45).first());
- assertEquals(b, User.find("name like ? and b = ? and c = ? and l = ? and i = ?", "%B%", false, true, 10000L, 34).first());
- assertNull(User.find("name like ? and b = ? and c = ? and l = ? and i = ?", "%B%", false, true, 10000L, 32).first());
+ assertEquals(a, User.find("name = ?1", "A").first());
+ assertEquals(a, User.find("name=?1", "A").first());
+ assertEquals(b, User.find("name = ?1 and c = ?2", "B", true).first());
+ assertNull(User.find("name = ?1 and c = ?2", "B", false).first());
+ assertEquals(a, User.find("name like ?1 and j = ?2", "%A%", 45).first());
+ assertEquals(b, User.find("name like ?1 and b = ?2 and c = ?3 and l = ?4 and i = ?5", "%B%", false, true, 10000L, 34).first());
+ assertNull(User.find("name like ?1 and b = ?2 and c = ?3 and l = ?4 and i = ?5", "%B%", false, true, 10000L, 32).first());
assertEquals(a, User.find("b is null").first());
assertEquals(b, User.find("b is not null").first());
}
@@ -120,21 +120,21 @@ public void fullFinders() {
User a = users.get(0);
User b = users.get(1);
//
- assertEquals(a, User.find("from User where name = ?", "A").first());
- assertEquals(b, User.find("from User where name = ? and c = ?", "B", true).first());
- assertNull(User.find("from User where name = ? and c = ?", "B", false).first());
- assertEquals(a, User.find("from User where name like ? and j = ?", "%A%", 45).first());
- assertEquals(b, User.find("from User where name like ? and b = ? and c = ? and l = ? and i = ?", "%B%", false, true, 10000L, 34).first());
- assertNull(User.find("from User where name like ? and b = ? and c = ? and l = ? and i = ?", "%B%", false, true, 10000L, 32).first());
+ assertEquals(a, User.find("from User where name = ?1", "A").first());
+ assertEquals(b, User.find("from User where name = ?1 and c = ?2", "B", true).first());
+ assertNull(User.find("from User where name = ?1 and c = ?2", "B", false).first());
+ assertEquals(a, User.find("from User where name like ?1 and j = ?2", "%A%", 45).first());
+ assertEquals(b, User.find("from User where name like ?1 and b = ?2 and c = ?3 and l = ?4 and i = ?5", "%B%", false, true, 10000L, 34).first());
+ assertNull(User.find("from User where name like ?1 and b = ?2 and c = ?3 and l = ?4 and i = ?5", "%B%", false, true, 10000L, 32).first());
assertEquals(a, User.find("from User where b is null").first());
assertEquals(b, User.find("from User where b is not null").first());
- assertEquals(a, User.find("select u from User u where u.name = ?", "A").first());
- assertEquals(b, User.find("select u from User u where u.name = ? and u.c = ?", "B", true).first());
- assertNull(User.find("select u from User u where u.name = ? and u.c = ?", "B", false).first());
- assertEquals(a, User.find("select u from User u where u.name like ? and u.j = ?", "%A%", 45).first());
- assertEquals(b, User.find("select u from User u where u.name like ? and u.b = ? and u.c = ? and u.l = ? and u.i = ?", "%B%", false, true, 10000L, 34).first());
- assertNull(User.find("select u from User u where u.name like ? and u.b = ? and u.c = ? and u.l = ? and u.i = ?", "%B%", false, true, 10000L, 32).first());
+ assertEquals(a, User.find("select u from User u where u.name = ?1", "A").first());
+ assertEquals(b, User.find("select u from User u where u.name = ?1 and u.c = ?2", "B", true).first());
+ assertNull(User.find("select u from User u where u.name = ?1 and u.c = ?2", "B", false).first());
+ assertEquals(a, User.find("select u from User u where u.name like ?1 and u.j = ?2", "%A%", 45).first());
+ assertEquals(b, User.find("select u from User u where u.name like ?1 and u.b = ?2 and u.c = ?3 and u.l = ?4 and u.i = ?5", "%B%", false, true, 10000L, 34).first());
+ assertNull(User.find("select u from User u where u.name like ?1 and u.b = ?2 and u.c = ?3 and u.l = ?4 and u.i = ?5", "%B%", false, true, 10000L, 32).first());
assertEquals(a, User.find("select u from User u where u.b is null").first());
assertEquals(b, User.find("select u from User u where u.b is not null").first());
}
@@ -214,5 +214,4 @@ public void testEquals() {
assertFalse(userA.equals(a1)); // compare scalar key to array key
assertFalse(a1.equals(userA)); // compare array key with scalar key
}
-}
-
+}
\ No newline at end of file
diff --git a/samples-and-tests/yabe/app/models/Post.java b/samples-and-tests/yabe/app/models/Post.java
index c64f547e9c..eb6630c219 100644
--- a/samples-and-tests/yabe/app/models/Post.java
+++ b/samples-and-tests/yabe/app/models/Post.java
@@ -62,7 +62,7 @@ public Post tagItWith(String name) {
public static List findTaggedWith(String tag) {
return Post.find(
- "select distinct p from Post p join p.tags as t where t.name = ?",
+ "select distinct p from Post p join p.tags as t where t.name = ?1",
tag
).fetch();
}