Play 2.6 访问SQL数据库
访问SQL数据库
Note: JDBC是一种阻塞操作。你不能直接在controller中运行JDBC查询语句。详见配置CustomExecutionContext章节 |
配置JDBC连接池
Play提供插件来管理连接池,你可以根据需要配置多个数据库。
为了启动数据库插件,需要添加以下依赖:
libraryDependencies += javaJdbc
然后需要字application.conf中配置连接池。出于方便考虑默认JDBC数据源必须叫做default
# Default database configuration
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
如果需要添加别的数据源
# Orders database
db.orders.driver=org.h2.Driver
db.orders.url="jdbc:h2:mem:orders"
# Customers database
db.customers.driver=org.h2.Driver
db.customers.url="jdbc:h2:mem:customers"
H2
# Default database configuration using H2 database engine in an in-memory mode
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
# Default database configuration using H2 database engine in a persistent mode
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:/path/to/db-file"
SQLite
# Default database configuration using SQLite database engine
db.default.driver=org.sqlite.JDBC
db.default.url="jdbc:sqlite:/path/to/db-file"
PostgreSQL
# Default database configuration using PostgreSQL database engine
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://database.example.com/playdb"
MySql
# Default database configuration using MySQL database engine
# Connect to playdb as playdbuser
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost/playdb"
db.default.username=playdbuser
db.default.password="a strong password"
获取JDBC数据源
play.db包提供了获取default数据的方法,主要是通过play.db.DataBase类
/*
* Copyright (C) 2009-2017 Lightbend Inc. <https://www.lightbend.com>
*/
package javaguide.sql;
import javax.inject.*;
import play.db.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@Singleton
class JavaApplicationDatabase {
private Database db;
private DatabaseExecutionContext executionContext;
@Inject
public JavaApplicationDatabase(Database db, DatabaseExecutionContext context) {
this.db = db;
this.executionContext = executionContext;
}
public CompletionStage<Integer> updateSomething() {
return CompletableFuture.supplyAsync(() -> {
return db.withConnection(connection -> {
// do whatever you need with the db connection
return 1;
});
}, executionContext);
}
}
对于其他的数据库
/*
* Copyright (C) 2009-2017 Lightbend Inc. <https://www.lightbend.com>
*/
package javaguide.sql;
import javax.inject.Inject;
import javax.inject.Singleton;
import play.mvc.Controller;
import play.db.NamedDatabase;
import play.db.Database;
// inject "orders" database instead of "default"
@javax.inject.Singleton
class JavaNamedDatabase {
private Database db;
private DatabaseExecutionContext executionContext;
@Inject
public JavaNamedDatabase(@NamedDatabase("orders") Database db, DatabaseExecutionContext executionContext) {
this.db = db;
this.executionContext = executionContext;
}
// do whatever you need with the db using supplyAsync(() -> { ... }, executionContext);
}
配置CustomExecutionContext
在使用JDBC时必须要使用一个自定义的执行上下文,来保证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}
}
}
获取JDBC连接
/*
* Copyright (C) 2009-2017 Lightbend Inc. <https://www.lightbend.com>
*/
package javaguide.sql;
import java.sql.Connection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
import play.mvc.Controller;
import play.db.NamedDatabase;
import play.db.Database;
class JavaJdbcConnection {
private Database db;
private DatabaseExecutionContext executionContext;
@Inject
public JavaJdbcConnection(Database db, DatabaseExecutionContext executionContext) {
this.db = db;
this.executionContext = executionContext;
}
public CompletionStage<Void> updateSomething() {
return CompletableFuture.runAsync(() -> {
// get jdbc connection
Connection connection = db.getConnection();
// do whatever you need with the db connection
return;
}, executionContext);
}
}
需要注意的是你要在代码的某个地方调用closs()方法。
通过JNDI暴露数据源
有些库需要通过JNDI来获取Datasource引用,可以在application.conf中进行如下配置
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.default.jndiName=DefaultDS
如何配置SQL log
不是所有的连接池都提供SQL语句的日志。HikariCP建议我们使用数据库提供商的log功能:
Log Statement Text / Slow Query Logging
就像是语句的缓存,大多数数据库提供商都支持SQL日志。其中的一些还能提供慢查询日志。我们认为这是一个开发阶段的特性。对于那些不支持的数据,jdbcdslog-exp是一个很好的选择。
出于以上的原因,Play使用jdbcdslog-exp来启用SQL语句输出的支持,可以通过logSql来配置
# Default database configuration using PostgreSQL database engine
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://database.example.com/playdb"
db.default.logSql=true
然后根据jdbcdslog-exp的手册(该连接需要*)来配置日志级别。大体上,需要将root设置为info,然后确定jdbcdslog-exp输出哪些内容(连接,语句和结果集)。下面是一个例子
<!--
~ Copyright (C) 2009-2017 Lightbend Inc. <https://www.lightbend.com>
-->
<!-- The default logback configuration that Play uses if no other configuration is provided -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>
<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />
<!-- https://hibernate.atlassian.net/browse/HV-1323 -->
<logger name="org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator" level="ERROR" />
<logger name="org.jdbcdslog.ConnectionLogger" level="OFF" /> <!-- Won' log connections -->
<logger name="org.jdbcdslog.StatementLogger" level="INFO" /> <!-- Will log all statements -->
<logger name="org.jdbcdslog.ResultSetLogger" level="OFF" /> <!-- Won' log result sets -->
<root level="WARN">
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>
Note: 这些配置仅适用于开发环境。 |
配置JDBC驱动
如果使用MySql5,
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.41"
选择和配置连接池
Play提供了两种连接池,HikariCP和BoneCP。默认的是HikariCP,可以进行修改
play.db.pool=bonecp
所有可配置的选择在 reference.conf(写在application.conf中应该也是可以的)
测试
启用Play数据库提升
根据文档查看Play数据库提升的用途及用法。
上一篇: Play 2.6 使用Play WS调用REST API
下一篇: Vue2.6踩坑
推荐阅读
-
解决SQL SERVER数据库备份时出现“操作系统错误5(拒绝访问)。BACKUP DATABASE 正在异常终止。”错误的解决办法
-
Linux下通过python访问MySQL、Oracle、SQL Server数据库的方法
-
C#访问SQL Server数据库的实现方法
-
.net(C#数据库访问) Mysql,Sql server,Sqlite,Access四种数据库的连接方式
-
go语言通过odbc访问Sql Server数据库的方法
-
Ruby中访问SQL Server数据库的配置实例
-
sql server 数据库创建链接服务器访问另外一个sql server 数据库
-
sql server 数据库创建链接服务器访问另外一个sql server 数据库
-
MyBatis 连接本地数据库拒绝访问错误:java.sql.SQLException: Access denied for user 'root
-
Powershell访问SQL Server数据库代码实例