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操作配置一个执行上下文。可以在 JavaAsyncThreadPools来获取更多细节。

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数据库提升的用途及用法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值