Java Stored Procedures in Oracle

October 3, 2018

in Datatypes, PL/SQL

Java Stored Procedures in Oracle

Some solution requirements are best addressed with Java code in the Oracle database. This article shows you use cases where Java methods in Oracle are useful, how Oracle lets you store Java methods and how they can be called from SQL or PL/SQL.

Java stored procedures in Oracle: Why do you need them?

A common reason why you would want Java stored procedures in Oracle is that the equivalent PL/SQL is not feasible, performant or economical to build. A few use cases:

  • Application-specific code that’s already in use in Java and needs to be migrated to the database: it might make more sense to make use of the working Java code than to recreate it from scratch in PLSQL.
  • Out-of-the-box Java functions: Java packages might have pre-built functions for the problem at hand, and the cost of building their PL/SQL equivalent is prohibitively high. This could range from simple stuff such as primality testing with BigInteger or advanced cryptographic operations with javax.crypto.

How to store and invoke Java methods in Oracle

The steps are outlined below. A working example follows in the next section.

1. Create the Java source

Write the code (java_source_code) as you normally would in Java. Give the Java source code a name (java_source_name) and create it in the database, with the syntax:

create or replace and resolve java source named
"<java_source_name>" as 
<java_source_code>;

2. Publish the Java method through a call specification

To publish the Java method, create a “call specification” that maps the Java method name, parameter types and return types to their SQL counterparts. The syntax:

create or replace function <plsql_function_name>
  (<plsql_parameters>)
  return <plsql_return_type>
as language java
name ‘<java_source_name>.<method>
  (<java_parameters>)
  return <java_return_type>’;

There should be a 1:1 correspondence between the java parameters/return types and the SQL counterparts. For more on mappings and data conversion considerations, see the Oracle documentation for mappings between SQL Types and Java Types (12c).

A call specification is not a wrapper. A wrapper adds another layer of execution, whereas a call specification only publishes the existence of a Java method. So when you call the Java method via its call specification, this happens at runtime with minimal overhead.

3. Invoke the Java method via the call specification

The stored Java method can now be called using <plsql_function_name> like any regular PL/SQL function. The Java stored procedure can accept arguments, reference Java classes, and return Java result values.

Java in Oracle: Demo

The method used for this demo is BigInteger‘s nextProbablePrime, a pre-built solution that returns the first probable prime integer greater than the current value.

Before moving on to the demo, a little introduction to BigInteger: this is a custom Java class for handling very large numbers, with pre-built methods for mathematical operations. Read more about it in the Java 8 documentation. Note that the class BigInteger does not have a direct datatype mapping in PL/SQL, and so we need to convert the method’s input/output to a Java primitive type, which can be then mapped to the PL/SQL datatype NUMBER.

Let’s see in action, the steps to store and invoke a Java method in Oracle.

1. Create the Java source

Java source MathFunction with method nextProbablePrime — this is a wrapper for BigInteger.nextProbablePrime, with a switch of datatype: int from/to BigInteger.

-- Java source with method which returns the first 
-- integer greater than the input that's probably prime. 
create or replace and resolve java source named 
"MathFunction" as
import java.math.*;

/**
 *  Java class to calculate math functions
 */
public class MathFunction {

      /**
       * Wrapper for BigInteger's nextProbablePrime
       * function. Input as well as return type are
       * are mapped from int to/from BigInteger.
       * 
       * @param int n
       * @return int next probable prime > n
       */
       public static int nextProbablePrime(int n) {

            return BigInteger.valueOf(n)
                    .nextProbablePrime().intValue();
       }
    };
/

When run:

SQL> -- Java source with method which returns the first
SQL> -- integer greater than the input that's probably prime.
SQL> create or replace and resolve java source named
  2  "MathFunction" as
  3  import java.math.*;
  4
  5  /**
  6   *  Java class to calculate math functions
  7   */
  8  public class MathFunction {
  9
 10        /**
 11         * Wrapper for BigInteger's nextProbablePrime
 12         * function. Input as well as return type are
 13     * are mapped from int to/from BigInteger.
 14         *
 15         * @param int n
 16         * @return next probable prime > n
 17         */
 18         public static int nextProbablePrime(int n) {
 19
 20              return BigInteger.valueOf(n)
 21                      .nextProbablePrime().intValue();
 22         }
 23      };
 24  /

Java created.

SQL>

2. Publish the Java method through a call specification

The call specification for the source created in step 1 -  MathFunction.nextProbablePrime(int) with return type int.

-- Call specification for the Java source 
-- MathFunction.nextProbablePrime
create or replace function nextProbablePrime 
  (n number)
  return number
as language java
name 'MathFunction.nextProbablePrime(int) 
  return int';

When run:

SQL> -- Call specification for the Java source
SQL> -- MathFunction.nextProbablePrime
SQL> create or replace function nextProbablePrime
  2    (n number)
  3    return number
  4  as language java
  5  name 'MathFunction.nextProbablePrime(int)
  6    return int';
  7  /

Function created.

SQL>

3. Invoke the Java method via the call specification

The Java stored method is now ready for use via its call specification.

Examples:

SQL> select nextProbablePrime(36) from dual;

NEXTPROBABLEPRIME(36)
---------------------
                   37

SQL> select nextProbablePrime(2147) from dual;

NEXTPROBABLEPRIME(2147)
-----------------------
                   2153

Summary

Java methods can be stored in Oracle and invoked via a call specification. This article shows you how this can be done, with an example using the Java method BigInteger.nextProbablePrime  in the Oracle database.

Leave a Comment

Previous post:

Next post: