10. Oracle Express 11g Release 2
接下来,我们将探讨如何将 MySQL5 所完成的工作移植到 Oracle Express 11g release 2 上。
![]() |
10.1. 工作环境的搭建
10.1.1. Eclipse 环境
我们将使用以下 Eclipse 环境:
![]() |
上述 Oracle 项目位于 [<exemples>/spring-database-config\oracle\eclipse] 文件夹中。
注意:执行 [Alt-F5] 可重新生成所有 Maven 项目。
启动 Oracle Express 及其客户端 [OraManager](参见第 23.6 节)。我们将生成:
- 使用项目 [generic-create-dbproduits] 生成数据库 [dbproduits];
- 使用项目 [generic-create-dbproduitscategories] 生成数据库 [dbproduitscategories];
10.1.2. 创建用户
现在所有操作都在 [OraManager] 中进行。必须启动 Oracle 进程 SGBD。系统管理员使用 system / system 凭据(需预先配置)。我们将创建两个用户:
- [DBPRODUITS / dbproduits],该用户将拥有数据库 [dbproduits];
- [DBPRODUITSCATEGORIES / dbproduitscategories],该用户将拥有数据库 [dbproduits];
![]() |
![]() |
- 在 [6-7] 中,标识符为 [system / system];
![]() |
![]() |
- 在 [14] 中:改为 dbproduits;
- 在 [16] 中,用户已创建但无足够权限登录。我们将通过脚本为其授予权限:SQL [17-18];
![]() |
- 在 [19] 中,将用户名改为大写;
我们重复上述步骤来创建用户 [DBPRODUITSCATEGORIES / dbproduitscategories]:
![]() | ![]() |
![]() |
10.1.3. 将 Oracle 的 JDBC 驱动程序安装到 Maven 仓库
Oracle 的 JDBC 驱动程序在中央 Maven 仓库中不可用。必须从 Oracle 下载 [http://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html]:
![]() |
下载完成后,需将其安装到本地 Maven 仓库中。可通过以下脚本完成:
"%M2_HOME%\bin\mvn.bat" install:install-file -Dfile=ojdbc6.jar -Dpackaging=jar -DgroupId=com.oracle.jdbc -DartifactId=ojdbc6 -Dversion=1.0
其中需将 [%M2_HOME%] 替换为 Maven 的安装目录路径(参见第 23.2 节)。完成此操作后,即可通过以下配置将 JDBC 驱动程序导入 Maven 项目:
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>1.0</version>
</dependency>
10.1.4. 生成 [dbproduits] 数据库
现在我们已拥有用户 [DBPRODUITS / dbproduits],将使用以下凭据连接到 Oracle:
![]() |
![]() |
- 在 [6] 中,改为 dbproduits;
- 在 [9] 中,我们将使用 [DBPRODUITS] 作为基础;
在项目 [oracle-config-jdbc] 的类 [ConfigJdbc] 中,使用的连接参数如下:
public final static String DRIVER_CLASSNAME = "oracle.jdbc.OracleDriver";
public final static String URL_DBPRODUITS = "jdbc:oracle:thin:@localhost:1521:xe";
public final static String USER_DBPRODUITS = "DBPRODUITS";
public final static String PASSWD_DBPRODUITS = "dbproduits";
public final static String URL_DBPRODUITSCATEGORIES = "jdbc:oracle:thin:@localhost:1521:xe";
public final static String USER_DBPRODUITSCATEGORIES = "DBPRODUITSCATEGORIES";
public final static String PASSWD_DBPRODUITSCATEGORIES = "dbproduitscategories";
您需要根据您的 Oracle 配置进行调整。
在项目 [oracle-config-jpa-eclipselink] 中,实体 JPA 的定义如下:
![]() |
package generic.jpa.entities.dbproduits;
import generic.jdbc.config.ConfigJdbc;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity(name="Produit1")
@Table(name = ConfigJdbc.TAB_PRODUITS)
public class Produit {
// 字段
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqProduits")
@SequenceGenerator(name="genSeqProduits",sequenceName="PRODUITS_SEQUENCE", allocationSize=5)
@Column(name = ConfigJdbc.TAB_PRODUITS_ID)
private Long id;
@Column(name = ConfigJdbc.TAB_PRODUITS_NOM, unique = true, length = 30, nullable = false)
private String nom;
@Column(name = ConfigJdbc.TAB_PRODUITS_CATEGORIE, nullable = false)
private int categorie;
@Column(name = ConfigJdbc.TAB_PRODUITS_PRIX, nullable = false)
private double prix;
@Column(name = ConfigJdbc.TAB_PRODUITS_DESCRIPTION, length = 100, nullable = false)
private String description;
...
}
- 第 18-19 行:表 [PRODUITS] 的主键生成策略为 [strategy=GenerationType.SEQUENCE]。 对于 MySQL,此前使用的是策略 [@GeneratedValue(strategy = GenerationType.IDENTITY)]。在 Oracle Express 11g 中,该策略不可用;
- 第 18 行:指定主键将通过通常称为序列的数字生成器生成;
- 第 19 行:序列生成器(属性 name 引用第 18 行的生成器)将在数据库 [dbproduits] 中创建一个名为 [PRODUITS_SEQUENCE] 的序列。 由于需要确保 JPA 各实现之间的可移植性,因此为序列命名至关重要。 否则,若缺少第19行,三个JPA实现将创建名称不一致的序列,导致JPA2无法利用JPA1创建的数据库;
现在我们可以执行 [generic-create-dbproduits-eclipselink] 配置了:
![]() | ![]() |
执行此配置将创建两个对象:
- 一个表 [PRODUITS];
- 一个名为 [PRODUITS_SEQUENCE] 的序列
![]() | ![]() |
表 [PRODUITS] 中的 DDL 如下:
![]() |
主键 [ID] 并非像 MySQL 那样采用自增机制。 然而,项目 [spring-jdbc-03] 假设 SGBD 负责生成表 [PRODUITS] 的主键。 我们将创建一个 trigger 或 déclencheur。触发器是 SGBD 中的一个存储过程,会在特定条件下执行。 我们将创建一个触发器,该触发器在每次插入新数据时,会根据配置 JPA 创建的序列 [PRODUITS_SEQUENCE],生成所插入产品的主键。
![]() |
- 在 [6] 中,每次插入前都会执行触发器 [PRODUITS_ID_TRIGGER] [4];
- 在 [7] 中,一个专属于 SGBD 的 Oracle 存储过程。 该存储过程指定,即将插入的行中的字段 [ID] 必须使用名为 [PRODUITS_SEQUENCE] 的生成器生成的以下值进行初始化;
![]() |
数据库 [dbproduits] 现已准备就绪。请执行以下配置:
- [spring-jdbc-generic-01.IntroJdbc01];
- [spring-jdbc-generic-01.IntroJdbc02];
- [spring-jdbc-generic-03.JUnitTestDao1] ;
- [spring-jdbc-generic-03.JUnitTestDao2] ;
所有配置都必须成功。
10.1.5. 生成数据库 [dbproduitscategories]
![]() |
现在我们执行项目 [generic-create-dbproduitscategories],该项目将生成数据库 [dbproduitscategories]。 在此之前,在 [OraManager] 中,我们将使用 [DBPRODUITSCATEGORIES / dbproduitscategories] 的凭据登录,以便观察对 [dbproduitscategories] 数据库所做的修改:
![]() | ![]() | ![]() |
![]() | ![]() |
![]() |
所使用的 JPA 实体具有以下主键生成策略:
[Categorie]
public class Categorie implements AbstractCoreEntity {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqCategories")
@SequenceGenerator(name="genSeqCategories",sequenceName="CATEGORIES_SEQUENCE", allocationSize=5)
@Column(name = ConfigJdbc.TAB_JPA_ID)
protected Long id;
[Produit]
public class Produit implements AbstractCoreEntity {
// 属性
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqProduits2")
@SequenceGenerator(name="genSeqProduits2",sequenceName="PRODUITS_SEQUENCE", allocationSize=5)
@Column(name = ConfigJdbc.TAB_JPA_ID)
protected Long id;
[Role]
public class Role implements AbstractCoreEntity {
// 属性
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqRoles")
@SequenceGenerator(name="genSeqRoles",sequenceName="ROLES_SEQUENCE", allocationSize=5)
@Column(name = ConfigJdbc.TAB_JPA_ID)
protected Long id;
[User]
public class User implements AbstractCoreEntity {
// 属性
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqUsers")
@SequenceGenerator(name="genSeqUsers",sequenceName="USERS_SEQUENCE", allocationSize=5)
@Column(name = ConfigJdbc.TAB_JPA_ID)
protected Long id;
[UserRole]
public class UserRole implements AbstractCoreEntity {
// 属性
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqUsersRoles")
@SequenceGenerator(name="genSeqUsersRoles",sequenceName="USERS_ROLES_SEQUENCE", allocationSize=5)
@Column(name = ConfigJdbc.TAB_JPA_ID)
protected Long id;
与[dbproduits]数据库的操作方式相同,将生成五个序列。这些序列由JPA的实现用于生成主键。 JPA 实现方案不使用触发器(如我们之前所做),而是查询序列以获取下一个主键。而我们将同样使用触发器来生成主键。这些触发器对于 [spring-jdbc-04] 项目是必需的。
我们执行配置 [generic-create-dbproduitscategories-eclipselink]:
![]() | ![]() |
并得到以下结果:
![]() |
随后,我们生成五个触发器以生成这五个表的主键:
![]() |
触发器与表的关联方式如下:
CATEGORIES | CATEGORIES_ID_TRIGGER | CATEGORIES_SEQUENCE |
PRODUITS | PRODUITS_ID_TRIGGER | PRODUITS_SEQUENCE |
ROLES | ROLES_ID_TRIGGER | ROLES_SEQUENCE |
USERS | USERS_ID_TRIGGER | USERS_SEQUENCE |
USERS_ROLES | USERS_ROLES_ID_TRIGGER | USERS_ROLES_SEQUENCE |
![]() |
项目 [spring-jdbc-04] 要求在每个表中,列 [VERSIONING] 都必须具有默认值:
![]() | ![]() |
对这五个表都进行此操作。
现在,执行以下配置:
- [spring-jdbc-generic-04.JUnitTestDao] ;
- [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink] ;
这两项配置都应成功。
10.2. 配置 JDBC 层
![]() | ![]() |
项目 [oracle-config-jdbc] 配置了以下测试架构中的 [JDBC] 层:
![]() |
该项目与 SGBD 中的 JDBC 层的配置项目 [mysql-config-jdbc] 类似(参见第 3.3 节)。此处仅列出修改内容:
文件 [pom.xml] 导入了 Oracle 的驱动程序 JDBC:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dvp.spring.database</groupId>
<artifactId>generic-config-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>configuration generic jdbc</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
</parent>
<dependencies>
<!-- 变量依赖关系 ********************************************** -->
<!-- SGBD 的驱动程序 JDBC -->
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc6</artifactId>
<version>1.0</version>
</dependency>
<!-- 常量依赖项 ********************************************** -->
....
</dependencies>
...
</project>
- 第18-22行:Oracle的驱动程序JDBC替换了MySQL;
第二个修改位于定义数据库访问凭据的 [ConfigJdbc] 类中:
// 连接参数
public final static String DRIVER_CLASSNAME = "oracle.jdbc.OracleDriver";
public final static String URL_DBPRODUITS = "jdbc:oracle:thin:@localhost:1521:xe";
public final static String USER_DBPRODUITS = "DBPRODUITS";
public final static String PASSWD_DBPRODUITS = "dbproduits";
public final static String URL_DBPRODUITSCATEGORIES = "jdbc:oracle:thin:@localhost:1521:xe";
public final static String USER_DBPRODUITSCATEGORIES = "DBPRODUITSCATEGORIES";
public final static String PASSWD_DBPRODUITSCATEGORIES = "dbproduitscategories";
第三项修改涉及一个 所能支持的参数最大数量:
// [PreparedStatement] 的最大参数数
public final static int MAX_PREPAREDSTATEMENT_PARAMETERS = 1000;
测试程序 [JUnitTestPushTheLimits] 针对 5000 种产品生成 SQL 订单,这些订单将生成包含 5000 个参数的 [PreparedStatement]。虽然 MySQL 支持该参数数量,但 Oracle 无法处理。 我们将该值降至 1000 后,问题得以解决。
10.3. JPA 和 EclipseLink 层的配置
![]() | ![]() |
注:执行 [Alt-F5] 以重新生成所有 Maven 项目。
项目 [oracle-config-jpa-eclipseLink] 配置了测试架构中的 [JPA] 层:
![]() |
该项目与 SGBD 和 MySQL 中的 JPA Eclipselink 层的配置项目 [mysql-config-jpa-eclipselink](参见第 7.3 节)类似。 此处仅列出修改内容:
第一处修改位于 [ConfigJpa] 类中,具体在 [jpaVendorAdapter] Bean 的定义部分:
// 提供程序 JPA
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
// 注意:JPA 实体和 Eclipselink 配置位于文件 META-INF/persistence.xml 中
EclipseLinkJpaVendorAdapter eclipseLinkJpaVendorAdapter = new EclipseLinkJpaVendorAdapter();
eclipseLinkJpaVendorAdapter.setShowSql(false);
eclipseLinkJpaVendorAdapter.setDatabase(Database.ORACLE);
eclipseLinkJpaVendorAdapter.setGenerateDdl(true);
return eclipseLinkJpaVendorAdapter;
}
- 第 7 行:指示实现类 JPA 将与 Oracle 数据库配合使用。实现类 JPA 随后将采用 Oracle 的专有数据类型以及 SQL。
第二项修改涉及主键生成策略。新策略已在第 10.1 节中介绍。
10.4. Hibernate 层的配置
![]() | ![]() |
注:执行 [Alt-F5] 以重新生成所有 Maven 项目。
项目 [oracle-config-jpa-hibernate] 与项目 [mysql-config-jpa-hibernate](第 6.3 节)类似,采用了与将 [mysql-config-jpa-eclipselink] 移植到项目 [oracle-config-jpa-eclipselink] 时相同的修改 (第 10.3 节)。
完成这些修改后,[spring-jpa-generic-JUnitTestDao-hibernate-eclipselink]配置的执行应能成功。
10.5. JPA 层的配置 OpenJpa
![]() | ![]() |
注:执行 [Alt-F5] 以重新生成所有 Maven 项目。
项目 [oracle-config-jpa-openjpa] 与项目 [mysql-config-jpa-openjpa](第 8.3 节)类似,采用了与将 [mysql-config-jpa-eclipselink] 移植到项目 [oracle-config-jpa-eclipselink] 时相同的修改 (第 10.3 节)所采用的修改。
完成这些修改后,[spring-jpa-generic-JUnitTestDao-openjpa]的配置执行应能成功。
![]() | ![]() |














































