Skip to content

10. Oracle Express 11g Release 2

接下来我们将讨论如何将针对 MySQL 5 所做的改动移植到 Oracle Express 11g Release 2 上。

10.1. 搭建开发环境

10.1.1. Eclipse 环境

我们将使用以下 Eclipse 环境:

  

上述 Oracle 项目位于 [<examples>/spring-database-config\oracle\eclipse] 文件夹中。

注意:按 [Alt-F5] 可重新生成所有 Maven 项目。

启动 Oracle Express 及其客户端 [OraManager](参见第 23.6 节)。我们将使用 [generic-create-dbproduits] 项目生成:

  • 使用 [generic-create-dbproduits] 项目生成 [dbproduits] 数据库;
  • 使用 [generic-create-dbproduitscategories] 项目生成 [dbproduitscategories] 数据库;

10.1.2. 创建用户

现在所有操作都在 [OraManager] 中进行。Oracle 数据库管理系统必须正在运行。我们使用 system / system 凭据登录系统管理员(此配置必须已预先完成)。我们将创建两个用户:

  • [DBPRODUITS / dbproduits],该用户将作为 [dbproduits] 数据库的所有者;
  • [DBPRODUCTSCATEGORIES / dbproducts-categories],该用户将作为 [dbproducts-categories] 数据库的所有者;
  • 在 [6-7] 中,凭据为 [system / system];
  • 在 [14] 中:输入 dbproduits
  • 在 [16] 中,用户已创建,但没有足够的权限登录。我们将通过一个 SQL 脚本 [17-18] 授予其权限;
  • 在 [19] 中,请输入大写用户名;

我们采用相同的方法创建用户 [DBPRODUITSCATEGORIES / dbproduitscategories]:

  

10.1.3. 在 Maven 仓库中安装 Oracle JDBC 驱动程序

Oracle JDBC 驱动程序在中央 Maven 存储库中不可用。必须从 Oracle [http://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html] 下载:

下载完成后,必须将其安装到本地 Maven 仓库中。可通过以下 DOS 脚本 [install.bat] [2] 完成此操作:

"%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 {
 
    // fields
    @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] 配置了:

运行此配置将创建两个对象:

  • 一个表 [PRODUCTS];
  • 一个名为 [PRODUITS_SEQUENCE] 的序列

[PRODUCTS] 表的 DDL 如下:

 

主键 [ID] 不会像在 MySQL 中那样自动递增。不过,[spring-jdbc-03] 项目假设数据库管理系统(DBMS)会负责生成 [PRODUCTS] 表的主键。 我们将创建一个触发器。触发器是数据库管理系统(DBMS)中的一种存储过程,会在特定条件下执行。我们将创建一个触发器,该触发器会在每次插入新数据时,基于 JPA 配置创建的 [PRODUCTS_SEQUENCE] 序列,为插入的产品生成主键。

  • 在 [6] 中,触发器 [PRODUCTS_ID_TRIGGER] [4] 将在每次插入之前执行;
  • 在[7]中,这是一个针对Oracle数据库管理系统(DBMS)的存储过程。它规定待插入行的[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 实体具有以下主键生成策略:

[类别]


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;

[产品]


public class Produit implements AbstractCoreEntity {
    // properties
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqProduits2")
  @SequenceGenerator(name="genSeqProduits2",sequenceName="PRODUITS_SEQUENCE", allocationSize=5)
    @Column(name = ConfigJdbc.TAB_JPA_ID)
    protected Long id;

[角色]


public class Role implements AbstractCoreEntity {
    // properties
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="genSeqRoles")
  @SequenceGenerator(name="genSeqRoles",sequenceName="ROLES_SEQUENCE", allocationSize=5)
    @Column(name = ConfigJdbc.TAB_JPA_ID)
    protected Long id;

[用户]


public class User implements AbstractCoreEntity {
    // properties
    @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 {
    // properties
    @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_ID_TRIGGER
分类_序列
产品
产品ID触发器
PRODUCTS_SEQUENCE
ROLES
ROLES_ID_TRIGGER
ROLES_SEQUENCE
USERS
用户_ID_触发器
用户序列
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] 层:

该项目类似于 MySQL 数据库管理系统 (DBMS) 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>
        <!-- dépendances variables ********************************************** -->
        <!-- driver JDBC from SGBD -->
        <dependency>
            <groupId>com.oracle.jdbc</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>1.0</version>
        </dependency>
        <!-- dépendances constantes ********************************************** -->
        ....
    </dependencies>
...
</project>
  • 第 18-22 行:Oracle JDBC 驱动程序替换了 MySQL 驱动程序;

第二个改动在 [ConfigJdbc] 类中,该类定义了数据库凭据:


    // paramètres de connexion
    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";

第三项更改涉及 所能支持的参数最大数量:


    // max number of parameters of a [PreparedStatement]
    public final static int MAX_PREPAREDSTATEMENT_PARAMETERS = 1000;

[JUnitTestPushTheLimits] 测试会为 5,000 种产品生成 SQL 语句,这将生成包含 5,000 个参数的 [PreparedStatement] 对象。MySQL 支持此参数数量,但 Oracle 不支持。我们将该值降至 1,000 后,测试便能正常运行。

 

注意:按 [Alt-F5] 可重新生成所有 Maven 项目。

[oracle-config-jpa-eclipseLink] 项目用于配置测试架构的 [JPA] 层:

该项目与针对 MySQL 数据库管理系统(DBMS)的 EclipseLink JPA 层的 [mysql-config-jpa-eclipselink] 配置项目(参见第 7.3 节)类似。此处仅列出变更内容:

首先是在 [ConfigJpa] 类中对 [jpaVendorAdapter] Bean 的定义:


    // the provider JPA
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        // Note: JPA entities and Eclipselink configuration are in the META-INF/persistence.xml file
        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 JPA 层

 

注意:按 [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. 配置 OpenJpa JPA 层

 

注意:按 [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] 配置的执行应能成功。