Play 2.6 使用JPA
使用JPA
https://playframework.com/documentation/2.6.x/JavaJPA
添加依赖
首先腰围工程添加javaJpa依赖,这里会提供JDBC和JPA的相关依赖。
Play中没有内建的JPA实现,可以使用任何可用的实现,下面的例子使用了Hibernate
libraryDependencies ++= Seq(
javaJpa,
"org.hibernate" % "hibernate-entitymanager" % "5.1.0.Final" // replace by your jpa implementation
)
通过JNDI暴露数据源
JPA需要通过JNDI来获取数据源。可以通过下面的配置来实现
db.default.jndiName=DefaultDS
创建一个持久化单元
现在需要创建一个persistence.xml JPA配置文件。将它放到conf/META0INF目录中,这样配置就会被添加到classpath中
下面是一个使用Hibernate的例子
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>DefaultDS</non-jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
</properties>
</persistence-unit>
</persistence>
最后在application.conf中告诉Play去用哪一个持久化单元
jpa.default=defaultPersistenceUnit
部署带有JPA的Play应用
以开发模式运行Play时JPA会很好的工作,但是为了部署应用需要在build.sbt添加以下配置
PlayKeys.externalizeResources := false
Note: 从Play2.4开始,conf目录默认添加到classpath中。这一选项会禁用这一情况,允许部署一个JPA应用。conf目录下的内容仍然在classpath中可用,因为这会被包含到应用程序的jar中。 |
使用play.db.jpa.JPAApi
Play提供了简便的API来使用Entity Manager和事物。这些API被定义到play.db.jpa.JPAApi中,可以通过注入的方式来获取实例
import play.db.jpa.JPAApi;
import javax.inject.*;
import javax.persistence.*;
import java.util.concurrent.*;
@Singleton
public class JPARepository {
private JPAApi jpaApi;
private DatabaseExecutionContext executionContext;
@Inject
public JPARepository(JPAApi api, DatabaseExecutionContext executionContext) {
this.jpaApi = api;
this.executionContext = executionContext;
}
}
建议将JPA的操作隔离到 Repository 或 DAO中,这样你可以用一个自定义的执行上下文和事物来管理所有的JPA操作
这意味着所有的JPA操作都在接口中完成,JPA类都是包私有的,(下面几句不知道如何翻译,希望有大神可以在评论区交流)there is no exposure of persistence aware objects to the rest of the application, and sessions are not held open past the method that defines an asynchronous boundary (i.e. returns CompletionStage).
这意味这你的domain对象包含了一个repository的内部引用,在调用时会返回实体和对象的列表,而不是一直保持着会话然后使用基于JPA的懒加载。
使用CustomExecutionContext
Note: 在action(使用Play的默认线程池)中直接使用JPA会限制Play异步处理的能力。因为JDBC是一种阻塞操作。 |
在使用JPA时必须要使用一个自定义的执行上下文,来保证Play的线程池专注与页面处理以及自己的功能。可以使用Play的CustomExecutionContext来为JDBC操作配置一个执行上下文。可以在 JavaAsync 和ThreadPools来获取更多细节。
https://github.com/playframework/play-java-jpa-example/ 提供了一个例子,例子中展示了 JPAPersonRepository将所有的JDBC操作封装进了DatabaseExecutionContext中。
由于线程池的大小对JDNC连接池有影响,在使用thred pool executor是,你需要一个可变大小的线程池来匹配连接池。根据[HikariCP]https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing)的建议,你需要将JDNC连接池的大小设置为物理核心数量的两倍再加上磁盘的数据。如果你又一个4核CPU加一个硬盘,你需要将连接池的大小设为9
# db connections = ((physical_core_count * 2) + effective_spindle_count)
fixedConnectionPool = 9
database.dispatcher {
executor = "thread-pool-executor"
throughput = 1
thread-pool-executor {
fixed-pool-size = ${fixedConnectionPool}
}
}
运行JPA事务
下面的例子可以运行任意的JPA事物
使用JPAApi.withTransaction(Function
public CompletionStage<Long> runningWithTransaction() {
return CompletableFuture.supplyAsync(() -> {
// lambda is an instance of Function<EntityManager, Long>
return jpaApi.withTransaction(entityManager -> {
Query query = entityManager.createNativeQuery("select max(age) from people");
return (Long) query.getSingleResult();
});
}, executionContext);
}
使用JPAApi.withTransaction(Runnable) 进行批量更新:
public CompletionStage<Void> runningWithRunnable() {
// lambda is an instance of Runnable
return CompletableFuture.runAsync(() -> {
jpaApi.withTransaction(() -> {
EntityManager em = jpaApi.em();
Query query = em.createNativeQuery("update people set active = 1 where age > 18");
query.executeUpdate();
});
}, executionContext);
}
启用Play数据库提升
根据文档查看Play数据库提升的用途及用法。
上一篇: 360云盘自动弹窗怎么设置永久性关闭?
下一篇: 百度网盘与360云盘哪个更好用?
推荐阅读
-
使用vue2.6实现抖音【时间轮盘】屏保效果附源码
-
使用Spring Data JPA的坑点记录总结
-
Spring boot中使用Spring-data-jpa方便快捷的访问数据库(推荐)
-
Spring Data JPA使用Sort进行排序(Using Sort)
-
详解Spring Data JPA使用@Query注解(Using @Query)
-
spring data jpa使用详解(推荐)
-
使用vue2.6实现抖音【时间轮盘】屏保效果附源码
-
在Spring Boot中使用Spring-data-jpa实现分页查询
-
使用Spring Data JPA进行数据分页与排序
-
详解Spring Data JPA使用@Query注解(Using @Query)