Skip to content

10. Oracle Express 11g Release 2

Vamos agora discutir a portabilidade do que foi feito com o MySQL 5 para o Oracle Express 11g Release 2.

10.1. Configurar o ambiente de desenvolvimento

10.1.1. Ambiente Eclipse

Iremos trabalhar com o seguinte ambiente Eclipse:

  

Os projetos Oracle acima referidos podem ser encontrados na pasta [<examples>/spring-database-config\oracle\eclipse].

Nota: Prima [Alt-F5] para regenerar todos os projetos Maven.

Inicie o Oracle Express e o seu cliente [OraManager] (consulte a secção 23.6). Iremos gerar:

  • a base de dados [dbproduits] utilizando o projeto [generic-create-dbproduits];
  • a base de dados [dbproduitscategories] com o projeto [generic-create-dbproduitscategories];

10.1.2. Criação de utilizadores

Tudo se realiza agora no [OraManager]. O SGBD Oracle deve estar em execução. Utilizamos as credenciais system/system para o administrador do sistema (estas devem ter sido configuradas previamente). Iremos criar dois utilizadores:

  • [DBPRODUITS / dbproduits], que será o proprietário da base de dados [dbproduits];
  • [DBPRODUCTSCATEGORIES / dbproducts-categories], que será o proprietário da base de dados [dbproducts-categories];
  • em [6-7], as credenciais são [system / system];
  • em [14]: introduza dbproduits;
  • em [16], o utilizador foi criado, mas não possui permissões suficientes para iniciar sessão. Iremos concedê-las utilizando um script SQL [17-18];
  • em [19], introduza o nome de utilizador em maiúsculas;

Fazemos o mesmo para criar o utilizador [DBPRODUITSCATEGORIES / dbproduitscategories]:

  

10.1.3. Instalação do controlador JDBC da Oracle no repositório Maven

O controlador JDBC da Oracle não está disponível nos repositórios centrais do Maven. Deve ser descarregado a partir do site da Oracle [http://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html]:

Depois de descarregado, deve ser instalado no repositório local do Maven. Isto é feito utilizando o seguinte script 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

onde [%M2_HOME%] deve ser substituído pelo caminho para o diretório de instalação do Maven (ver secção 23.2). Depois de feito isto, o controlador JDBC pode então ser importado para projetos Maven utilizando a seguinte configuração:


        <dependency>
            <groupId>com.oracle.jdbc</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>1.0</version>
</dependency>

10.1.4. Criação da base de dados [dbproduits]

Agora que temos um utilizador [DBPRODUITS / dbproduits], vamos ligar-nos ao Oracle utilizando estas credenciais:

  • em [6], introduza dbproduits;
  • em [9], a base de dados [DBPRODUITS] que iremos utilizar;

Na classe [ConfigJdbc] do projeto [oracle-config-jdbc], os parâmetros de ligação utilizados são os seguintes:


    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";

Deve adaptar estes valores à sua configuração Oracle.

No projeto [oracle-config-jpa-eclipselink], a entidade JPA é definida da seguinte forma:

  

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;
 
...
}
  • linhas 18-19: a estratégia para gerar a chave primária da tabela [PRODUITS] é [strategy=GenerationType.SEQUENCE]. Para o MySQL, utilizámos a estratégia [ ] [@GeneratedValue(strategy = GenerationType.IDENTITY)]. Com o Oracle Express 11g, esta estratégia não pode ser utilizada;
  • linha 18: especificamos que a chave primária será gerada utilizando um gerador de números, frequentemente referido como uma sequência;
  • linha 19: o gerador de sequências (o atributo name faz referência ao gerador da linha 18) criará uma sequência denominada [PRODUITS_SEQUENCE] na base de dados [dbproduits]. Como pretendemos portabilidade entre implementações JPA, é importante nomear a sequência. Caso contrário, sem a linha 19, as três implementações JPA criarão sequências com nomes diferentes, tornando impossível para o JPA2 utilizar uma base de dados criada pelo JPA1;

Estamos prontos para executar a configuração [generic-create-dbproduits-eclipselink]:

A execução desta configuração cria dois objetos:

  • uma tabela [PRODUCTS];
  • uma sequência denominada [PRODUITS_SEQUENCE]

O DDL para a tabela [PRODUCTS] é o seguinte:

 

A chave primária [ID] não é autoincrementada, como acontecia no MySQL. No entanto, o projeto [spring-jdbc-03] pressupõe que o SGBD lida com a geração de chaves primárias para a tabela [PRODUCTS]. Vamos criar um trigger. Um trigger é um procedimento armazenado no SGBD que é executado sob determinadas condições. Vamos criar um trigger que, a cada nova inserção, gere a chave primária do produto inserido com base na sequência [PRODUCTS_SEQUENCE] criada pela configuração JPA.

  • Em [6], o gatilho [PRODUCTS_ID_TRIGGER] [4] será executado antes de cada inserção;
  • em [7], um procedimento armazenado específico do SGBD Oracle. Este especifica que o campo [ID] da linha a inserir deve ser inicializado com o valor seguinte do gerador denominado [PRODUITS_SEQUENCE];
 

A base de dados [dbproduits] está agora pronta. Execute as seguintes configurações:

  • [spring-jdbc-generic-01.IntroJdbc01];
  • [spring-jdbc-generic-01.IntroJdbc02];
  • [spring-jdbc-generic-03.JUnitTestDao1];
  • [spring-jdbc-generic-03.JUnitTestDao2];

Todos têm de ser bem-sucedidos.

10.1.5. Gerar a base de dados [dbproduitscategories]

  

Vamos agora executar o projeto [generic-create-dbproduitscategories], que irá gerar a base de dados [dbproduitscategories]. Antes de o fazer, no [OraManager], ligamo-nos utilizando as credenciais [DBPRODUITSCATEGORIES / dbproduitscategories] para que possamos observar as alterações feitas na base de dados [dbproduitscategories]:

  

As entidades JPA utilizadas têm as seguintes estratégias de geração de chaves primárias:

[Categoria]


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;

[Produto]


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;

[Função]


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;

[Utilizador]


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;

Tal como foi feito para a base de dados [dbproduits], serão geradas cinco sequências. Estas são utilizadas pelas implementações JPA para gerar chaves primárias. As implementações JPA não utilizam gatilhos como fizemos anteriormente, mas sim consultam as sequências para obter a próxima chave primária. Também iremos gerar as chaves primárias utilizando gatilhos. Estas são necessárias para o projeto [spring-jdbc-04].

Executamos a configuração [generic-create-dbproduitscategories-eclipselink]:

e obtemos o seguinte resultado:

  

Em seguida, criamos cinco gatilhos para gerar as chaves primárias das cinco tabelas:

 

Os gatilhos estão associados às tabelas da seguinte forma:

Tabela
Gatilho
Sequência
CATEGORIAS
CATEGORIAS_ID_GATILHO
SEQUÊNCIA_DE_CATEGORIAS
PRODUTOS
PRODUTOS_ID_TRIGGER
SEQUÊNCIA_DE_PRODUTOS
FUNÇÕES
ID_DE_FUNÇÕES_TRIGGER
SEQUÊNCIA_DE_FUNÇÕES
USUÁRIOS
USUÁRIOS_ID_TRIGGER
USUÁRIOS_SEQUÊNCIA
USERS_ROLES
USUÁRIOS_FUNÇÕES_ID_TRIGGER
USUÁRIOS_FUNÇÕES_SEQUÊNCIA
  

O projeto [spring-jdbc-04] exige que a coluna [VERSIONING] tenha um valor padrão em cada uma das tabelas:

Fazemos isto para todas as cinco tabelas.

Agora, execute as configurações:

  • [spring-jdbc-generic-04.JUnitTestDao];
  • [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink];

Ambas devem ser aprovadas.

10.2. Configurar a camada JDBC

 

O projeto [oracle-config-jdbc] configura a camada [JDBC] da seguinte arquitetura de teste:

O projeto é análogo ao projeto de configuração [mysql-config-jdbc] para a camada JDBC do SGBD MySQL (ver Secção 3.3). Apresentamos apenas as alterações:

O ficheiro [pom.xml] importa o controlador JDBC da Oracle:


<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>
  • linhas 18-22: o controlador JDBC da Oracle substitui o controlador MySQL;

A segunda alteração está na classe [ConfigJdbc], que define as credenciais da base de dados:


    // 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";

A terceira alteração diz respeito ao número máximo de parâmetros que um pode suportar:


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

O teste [JUnitTestPushTheLimits] gera instruções SQL para 5.000 produtos, o que irá gerar objetos [PreparedStatement] com 5.000 parâmetros. O MySQL suportava este valor, mas o Oracle não. Reduzimos este valor para 1.000 e agora funciona.

 

Nota: Prima [Alt-F5] para regenerar todos os projetos Maven.

O projeto [oracle-config-jpa-eclipseLink] configura a camada [JPA] da arquitetura de teste:

O projeto é semelhante ao projeto de configuração [mysql-config-jpa-eclipselink] (ver Secção 7.3) para a camada JPA do EclipseLink do SGBD MySQL. Apresentamos apenas as alterações:

A primeira encontra-se na classe [ConfigJpa], na definição do bean [jpaVendorAdapter]:


    // 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;
}
  • Linha 7: Indicamos à implementação JPA que irá trabalhar com uma base de dados Oracle. A implementação JPA irá então adotar os tipos de dados e o SQL proprietários da Oracle.

A segunda alteração diz respeito à estratégia de geração da chave primária. A nova estratégia foi apresentada na Secção 10.1.

10.4. Configurar a camada JPA do Hibernate

 

Nota: Prima [Alt-F5] para regenerar todos os projetos Maven.

O projeto [oracle-config-jpa-hibernate] é análogo ao projeto [mysql-config-jpa-hibernate] (Secção 6.3), com as mesmas modificações que orientaram a portabilidade do [mysql-config-jpa-eclipselink] para o projeto [oracle-config-jpa-eclipselink] (Secção 10.3).

Com estas modificações implementadas, a execução da configuração [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink] deverá ser bem-sucedida.

10.5. Configurar a camada JPA do OpenJpa

 

Nota: Prima [Alt-F5] para regenerar todos os projetos Maven.

O projeto [oracle-config-jpa-openjpa] é semelhante ao projeto [mysql-config-jpa-openjpa] (secção 8.3), com as mesmas modificações que foram utilizadas para portar o projeto [mysql-config-jpa-eclipselink] para o projeto [oracle-config-jpa-eclipselink] (secção 10.3).

Com estas modificações implementadas, a execução da configuração [spring-jpa-generic-JUnitTestDao-openjpa] deverá ser bem-sucedida.