Skip to content

10. Oracle Express 11g release 2

Passiamo ora al porting su Oracle Express 11g release 2 di quanto realizzato con MySQL5.

10.1. Configurazione dell'ambiente di lavoro

10.1.1. Ambiente Eclipse

Lavoreremo con il seguente ambiente Eclipse:

  

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

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

Avviare Oracle Express e il relativo client [OraManager] (cfr. paragrafo 23.6). Si procederà a generare:

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

10.1.2. Creazione degli utenti

Ora tutte le operazioni si svolgono in [OraManager]. È necessario avviare il processo Oracle SGBD. Si utilizzano le credenziali system / system per l’amministratore di sistema (che deve essere stato configurato in precedenza). Creeremo due utenti:

  • [DBPRODUITS / dbproduits], che sarà il proprietario del database [dbproduits];
  • [DBPRODUITSCATEGORIES / dbproduitscategories], che sarà il proprietario del database [dbproduits];
  • in [6-7], gli identificativi sono [system / system];
  • in [14]: inserire dbproduits;
  • in [16], l'utente è stato creato ma non dispone dei diritti sufficienti per effettuare l'accesso. Glieli assegneremo tramite uno script SQL [17-18];
  • in [19], scrivere il nome dell'utente in maiuscolo;

Ripetiamo la stessa operazione per creare l’utente [DBPRODUITSCATEGORIES / dbproduitscategories]:

  

10.1.3. Installazione del driver JDBC di Oracle nel repository Maven

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

Una volta scaricato, è necessario installarlo nel repository Maven locale. Ciò avviene tramite il seguente script:

"%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%] va sostituito con il percorso della directory di installazione di Maven (cfr. paragrafo 23.2). Una volta fatto ciò, il driver JDBC può essere importato nei progetti Maven tramite la configurazione:


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

10.1.4. Generazione del database [dbproduits]

Ora che disponiamo di un utente [DBPRODUITS / dbproduits], effettueremo l’accesso a Oracle con queste credenziali:

  • in [6], inserire dbproduits;
  • in [9], il database [DBPRODUITS] che utilizzeremo;

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 adattarli 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 {

    // campi
    @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 di generazione della chiave primaria della tabella [PRODUITS] è [strategy=GenerationType.SEQUENCE]. Per MySQL era stata utilizzata la strategia [@GeneratedValue(strategy = GenerationType.IDENTITY)]. Con Oracle Express 11g, questa strategia non è utilizzabile;
  • riga 18: si specifica che la chiave primaria sarà generata tramite 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é si desidera garantire la portabilità tra le implementazioni JPA, è importante assegnare un nome alla sequenza. Altrimenti, in assenza della riga 19, le tre implementazioni JPA creeranno sequenze che non avranno lo stesso nome, rendendo impossibile l’utilizzo da parte di JPA2 di 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 [PRODUITS];
  • una sequenza denominata [PRODUITS_SEQUENCE]

Il valore DDL della tabella [PRODUITS] è il seguente:

 

La chiave primaria [ID] non è autoincrementale come lo era MySQL. Tuttavia, il progetto [spring-jdbc-03] presuppone che SGBD si occupi di generare le chiavi primarie della tabella [PRODUITS]. Creeremo un trigger o un déclencheur. Un trigger è una procedura memorizzata all’interno del SGBD che viene eseguita a determinate condizioni. Creeremo un trigger che, ad ogni nuovo inserimento, generi la chiave primaria del prodotto inserito a partire dalla sequenza [PRODUITS_SEQUENCE] creata dalla configurazione JPA.

  • in [6], il trigger [PRODUITS_ID_TRIGGER] [4] verrà eseguito prima di ogni inserimento;
  • in [7], una procedura memorizzata specifica per SGBD Oracle. Essa indica che il campo [ID] della riga che sta per essere inserita deve essere inizializzato con il seguente valore 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 tutte andare a buon fine.

10.1.5. Generazione del database [dbproduitscategories]

  

Ora eseguiamo il progetto [generic-create-dbproduitscategories] che genererà il database [dbproduitscategories]. Prima di farlo, in [OraManager], effettuiamo l’accesso con le credenziali di [DBPRODUITSCATEGORIES / dbproduitscategories] per poter osservare le modifiche apportate al database [dbproduitscategories]:

  

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

[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 {
    // proprietà
    @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 {
    // proprietà
    @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 {
    // proprietà
    @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 {
    // proprietà
    @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 già fatto per la base [dbproduits], verranno generate cinque sequenze. Queste vengono utilizzate dalle implementazioni JPA per generare le chiavi primarie. Le implementazioni JPA non utilizzano trigger come abbiamo fatto in precedenza, ma interrogano le sequenze per ottenere la chiave primaria successiva. Noi, invece, genereremo le chiavi primarie anche con 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 nel modo seguente:

Table
Trigger
Séquence
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
  

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

Si esegue questa operazione per tutte e cinque le tabelle.

Ora eseguire le configurazioni:

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

Entrambe devono andare a buon fine.

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] del livello JDBC del SGBD MySQL (cfr. paragrafo 3.3). Presentiamo 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>
        <!-- dipendenze variabili ********************************************** -->
        <!-- driver JDBC del SGBD -->
        <dependency>
            <groupId>com.oracle.jdbc</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>1.0</version>
        </dependency>
        <!-- dipendenze costanti ********************************************** -->
        ....
    </dependencies>
...
</project>
  • righe 18-22: il driver JDBC di Oracle sostituisce quello di MySQL;

La seconda modifica riguarda la classe [ConfigJdbc] che definisce gli identificativi di accesso ai database:


    // parametri di connessione
    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 driver può supportare:


    // numero massimo di parametri di un [PreparedStatement]
    public final static int MAX_PREPAREDSTATEMENT_PARAMETERS = 1000;

Il test [JUnitTestPushTheLimits] genera comandi SQL su 5000 prodotti che a loro volta genereranno [PreparedStatement] con 5000 parametri. MySQL supportava questo valore, ma Oracle no. Abbiamo ridotto questo valore a 1000 e ora funziona.

 

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

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

Il progetto è analogo al progetto di configurazione [mysql-config-jpa-eclipselink] (cfr. paragrafo 7.3) del livello JPA Eclipselink del SGBD MySQL. Riportiamo solo le modifiche:

La prima si trova nella classe [ConfigJpa], nella definizione del bean [jpaVendorAdapter]:


    // il provider JPA
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        // Nota: le entità JPA e la configurazione di EclipseLink si trovano nel file META-INF/persistence.xml
        EclipseLinkJpaVendorAdapter eclipseLinkJpaVendorAdapter = new EclipseLinkJpaVendorAdapter();
        eclipseLinkJpaVendorAdapter.setShowSql(false);
        eclipseLinkJpaVendorAdapter.setDatabase(Database.ORACLE);
        eclipseLinkJpaVendorAdapter.setGenerateDdl(true);
        return eclipseLinkJpaVendorAdapter;
}
  • riga 7: si indica all’implementazione JPA che opererà con un database Oracle. L’implementazione JPA adotterà quindi sia i tipi di dati proprietari sia il SQL proprietario di Oracle.

La seconda modifica riguarda la strategia di generazione delle chiavi primarie. La nuova strategia è stata illustrata nel paragrafo 10.1.

10.4. Configurazione del livello Hibernate JPA

 

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

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

Una volta apportate queste modifiche, l'esecuzione della configurazione [spring-jpa-generic-JUnitTestDao-hibernate-eclipselink] dovrebbe andare a buon fine.

10.5. Configurazione del livello JPA OpenJpa

 

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

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

Una volta apportate queste modifiche, l'esecuzione della configurazione [spring-jpa-generic-JUnitTestDao-openjpa] dovrebbe andare a buon fine.