Follow Us on Twitter

Java Stored Procedures in de Oracle Database

Juni 2007 - Stored procedures zijn in de database opgeslagen programma’s die een bepaalde procedurele logica uitvoeren, meestal geconcentreerd rond het verwerken van SQL statements. Bijvoorbeeld een taak waarin wordt geselecteerd uit een tabel met orders die verwerkt moeten worden tot een tabel met facturen. Een groot voordeel van stored procedures is de snelle verwerking van de data doordat het programma in de database zelf draait en daarmee bovenop de data zit. De verwerking gaat, vooral door het ontbreken van netwerk overhead, sneller dan verwerking door een programma dat op een andere machine draait.

Traditioneel is PL/SQL de programmeertaal waarin stored procedures in de Oracle database zijn uitgevoerd. Deze taal is eigendom van Oracle en zit standaard in de database. Sinds database versie 8i biedt Oracle de mogelijkheid om stored procedures te maken in de programmeertaal Java. Ook voor Java Stored Procedures geldt het voordeel van snelle uitvoering van data intensieve operaties doordat het programma in de database draait en via speciale drivers snelle toegang heeft tot de data.

In een eerder Whitebook zijn de voordelen van het coderen van Java in de database aan bod gekomen, met name gezien vanuit het perspectief van de Java ontwikkelaar. Dit Whitebook neemt het perspectief van traditionele Oracle database ontwikkelaar, die gewend is aan PL/SQL. Het lijkt er namelijk op dat de Java Stored Procedures sinds hun introductie met 8i (dat was al in 1999) niet echt zijn aangeslagen onder database ontwikkelaars. Of dit terecht is - want wat zijn nu eigenlijk de voor- en nadelen van Java Stored Procedures - zal ook aan bod komen in dit Whitebook. Maar om te beginnen zullen we bekijken hoe de OracleJVM werkt, hoe Java Stored Procedures worden ontwikkeld en wat er zoal mee gedaan kan worden.

De OracleJVM

De Oracle database bevat een complete Java runtime omgeving: de Oracle Java virtual machine (OracleJVM). De OracleJVM draait in dezelfde proces en geheugenruimte als de database kernel, en heeft daarmee dezelfde snelle toegang tot de data als SQL en PL/SQL. Oracle heeft de JVM sterk geïntegreerd met haar eigen database sessie-architectuur.

Dit geeft Java dezelfde vorm van sessie-isolatie, data- integriteit en -security als er is voor SQL en PL/SQL. Een voordeel van deze aanpak is de schaalbaarheid van de Java applicatie; de Oracle database kan door haar opzet vele gebruikers tegelijkertijd bedienen en doordat de Oracle JVM gebruikt maakt van de bestaande structuren geldt hiervoor hetzelfde.

Met de keuze voor een sterke integratie met de database heeft Oracle het zichzelf een stuk lastiger gemaakt dan wanneer gekozen was voor een meer loosely-coupled benadering. Het even upgraden van de Oracle JVM naar een nieuwere Java versie is niet mogelijk binnen dezelfde databaseversie.

Ontwikkelen van Java Stored Procedures

De ontwikkeling van Java Stored Procedures gaat in vier stappen:

Stap 1 Schrijven van de Java class

Het schrijven van de Java klasse gaat op de gebruikelijke manier voor Java code: door simpelweg gebruik te maken van een text editor of een ontwikkelomgeving zoals JDeveloper. Een eenvoudig voorbeeld is een klasse die het aantal rijen in de opgegeven tabel telt:

package counters;

import java.sql.*;
import java.io.*;
import oracle.jdbc.*;

public class RowCounter {

   public static int rowCount (String tabName) throws SQLException {

      Connection conn =
      DriverManager.getConnection("jdbc:default:connection:");
      String sql = "SELECT COUNT(*) FROM " + tabName;
      int rows = 0;

      try {
         Statement stmt = conn.createStatement();
         ResultSet rset = stmt.executeQuery(sql);
         while (rset.next()) {rows = rset.getInt(1);}
         rset.close();
         stmt.close();
      }
      catch (SQLException e) {
         System.err.println(e.getMessage());
      }
      return rows;
   }

}

Wat opvalt in bovenstaande code is dat het niet nodig is om expliciet een JDBC driver bij de database te registreren. De Java stored procedure draait in de database en beschikt over een default sessie en transactie context. Je bent dus al verbonden met de database, een connectieobject verkrijgen kan simpelweg als volgt:

Connection conn = DriverManager.getConnection("jdbc:default:connection:");

Stap 2: De Java class in de database laden en compileren (resolven)

Met behulp van de loadjava utility kunnen Java source, class en resource bestanden in de database geladen worden. Ze worden opgeslagen als schemaobjecten, net zoals tabellen en PL/SQL procedures schemaobjecten zijn.

In ons voorbeeld starten we loadjava vanaf de command line:

$ loadjava -user scott/tiger@WH01 -verbose -resolve RowCounter.java

De optie -resolve zorgt ervoor dat de het .java bronbestand wordt gecompileerd en dat alle externe referenties naar andere Java classes worden gecontroleerd.

Het zojuist aangemaakt database object is als volgt op te vragen uit de datadictionary, de gecompileerde code is een eigen object:

SELECT object_name, object_type, status
FROM   user_objects
WHERE  object_type LIKE 'JAVA%';

OBJECT_NAME                   OBJECT_TYPE         STATUS
----------------------------- ------------------- -------
counters/RowCounter           JAVA SOURCE         VALID
counters/RowCounter           JAVA CLASS          VALID

2 rijen zijn geselecteerd.

Het laden van de Java code kan overigens ook via de SQL*Plus opdracht CREATE JAVA, een commando dat loadjava uiteindelijk ook uitvoert. Wanneer je echter direct de gecompileerde Java bytecode (.class file) of bijvoorbeeld een resource bestand in de database wilt laden moet je gebruik maken van een hulptabel met een BLOB kolom. Loadjava is in de praktijk een stuk gebruiksvriendelijker.

Stap 3: De methoden van de Java class publiceren naar SQL

Wanneer een Java class in de database is geladen, worden haar methoden niet automatisch gepubliceerd omdat Oracle niet weet welke methoden veilige instappunten zijn vanuit SQL. Om een methode te publiceren moet daarvoor een call specification worden geschreven. De call specification bied de toewijzing (mapping) van Java methode, parameters en return values op de tegenhangers daarvan in SQL:

CREATE OR REPLACE FUNCTION rowcount(p_tabelnaam IN VARCHAR2)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'counters.RowCounter.rowCount(java.lang.String) return int';

Java methoden die waarden teruggeven worden gepubliceerd als functies, methoden die void teruggeven worden gepubliceerd als procedures. De Oracle datatypes verschillen van de Java datatypes, een eenvoudige mapping zoals een Oracle VARCHAR2 op een Java String is redelijk voor de hand liggend. Voor ingewikkelder mappings kan ook gebruik gemaakt worden van de Java classes in de oracle.sql package zoals oracle.sql.CLOB.

Call specifications kunnen gemaakt worden als losse PL/SQL functions en procedures, Packaged PL/SQL functions/procedures en als member methoden van SQL object types. Alleen public static methoden kunnen worden gepubliceerd. Met één uitzondering: instance methoden kunnen als member methoden van een SQL object type worden gepubliceerd.

Stap 4: De Java stored procedure aanroepen vanuit de gewenste context.

Java Stored Procedures kunnen via hun call specification aangeroepen worden vanuit SQL statements en PL/SQL programma’s. Bijvoorbeeld:

SQL> VARIABLE my_count NUMBER;

SQL> CALL rowcount('EMP') into :my_count ;

SQL> PRINT my_count;

  MY_COUNT
----------
        14

Met JDeveloper kunnen de stappen 1 t/m 3 van ontwikkelen van de Java stored procedure eenvoudig uitgevoerd worden, JDeveloper kan een deployment profile maken voor loadjava en automatisch call specifications genereren.

SQLJ

Met SQLJ kan het schrijven van de Java Stored Procedures aanzienlijk worden vergemakkelijkt. SQLJ is een eenvoudige manier om SQL statements in Java programma’s af te handelen (vergelijkbaar met Pro*C). Via een pre-compiler (SQLJ translator) wordt de Java code verder aangevuld met de volledige Java syntax. Bijvoorbeeld:

mport java.sql.*;

public class Emp {
   public static String getName (int empNo) throws SQLException {
     String eName ;
     try {
       #sql {SELECT ename INTO :eName FROM EMP WHERE empno = :empNo};
     } catch (Exception e) {eName = "Onbekend";}
     return eName;
   }
}

Voor en nadelen van Java Stored Procedures

Java Stored Procedures hebben een aantal voordelen in vergelijking met PL/SQL:

  • De Java code is (met wat kleine aanpassingen) migreerbaar naar database platforms van andere leveranciers.
  • Indien nodig kan de Java code verplaatst worden naar andere plekken in de IT-architectuur, bijvoorbeeld van database naar Application Server of andersom.
  • Java is een volledige programmeertaal, er kunnen uiteindelijk meer soorten functionaliteit mee gemaakt worden dan met PL/SQL. Op die manier breid je de functionaliteit van de database uit.

Nadelen ten opzichte van PL/SQL:

  • Vanuit het perspectief van een database ontwikkelaar is coderen in Java lastiger dan het gebruik van PL/SQL. Dit betekent dat bij bedrijven waar de kennis op het gebied van Java ontbreekt de stap naar Java best groot is.
  • Het debuggen van de Java Stored Procedures was zeker in Oracle 8i nogal omslachtig. Debuggen van code in een losse JVM kan eenvoudig in je lokale Java IDE. Zodra het programma in de database draait wordt het lastiger. Vanaf release 9.2 kan het Java Debug Wire Protocol gebruikt worden om de procedure ‘remote’ te debuggen.

 Nadelen algemeen:

  • De database Oracle JVM is niet pluggable, per database release ben je gebonden aan een specifieke Java versie. Voor bijvoorbeeld Oracle 10g Release 2 is dat JDK 1.4.2. De komende database versie 11g zal een upgrade naar J2EE 5.0 bevatten. De mogelijkheid om binnen de database versie te upgraden volgt in de toekomst.
  • Java code die veel berekeningen uitvoert en weinig data ophaalt zal in een JVM buiten de database sneller draaien dan er in.
  • Niet echt een nadeel maar wel lastig: Oracle’s gratis database XE bevat geen Java ondersteuning. Om te experimenteren met Java Stored Procedures is minimaal Oracle Standard Edition One nodig.

Wat betreft performance in de database zullen PL/SQL en Java elkaar niet veel hoeven te ontlopen. PL/SQL code kan tegenwoordig voor het OS-platform waarop de database draait gecompileerd worden (native compilation), hetzelfde geldt voor Java.

Toepassen van Java Stored Procedures

Met Java Stored Procedures kan dezelfde functionaliteit worden ontwikkeld als met PL/SQL. Java biedt zelfs meer: een volledige programmeertaal waarmee functionaliteit kan worden ontwikkeld die met PL/SQL niet of moeilijk te maken is. Een Oracle database ontwikkelaar die minder vertrouwd is met Java zal waarschijnlijk proberen een probleem eerst in SQL of PL/SQL op te lossen. Daartoe al dan niet geïnspireerd door een bekend mantra van Oracle goeroe Tom Kyte:

  • You should do it in a single SQL statement if at all possible.
  • If you cannot do it in a single SQL statement, do it in PL/SQL.
  • If you cannot do it in PL/SQL, try a Java stored procedure.
  • If you cannot do it in Java, do it in a C external procedure.
  • If you cannot do it in a C external procedure, you might want to seriously think about why it is you need to do it.

Een voorbeeld van het gebruik van Java stored procedure is het verkrijgen van data vanuit een externe Webservice. Je schrijft eerst de Java code om de Webservice aan te roepen en de resultaten op te halen. Dit is dan een ‘gewoon’ Java programma dat ook zonder de Oracle database draait. Deze Java Webservice client laad je vervolgens in de database en publiceer je middels een call specification. Op die manier kan vanuit SQL of PL/SQL verder gewerkt worden met de data uit de Webservice.

Een ander voorbeeld zijn callouts vanuit de database naar andere systemen. Op deze manier kan de database ingezet worden als relatief goedkoop middel voor applicatie-integratie. Zo kun je een trigger op een tabel schrijven die een Java stored procedure afvuurt die via RMI (Remote Method Invocation) een callout naar een ander systeem doet om aan te geven dat er data is bijgewerkt in jouw bronsysteem. Of je kan door het laden van de ‘IBM Toolbox for Java’ JAR file (jt400.jar), data benaderen in een AS400 database (DB2/400) of DB2 database.

Conclusie

Het ontwikkelen van Java Stored Procedures gaat volgens een redelijk eenvoudig stappenplan. De moeilijkheid zit vooral in het schrijven van de Java code zelf. Komen we terug op de vraag uit de inleiding of het terecht is dat de Java Stored Procedures zo weinig populariteit genieten. Op basis van de geboden functionaliteit zijn er geen doorslaggevende redenen om te kiezen voor PL/SQL dan wel Java. Echter, in de praktijk is een grote groep Oracle Database ontwikkelaars gewend aan PL/SQL. Indien hetzelfde probleem met beide talen kan worden opgelost valt de keuze snel op een vertrouwde taal. Als je niets anders gewend ben ziet de Java code er toch complexer in vergelijking met PL/SQL, hoewel met SQLJ het coderen alweer makkelijker gaat.

Het is mogelijk dat een bedrijf als regel stelt dat alle stored procedures in Java moeten worden ontwikkeld. Daarvoor kunnen zeker geldige redenen zijn: de mogelijkheden tot migratie naar andere database platformen of het simpelweg benutten van de aanwezige Java kennis. Maar indien er geen expliciet beleid is ten faveure van Java Stored Procedures zal een Oracle database ontwikkelaar geneigd zijn de Java Stored Procedures pas toe te passen als PL/SQL niet meer toereikend is. Met deze redelijk voor de hand liggende werkwijze laat een PL/SQL ontwikkelaar echter wel een mooie mogelijkheid schieten om binnen een bekende omgeving te gaan experimenteren met Java en hier de eerste stappen in te zetten. Dit laatste is nu juist interessant omdat Oracle steeds meer met Java gaat doen. PL/SQL zal zeker niet verdwijnen, maar Java Stored Procedures kunnen een zinvolle toevoeging zijn, zeker nu integratie en webservices een steeds belangrijkere rol krijgen.

Referenties


Waardering:
 
Tags:

Reacties

Nieuwe reactie inzenden

De inhoud van dit veld is privé en zal niet openbaar worden gemaakt.

Meer informatie over formaatmogelijkheden

CAPTCHA
Deze vraag is om te testen of u een persoon bent en om spam te voorkomen
Image CAPTCHA
Enter the characters shown in the image.