原文:https://devcenter.heroku.com/articles/connecting-to-relational-databases-on-heroku-with-java
部署在Heroku上的应用程序可以使用多种关系数据库服务,包括Heroku提供的Postgres数据库和AWS(亚马逊)提供的MySQL数据库。
数据库的提供是通过使用add-on系统实现的。默认情况下,应用将会被提供一个小的并且免费的Postgres数据库,你可以通过如下的命令来检查提供的数据库:
$ heroku info === sparkling-wine-2003 Web URL: http://sparkling-wine-2003.herokuapp.com/ Git Repo: [email protected]:sparkling-wine-2003.git Repo size: 21M Slug size: 916k Stack: cedar Data size: (empty) Addons: Heroku Postgresql Dev Owner: [email protected]可以看到Addons项中的“Heroku Postgresql Dev”。这个是根据应用构建默认添加的,你还可以手动使用如下命令添加:
$ heroku addons:add heroku-postgresql这里的dev 数据库意味着,此数据库仅是为了测试而用。对于要发部的应用应该使用 Heroku Postgres数据库或SQL add-ons.
注解:这里说明的是使用系统默认提供的数据库仅为了满足测试而用,要想获得更高的数据库性能,必须使用那些Add-ons收费的数据库服务,但对于小打小闹的我来说,免费的Heroku PostgreSQL dev提供的10,000行数据,已经足够了。
当你的应用添加了一个关系型数据库时,你就可以通过读取DATABASE_URL
配置变量来获取数据库的连接信息,对应它的格式如下:
[database type]://[username]:[password]@[host]:[port]/[database name]例如:
postgres://foo:[email protected]:5432/hellodb你可以通过如下命令来获取Heroku提供给你的
DATABASE_URL
变量:
$ heroku config DATABASE_URL => postgres://foo:[email protected]:5432/hellodb在这里不推荐将如上的
DATABASE_URL
环境变量复制到一个静态的文件中通过程序解析。因为这样不方便应用环境的变更。对于一个实例应用来说,可以直接通过读取系统的环境变量来获取
DATABASE_URL
,从而解析获取数据库的连接信息。
DATEBASE_URL获取
JDBC连接如下通过JDBC直接访问数据库,代码如下:
private Connection getConnection() throws URISyntaxException, SQLException { URI dbUri = new URI(System.getenv("DATABASE_URL")); String username = dbUri.getUserInfo().split(":")[0]; String password = dbUri.getUserInfo().split(":")[1]; String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + dbUri.getPath(); return DriverManager.getConnection(dbUrl, username, password); }
本段Spring XML配置文件中将通过DATEBASE_URL配置一个BasicDataSource Bean,这样方便与Hibernate,JPA等进行整合,如下:
<bean class="java.net.URI" id="dbUrl"> <constructor-arg value="#{systemEnvironment['DATABASE_URL']}"/> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + '/' + @dbUrl.getPath() }"/> <property name="username" value="#{ @dbUrl.getUserInfo().split(':')[0] }"/> <property name="password" value="#{ @dbUrl.getUserInfo().split(':')[1] }"/> </bean>
另外,还可以直接在Spring的代码中通过DATABASE_URL来获取一个BasicDataSource对象,如下:
@Configuration public class MainConfig { @Bean public BasicDataSource dataSource() throws URISyntaxException { URI dbUri = new URI(System.getenv("DATABASE_URL")); String username = dbUri.getUserInfo().split(":")[0]; String password = dbUri.getUserInfo().split(":")[1]; String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + "/" + dbUri.getPath(); BasicDataSource basicDataSource = new BasicDataSource(); basicDataSource.setUrl(dbUrl); basicDataSource.setUsername(username); basicDataSource.setPassword(password); return basicDataSource; } }注意:
在Heroku Postgres的DATABASE_URL使用的是如下形式:
postgres://<username>:<password>@<host>/<dbname>而在PostgresSQL中JDBC的URL应该使用的是如下形式:
jdbc:postgresql://<host>:<port>/<dbname>?username=<username>&password=<password>注意这里的两个URL是不同的,因此在使用时,需要手动的处理一下,使其符合PostgresSQL的JDBC标准。
如果使用的是Heroku Postgres数据库,你可以通过远程连接来管理和调试它。如果实现这,需要建立一个SSL连接:在你的JDBC连接的URL中,需要加上如下参数:
ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory如果ssl为false,将会得到一个连接错误,同时如果不设置sslfactory=org.postgresql.ssl.NonValidatingFactory,你将可能得到如下错误:
unable to find valid certification path to requested target点击 这里,可获取更多关于Postgres JDBC 驱动的SSL支持。而对于其实的SQL数据库,请参考相应的JDBC文档。
注解:关于PostgresSQL的远程连接本人未试过,上面的只是照搬过来的。
在这里有Heroku官网提供的一个以三种方式(包括使用Java的Play框架,由于我没学过,因此上面的关于Play的处理我忽略了,详情见原文)连接数据库的示例项目:https://github.com/heroku/devcenter-java-database。
关于示例项目的运行,先要根据Heroku给你分配的DATABASE_URL,在本地也要仿造设置一个DATABASE_URL环境变量:
在Linux/Mac平台下,使用如下命令:
export DATABASE_URL=postgres://foo:foo@localhost/hellodb在Windows平台下,使用如下命令:
set DATABASE_URL=postgres://foo:foo@localhost/hellodb注意:在设置好变量后,不要关闭命令行或终端,需要继续在其中运行命令才行。
设置好环境变量后,接着就是运行了,由于上面的示例项目都使用Maven生成了相应的批处理或Shell脚本文件,因此运行这些程序直接运行这些脚本就行,如下:
在Linux/Mac平台下:
sh devcenter-java-database-plain-jdbc/target/bin/main sh devcenter-java-database-spring-xml/target/bin/main sh devcenter-java-database-spring-java/target/bin/main在Windows平台下:
devcenter-java-database-plain-jdbc/target/bin/main.bat devcenter-java-database-spring-xml/target/bin/main.bat devcenter-java-database-spring-java/target/bin/main.bat如果一切顺利,你将会看到如下的提示信息:
Read from DB: 2011-11-23 11:37:03.886016
接着就是将其部署到Heroku上了,这与部署普通的Java应用是一样,在本地运行通过后,直接使用Git Pushing上传代码于Heroku就行了。
关于部置Java应用到Heroku上,请参考我的上篇文章:http://blog.csdn.net/xianqiang1/article/details/8587123。
关于上面的示例项目Pushing上传后的运行,需要额外的使用如下命令:
$ heroku run "sh devcenter-java-database-plain-jdbc/target/bin/main" Running sh devcenter-java-database-plain-jdbc/target/bin/main attached to terminal... up, run.1 Read from DB: 2011-11-29 20:36:25.001468注解:由上面的信息可知Heroku上的运行环境,应该是LINUX,呵呵。关于原文中设置环境变量后在本地运行,我的是测试失败了,原因是数据库连接不上,可以是在国内,访问Heroku国外的数据库,网络跟不上吧。
运行heroku run "Shell脚本"命令可以在heroku端执行shell脚本命令。
注意:这里执行的所有Heroku命令需要在你的项目的根目录下执行。