Skip to content

10. Oracle Express 11g Release 2

Discuteremo ora del porting di quanto fatto con MySQL 5 su Oracle Express 11g Release 2.

10.1. Configurazione dell'ambiente di sviluppo

10.1.1. Ambiente Eclipse

Lavoreremo con il seguente ambiente Eclipse:

  

I progetti Oracle sopra elencati si trovano nella cartella [<examples>/spring-database-config\oracle\eclipse].

Nota: premere [Alt-F5] per rigenerare tutti i progetti Maven.

Avviare Oracle Express e il suo client [OraManager] (vedere la sezione 23.6). Genereremo:

  • il database [dbproduits] utilizzando il progetto [generic-create-dbproduits];
  • il database [dbproduitscategories] con il progetto [generic-create-dbproduitscategories];

10.1.2. Creazione degli utenti

Ora tutto avviene in [OraManager]. Il DBMS Oracle deve essere in esecuzione. Utilizziamo le credenziali system / system per l'amministratore di sistema (questo deve essere stato configurato in precedenza). Creeremo due utenti:

  • [DBPRODUITS / dbproduits], che sarà il proprietario del database [dbproduits];
  • [DBPRODUCTSCATEGORIES / dbproducts-categories], che sarà il proprietario del database [dbproducts-categories];
  • in [6-7], le credenziali sono [system / system];
  • in [14]: inserisci dbproduits;
  • in [16], l'utente è stato creato ma non dispone di autorizzazioni sufficienti per effettuare l'accesso. Le concederemo utilizzando uno script SQL [17-18];
  • in [19], inserisci il nome utente in maiuscolo;

Procediamo allo stesso modo per creare l'utente [DBPRODUITSCATEGORIES / dbproduitscategories]:

  

10.1.3. Installazione del driver JDBC Oracle nel repository Maven

Il driver JDBC Oracle non è disponibile nei repository Maven centrali. Deve essere scaricato dal sito Oracle [http://www.oracle.com/technetwork/apps-tech/jdbc-112010-090769.html]:

Una volta scaricato, deve essere installato nel repository Maven locale. Ciò avviene utilizzando il seguente 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

dove [%M2_HOME%] deve essere sostituito con il percorso della directory di installazione di Maven (vedere la sezione 23.2). Una volta fatto ciò, il driver JDBC può essere importato nei progetti Maven utilizzando la seguente configurazione:


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

10.1.4. Creazione del database [dbproduits]

Ora che disponiamo di un utente [DBPRODUITS / dbproduits], ci collegheremo a Oracle utilizzando queste credenziali:

  • in [6], inserisci dbproduits;
  • in [9], il database [DBPRODUITS] che useremo;

Nella classe [ConfigJdbc] del progetto [oracle-config-jdbc], i parametri di connessione utilizzati sono i seguenti:


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

È necessario adattare questi valori alla propria configurazione Oracle.

Nel progetto [oracle-config-jpa-eclipselink], l'entità JPA è definita come segue:

  

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;
 
...
}
  • righe 18-19: la strategia per la generazione della chiave primaria della tabella [PRODUITS] è [strategy=GenerationType.SEQUENCE]. Per MySQL, abbiamo utilizzato la strategia [ ] [@GeneratedValue(strategy = GenerationType.IDENTITY)]. Con Oracle Express 11g, questa strategia non può essere utilizzata;
  • riga 18: specifichiamo che la chiave primaria verrà generata utilizzando un generatore di numeri, spesso denominato sequenza;
  • riga 19: il generatore di sequenze (l'attributo name fa riferimento al generatore della riga 18) creerà una sequenza denominata [PRODUITS_SEQUENCE] nel database [dbproduits]. Poiché vogliamo garantire la portabilità tra le implementazioni JPA, è importante assegnare un nome alla sequenza. Altrimenti, senza la riga 19, le tre implementazioni JPA creeranno sequenze con nomi diversi, rendendo impossibile per JPA2 utilizzare un database creato da JPA1;

Siamo pronti per eseguire la configurazione [generic-create-dbproduits-eclipselink]:

L'esecuzione di questa configurazione crea due oggetti:

  • una tabella [PRODUCTS];
  • una sequenza denominata [PRODUITS_SEQUENCE]

Il DDL per la tabella [PRODUCTS] è il seguente:

 

La chiave primaria [ID] non viene autoincrementata come avveniva con MySQL. Tuttavia, il progetto [spring-jdbc-03] presuppone che il DBMS gestisca la generazione delle chiavi primarie per la tabella [PRODUCTS]. Creeremo un trigger. Un trigger è una procedura memorizzata all'interno del DBMS che viene eseguita in determinate condizioni. Creeremo un trigger che, ad ogni nuovo inserimento, generi la chiave primaria del prodotto inserito in base alla sequenza [PRODUCTS_SEQUENCE] creata dalla configurazione JPA.

  • In [6], il trigger [PRODUCTS_ID_TRIGGER] [4] verrà eseguito prima di ogni inserimento;
  • in [7], una procedura memorizzata specifica per il DBMS Oracle. Essa specifica che il campo [ID] della riga da inserire deve essere inizializzato con il valore successivo del generatore denominato [PRODUITS_SEQUENCE];
 

Il database [dbproduits] è ora pronto. Eseguire le seguenti configurazioni:

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

Devono tutti avere esito positivo.

10.1.5. Generazione del database [dbproduitscategories]

  

Ora eseguiremo il progetto [generic-create-dbproduitscategories], che genererà il database [dbproduitscategories]. Prima di farlo, in [OraManager], ci colleghiamo utilizzando le credenziali [DBPRODUITSCATEGORIES / dbproduitscategories] in modo da poter osservare le modifiche apportate al database [dbproduitscategories]:

  

Le entità JPA utilizzate hanno le seguenti strategie di generazione delle chiavi primarie:

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

[Prodotto]


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;

[Role]


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;

[Utente]


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;

Come è stato fatto per il database [dbproduits], verranno generate cinque sequenze. Queste vengono utilizzate dalle implementazioni JPA per generare le chiavi primarie. Le implementazioni JPA non utilizzano i trigger come abbiamo fatto in precedenza, ma interrogano invece le sequenze per ottenere la chiave primaria successiva. Genereremo le chiavi primarie anche utilizzando i trigger. Questi sono necessari per il progetto [spring-jdbc-04].

Eseguiamo la configurazione [generic-create-dbproduitscategories-eclipselink]:

e otteniamo il seguente risultato:

  

Generiamo quindi cinque trigger per generare le chiavi primarie delle cinque tabelle:

 

I trigger sono associati alle tabelle come segue:

Tabella
Trigger
Sequenza
CATEGORIE
CATEGORIE_ID_TRIGGER
CATEGORIE_SEQUENZA
PRODOTTI
PRODOTTI_ID_TRIGGER
PRODOTTI_SEQUENZA
RUOLI
ROLI_ID_TRIGGER
RUOLI_SEQUENZA
UTENTI
UTENTI_ID_TRIGGER
USERS_SEQUENCE
USERS_ROLES
USERS_ROLES_ID_TRIGGER
USERS_ROLES_SEQUENCE
  

Il progetto [spring-jdbc-04] richiede che la colonna [VERSIONING] abbia un valore predefinito in ciascuna delle tabelle:

Lo facciamo per tutte e cinque le tabelle.

Ora, esegui le configurazioni:

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

Entrambe dovrebbero superare il test.

10.2. Configurazione del livello JDBC

 

Il progetto [oracle-config-jdbc] configura il livello [JDBC] della seguente architettura di test:

Il progetto è analogo al progetto di configurazione [mysql-config-jdbc] per il livello JDBC del DBMS MySQL (vedere la Sezione 3.3). Riportiamo solo le modifiche:

Il file [pom.xml] importa il driver JDBC di 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>
  • righe 18-22: il driver JDBC Oracle sostituisce il driver MySQL;

La seconda modifica riguarda la classe [ConfigJdbc], che definisce le credenziali del database:


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

La terza modifica riguarda il numero massimo di parametri che un può supportare:


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

Il test [JUnitTestPushTheLimits] genera istruzioni SQL per 5.000 prodotti, il che genererà oggetti [PreparedStatement] con 5.000 parametri. MySQL supportava questo valore, ma Oracle no. Abbiamo ridotto questo valore a 1.000 e ora funziona.

 

Nota: premere [Alt-F5] per rigenerare tutti i progetti Maven.

Il progetto [oracle-config-jpa-eclipseLink] configura il livello [JPA] dell'architettura di test:

Il progetto è simile al progetto di configurazione [mysql-config-jpa-eclipselink] (vedere la Sezione 7.3) per il livello JPA di EclipseLink del DBMS MySQL. Presentiamo solo le modifiche:

La prima riguarda la classe [ConfigJpa] nella definizione del 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;
}
  • Riga 7: Indichiamo all'implementazione JPA che lavorerà con un database Oracle. L'implementazione JPA adotterà quindi i tipi di dati proprietari di Oracle e il linguaggio SQL.

La seconda modifica riguarda la strategia di generazione della chiave primaria. La nuova strategia è stata presentata nella Sezione 10.1.

10.4. Configurazione del livello JPA di Hibernate

 

Nota: premere [Alt-F5] per rigenerare tutti i progetti Maven.

Il progetto [oracle-config-jpa-hibernate] è analogo al progetto [mysql-config-jpa-hibernate] (Sezione 6.3) con le stesse modifiche che hanno guidato il porting di [mysql-config-jpa-eclipselink] al progetto [oracle-config-jpa-eclipselink] (Sezione 10.3).

Una volta apportate queste modifiche, l'esecuzione della configurazione [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink] dovrebbe avere esito positivo.

10.5. Configurazione del livello JPA di OpenJpa

 

Nota: premere [Alt-F5] per rigenerare tutti i progetti Maven.

Il progetto [oracle-config-jpa-openjpa] è simile al progetto [mysql-config-jpa-openjpa] (sezione 8.3) e presenta le stesse modifiche utilizzate per portare il progetto [mysql-config-jpa-eclipselink] al progetto [oracle-config-jpa-eclipselink] (Sezione 10.3).

Una volta apportate queste modifiche, l'esecuzione della configurazione [spring-jpa-generic-JUnitTestDao-openjpa] dovrebbe avere esito positivo.