将TERASOLUNA5.x的空白项目更改为支持PostgreSQL的方法
首先
在TERASOLUNA Server Framework for Java (5.x)的空白项目的初始状态下,默认配置使用内存数据库h2db。今天我想留下个人备忘录,介绍如何将数据库更改为PostgreSQL的方法。
1.1. 验证环境
-
- Java 1.8.0_131
-
- TERASOLUNA Server Framework for Java 5.3.0
-
- PostgreSQL 9.3
- Apache Tomcat 8.0.44
1.2. PostgreSQL兼容性修改的流程
下面展示了将空白项目更改为支持PostgreSQL的工作流程。请注意,本次将使用应用程序内准备的连接池而不是在应用程序服务器(Servlet容器)的数据源上定义的连接池。
2. 创建空白项目
根据公开的指南中的“3.1.2. 开发项目的创建”部分的步骤,我们将创建一个空白项目。
本次项目的设置如下,在C:\work作为当前目录下创建空白项目。
4artifactIddemo-database-postgresql
mvn archetype:generate -B^
-DarchetypeGroupId=org.terasoluna.gfw.blank^
-DarchetypeArtifactId=terasoluna-gfw-multi-web-blank-mybatis3-archetype^
-DarchetypeVersion=5.3.0.RELEASE^
-DgroupId=com.example.demo.postgresql^
-DartifactId=demo-database-postgresql^
-Dversion=1.0.0-SNAPSHOT
... 省略 ...
[INFO] Parameter: groupId, Value: com.example.demo.postgresql
[INFO] Parameter: artifactId, Value: demo-database-postgresql
[INFO] Parent element not overwritten in C:\work\demo-database-postgresql\demo-database-postgresql-env\pom.xml
[INFO] Parent element not overwritten in C:\work\demo-database-postgresql\demo-database-postgresql-domain\pom.xml
[INFO] Parent element not overwritten in C:\work\demo-database-postgresql\demo-database-postgresql-web\pom.xml
[INFO] Parent element not overwritten in C:\work\demo-database-postgresql\demo-database-postgresql-initdb\pom.xml
[INFO] Parent element not overwritten in C:\work\demo-database-postgresql\demo-database-postgresql-selenium\pom.xml
[INFO] Project created from Archetype in dir: C:\work\demo-database-postgresql
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 26.941 s
[INFO] Finished at: 2017-08-31T10:12:00+09:00
[INFO] Final Memory: 10M/48M
[INFO] ------------------------------------------------------------------------
C:\work>
如果出现”BUILD SUCCESS”的显示,并且在C:\work目录下成功创建了以artifactId为指定的demo-database-postgresql目录,则表示成功。
3. 数据库准备利用
创建并使用数据库和用户,以便执行DDL语句。
我们在本地主机上使用以下设置,在PostgreSQL上准备了数据库。
在父级pom的依赖关系中添加要使用的数据库库。
在最初的状态下,Oracle和PostgreSQL的设置是以注释方式进行描述的。
取消PostgreSQL的注释并使其生效。
- 対象ファイル:C:\work\demo-database-postgresql\pom.xml
<!-- == Begin Database == -->
<!-- <dependency> -->
<!-- <groupId>org.postgresql</groupId> -->
<!-- <artifactId>postgresql</artifactId> -->
<!-- <version>${postgresql.version}</version> -->
<!-- </dependency> -->
<!-- <dependency> -->
<!-- <groupId>com.oracle</groupId> -->
<!-- <artifactId>ojdbc7</artifactId> -->
<!-- <version>${ojdbc.version}</version> -->
<!-- </dependency> -->
<!-- == End Database == -->
<!-- == Begin Database == -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<!-- <dependency> -->
<!-- <groupId>com.oracle</groupId> -->
<!-- <artifactId>ojdbc7</artifactId> -->
<!-- <version>${ojdbc.version}</version> -->
<!-- </dependency> -->
<!-- == End Database == -->
5. 禁用应用程序启动时的数据库初始化处理。
在空白项目的初始状态下,即DI容器启动时,也就是应用程序启动时,会执行指定的DDL文件,该文件是通过指定的。虽然在使用内存数据库时是必要的,但在一般的Web应用程序中,我认为这个功能是不需要的。我们可以将的描述注释掉以禁用它。
- 対象ファイル:C:\work\demo-database-postgresql\demo-database-postgresql-env\src\main\resources\META-INF\spring\demo-database-postgresql-env.xml
<jdbc:initialize-database data-source="dataSource"
ignore-failures="ALL">
<jdbc:script location="classpath:/database/${database}-schema.sql" encoding="UTF-8" />
<jdbc:script location="classpath:/database/${database}-dataload.sql" encoding="UTF-8" />
</jdbc:initialize-database>
<!--
<jdbc:initialize-database data-source="dataSource"
ignore-failures="ALL">
<jdbc:script location="classpath:/database/${database}-schema.sql" encoding="UTF-8" />
<jdbc:script location="classpath:/database/${database}-dataload.sql" encoding="UTF-8" />
</jdbc:initialize-database>
-->
(选项)禁用log4jdbc通过JDBC进行日志记录。
当在@Transactional(readOnly = true)中将事务设置为只读时,使用log4jdbc记录日志时会出现错误消息的日志输出。
date:2017-08-31 20:04:25 thread:http-nio-8080-exec-2 X-Track:b67e7712dcc143f398f5e51b762e3dea level:ERROR logger:jdbc.audit message:2. Connection.setReadOnly(true)
org.postgresql.util.PSQLException: トランザクションの最中に読み出し専用プロパティを変えることはできません。
at org.postgresql.jdbc2.AbstractJdbc2Connection.setReadOnly(AbstractJdbc2Connection.java:741)
at org.apache.commons.dbcp2.DelegatingConnection.setReadOnly(DelegatingConnection.java:562)
at org.apache.commons.dbcp2.DelegatingConnection.setReadOnly(DelegatingConnection.java:562)
at net.sf.log4jdbc.ConnectionSpy.setReadOnly(ConnectionSpy.java:374)
... 省略 ...
虽然在应用程序中设置为“只读”,但由于log4jdbc需要“可读写”事务,这是理所当然的。
由于错误消息仅输出到日志中,不会影响应用程序的处理,但由于个人原因,我总是禁用log4jdbc,这让我有些不安。
禁用该功能的方法很简单,只需删除Log4jdbcProxyDataSource的Bean定义,并将dataSource的BeanId更改为dbcp2的数据源即可。
- 対象ファイル:C:\work\demo-database-postgresql\demo-database-postgresql-env\src\main\resources\META-INF\spring\demo-database-postgresql-env.xml
<bean id="realDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="defaultAutoCommit" value="false" />
<property name="maxTotal" value="${cp.maxActive}" />
<property name="maxIdle" value="${cp.maxIdle}" />
<property name="minIdle" value="${cp.minIdle}" />
<property name="maxWaitMillis" value="${cp.maxWait}" />
</bean>
<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
<constructor-arg index="0" ref="realDataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="defaultAutoCommit" value="false" />
<property name="maxTotal" value="${cp.maxActive}" />
<property name="maxIdle" value="${cp.maxIdle}" />
<property name="minIdle" value="${cp.minIdle}" />
<property name="maxWaitMillis" value="${cp.maxWait}" />
</bean>
<!--
<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
<constructor-arg index="0" ref="realDataSource" />
</bean>
-->
7. 数据库连接的更改
这次我们将介绍如何在应用程序中使用dbcp2连接池。因此,数据库的连接信息(URL、端口号、用户ID、密码等)需要在应用程序中进行管理。
在TERASOLUNA5.x的默认设置中,这些信息可以定义在***infra.properties文件中。
另外,如果要使用JNDI来使用应用程序服务器的datasource,将在另一个机会进行说明。
- 対象ファイル:C:\work\demo-database-postgresql\demo-database-postgresql-env\src\main\resources\META-INF\spring\demo-database-postgresql-infra.properties
database=H2
database.url=jdbc:h2:mem:demo-database-postgresql;DB_CLOSE_DELAY=-1
database.username=sa
database.password=
database.driverClassName=org.h2.Driver
# connection pool
cp.maxActive=96
cp.maxIdle=16
cp.minIdle=0
cp.maxWait=60000
### default setting is H2
# database=H2
# database.url=jdbc:h2:mem:demo-database-postgresql;DB_CLOSE_DELAY=-1
# database.username=sa
# database.password=
# database.driverClassName=org.h2.Driver
### setting for postgreSQL
database=POSTGRESQL
database.url=jdbc:postgresql://127.0.0.1:5432/demodb
database.username=demoUser
database.password=demoPass
database.driverClassName=org.postgresql.Driver
# connection pool
cp.maxActive=96
cp.maxIdle=16
cp.minIdle=0
cp.maxWait=60000
把要使用的数据库库添加到domain项目的依赖关系中。
初始状态下,Oracle和PostgreSQL的设置被注释掉了。
取消注释PostgreSQL的内容使其生效。
- 対象ファイル:C:\work\demo-database-postgresql\demo-database-postgresql-domain\pom.xml
<!-- == Begin Database == -->
<!-- <dependency> -->
<!-- <groupId>org.postgresql</groupId> -->
<!-- <artifactId>postgresql</artifactId> -->
<!-- <scope>test</scope> -->
<!-- </dependency> -->
<!-- <dependency> -->
<!-- <groupId>com.oracle</groupId> -->
<!-- <artifactId>ojdbc7</artifactId> -->
<!-- <scope>test</scope> -->
<!-- </dependency> -->
<!-- == End Database == -->
<!-- == Begin Database == -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency> -->
<!-- <groupId>com.oracle</groupId> -->
<!-- <artifactId>ojdbc7</artifactId> -->
<!-- <scope>test</scope> -->
<!-- </dependency> -->
<!-- == End Database == -->
9. (选项)修复initdb项目
initdb项目中也保存了数据库的连接信息。不过,由于initdb项目本身就是用来进行数据库初始构建的,所以如果不使用initdb,就不需要进行任何修正。
需要进行修正的地方是设置数据库连接信息的、和。
- 対象ファイル:C:\work\demo-database-postgresql\demo-database-postgresql-initdb\pom.xml
<profile>
<id>local-postgres</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<db.encoding>UTF8</db.encoding>
<db.basedir>${project.basedir}/src/main/sqls/postgres</db.basedir>
<db.url>jdbc:postgresql://127.0.0.1:5432/projectName</db.url>
<db.username>postgres</db.username>
<db.password>P0stgres</db.password>
<db.driver>org.postgresql.Driver</db.driver>
<db.groupId>org.postgresql</db.groupId>
<db.artifactId>postgresql</db.artifactId>
<db.version>${postgresql.version}</db.version>
<db.delimiterType>row</db.delimiterType>
</properties>
</profile>
<profile>
<id>local-postgres</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<db.encoding>UTF8</db.encoding>
<db.basedir>${project.basedir}/src/main/sqls/postgres</db.basedir>
<db.url>jdbc:postgresql://127.0.0.1:5432/demodb</db.url>
<db.username>demoUser</db.username>
<db.password>demoPass</db.password>
<db.driver>org.postgresql.Driver</db.driver>
<db.groupId>org.postgresql</db.groupId>
<db.artifactId>postgresql</db.artifactId>
<db.version>${postgresql.version}</db.version>
<db.delimiterType>row</db.delimiterType>
</properties>
</profile>
10. 使用initdb项目构建数据库(选项)。
10.1. 创建用于数据库构建的DDL
在構建数据库时,使用的DDL将存储在前述的指定的目录中。在本例中,目录为C:\work\demo-database-postgresql\demo-database-postgresql-initdb\src\main\sqls\postgres。由于该目录在初始状态下不存在,需要创建该目录。
为了按照文件名排序并逐一执行,请在命名文件时注意执行顺序。
虽然本次未创建,但如有需要,请准备用于创建顺序或索引的DDL。
DROP TABLE IF EXISTS employee;
-- 社員テーブル --
CREATE TABLE employee (
-- 社員ID
employee_id varchar(10) NOT NULL,
-- 氏名
name varchar(30) NOT NULL,
-- 入社日
register_date date NOT NULL,
-- ポイント
point numeric(3,0) NOT NULL,
-- 主キー制約
CONSTRAINT EMPLOYEE_PK PRIMARY KEY(employee_id)
);
INSERT INTO employee (employee_id, name, register_date, point) VALUES ('0000000777', '試験 太郎', to_date('2016/04/01', 'yyyy/MM/dd'), 10);
COMMIT;
10.2. 使用mvn sql:execute命令来构建数据库。
在initdb项目中运行mvn sql:execute命令时,将执行前述准备的DDL,完成数据库的构建和初始化操作。
C:\work\demo-database-postgresql\demo-database-postgresql-initdb>mvn sql:execute
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building demo-database-postgresql-initdb 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- sql-maven-plugin:1.5:execute (default-cli) @ demo-database-postgresql-initdb ---
[INFO] Executing file: C:\work\demo-database-postgresql\demo-database-postgresql-initdb\src\main\sqls\postgres\00000_dro
p_all_tables.sql
[INFO] Executing file: C:\work\demo-database-postgresql\demo-database-postgresql-initdb\src\main\sqls\postgres\00100_cre
ate_all_tables.sql
[INFO] Executing file: C:\work\demo-database-postgresql\demo-database-postgresql-initdb\src\main\sqls\postgres\00200_ins
ert_employee.sql
[INFO] 3 of 3 SQL statements executed successfully
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.217 s
[INFO] Finished at: 2017-08-31T10:56:24+09:00
[INFO] Final Memory: 8M/20M
[INFO] ------------------------------------------------------------------------
C:\work\demo-database-postgresql\demo-database-postgresql-initdb>
请确认已成功执行了3个SQL语句并且已经顺利结束,也确认了BUILD SUCCESS。
11. 试用版本建造
为了支持PostgreSQL,我们修改了许多配置文件。为了确认没有任何问题,我们将进行试验性构建。
C:\work\demo-database-postgresql>mvn package
[INFO] Scanning for projects...
... 省略 ...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] TERASOLUNA Server Framework for Java (5.x) Web Blank Multi Project (MyBatis3) SUCCESS [ 0.015 s]
[INFO] demo-database-postgresql-env ....................... SUCCESS [ 1.248 s]
[INFO] demo-database-postgresql-domain .................... SUCCESS [ 0.359 s]
[INFO] demo-database-postgresql-web ....................... SUCCESS [ 4.883 s]
[INFO] demo-database-postgresql-initdb .................... SUCCESS [ 0.031 s]
[INFO] demo-database-postgresql-selenium .................. SUCCESS [ 2.090 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.048 s
[INFO] Finished at: 2017-08-31T10:57:46+09:00
[INFO] Final Memory: 35M/84M
[INFO] ------------------------------------------------------------------------
C:\work\demo-database-postgresql>
只要出现“构建成功”,就可以确认在构建过程中没有发现任何问题所在。
试启动
如果试用版本的构建正常完成,则会有C:\work\demo-database-postgresql\demo-database-postgresql-web\target\demo-database-postgresql-web.war文件存在。我们将把demo-database-postgresql-web.war文件复制到Tomcat安装目录下的/webapps目录中进行部署。
运行Tomcat安装目录/bin/startup.bat,启动Tomcat。
使用Web浏览器访问http://localhost:8080/demo-database-postgresql-web/,如果显示默认页面上的“Hello world!”,则表示成功。
13. 最后
本次讲解了如何将TERASOLUNA5.x的空白项目更改为支持PostgreSQL的方法。通常情况下,只需要在创建项目时进行一次数据库设置,因此机会并不多。然而,如果项目的初始设置未完成,就无法进行应用程序(业务处理)的开发,因此希望能迅速应对。