Subclassed Objects
The object orientated programming in stored procedures is a little bit restricted. This example shows how to work with derived object type and how they are represented as Java transfer object classes.Example Description
- A base object is declared as PL/SQL object type named BASE_OBJECT with a member function val(). This PL/SQL object type is stored in the Java transfer object class BaseObject
- An derived object is declared as PL/SQL object type named DERIVED_OBJECT overwriting the member function val(). This PL/SQL object type is stored in the Java transfer object class DerivedObject
- The PL/SQL package has three functions :
- Get a Java transfer object BaseObject of PL/SQL object type BASE_OBJECT.
- Get a Java transfer object DerivedObject of PL/SQL object type DERIVED_OBJECT.
- A function returning the type and the values of the PL/SQL object type for identification/inspection.
- The Java calling class receives the transfer object when calling the stored procedure.
- The transfer object is sent to the stored procedure and returns a string of the type and the values.
User Defined Object Specification of Parent Object
Object Type Specification : BASE_OBJECT
/**
* Parent object containing one member function for inspect information.
*/
create or replace type base_object force as object (
d date,
ts timestamp,
instance varchar2(100),
db_version number(9),
db_release number(9),
member function val return varchar2
) not final;
User Defined Object Body of Parent Object
Object Type Body : BASE_OBJECT
create or replace type body base_object
as
member function val return varchar2
is
begin
return 'd:'||to_char(d, 'yyyy/mm/dd')||'/ts:'||to_char(ts, 'yyyy/mm/dd hh:mi:ss')||'/instance:'||instance||'/db_version:'||db_version||'/db_release:'||db_release;
end val;
end;
Generated Transfer Object Type from User Defined Object 'BASE_OBJECT'
Java Transfer Object : BaseObject.java
/*
* This file is generated by PL/SQL Enterprise Workbench Connector Builder.
* PL/SQL Enterprise Workbench Copyright (c) Jan Richter, www.jr-database-tools.com, Switzerland, 2015-2024. All rights reserved.
*
* THIS FILE IS NOT INTENDED TO BE MODIFIED - IT WILL BE OVERWRITTEN ON EVERY RUN OF THE CONNECTOR BUILDER
*/
package transferobject;
import java.io.Serializable;
import java.sql.Date;
import java.sql.Timestamp;
/**
* Transfer object of user defined type <em>BASE_OBJECT</em>.
*/
public class BaseObject implements Serializable {
private static final long serialVersionUID = 1L;
public Date d;
public Timestamp ts;
public String instance;
public int dbVersion;
public int dbRelease;
}
User Defined Object Specification of Subclassed Object
Object Type Specification : DERIVED_OBJECT
/**
* Derived object containing overriding member function for inspect information.
*/
create or replace type derived_object force under base_object (
new_s varchar2(100),
new_ts timestamp,
new_d date,
new_n number(9),
overriding member function val return varchar2
);
User Defined Object Body of Subclassed Object
Object Type Body : DERIVED_OBJECT
create or replace type body derived_object
as
overriding member function val return varchar2
is
begin
return (self as base_object).val || '/new_s:'||new_s||'/new_ts:'||to_char(new_ts, 'yyyy/mm/dd hh:mi:ss')||'/new_d:'||to_char(new_d, 'yyyy/mm/dd')||'/new_n:'||new_n;
end val;
end;
Generated Transfer Object Type from User Defined Object 'DERIVED_OBJECT'
Java Transfer Object : DerivedObject.java
/*
* This file is generated by PL/SQL Enterprise Workbench Connector Builder.
* PL/SQL Enterprise Workbench Copyright (c) Jan Richter, www.jr-database-tools.com, Switzerland, 2015-2024. All rights reserved.
*
* THIS FILE IS NOT INTENDED TO BE MODIFIED - IT WILL BE OVERWRITTEN ON EVERY RUN OF THE CONNECTOR BUILDER
*/
package transferobject;
import java.sql.Date;
import java.sql.Timestamp;
/**
* Transfer object of user defined type <em>DERIVED_OBJECT</em>.
*/
final public class DerivedObject extends BaseObject {
private static final long serialVersionUID = 1L;
public String newS;
public Timestamp newTs;
public Date newD;
public int newN;
}
PL/SQL Package Specification
PL/SQL Package Specification : SUBCLASSED_OBJECTS
create or replace package subclassed_objects
/**
* Demonstration of calling a stored procedure with in/put parameter of collections of scalar element types.
*
* @param i_col_number Table-Collection of integer input values.
* @param io_col_timestamp Table-Collection of timestamp value.
* @param o_col_varchar Varray(5)-Collection of varchar2 out put values.
*/
as
/**
* Generating an object of type base_object.
*
* @return Object of type base_object.
*/
function get_base_object return base_object;
/**
* Generating an object of type derived_object.
*
* @param i_diff Offset of field values of type derived_object.
* @return Object of type derived_object.
*/
function get_derived_object(i_diff in number) return base_object;
/**
* Calling member function 'val' of base_object or derived_object.
*
* @param base_object Object value to inspect.
* @return Result of member function 'val'.
*/
function inspect_object(i_object in base_object) return varchar2;
end subclassed_objects;
PL/SQL Package Body
PL/SQL Package Body : SUBCLASSED_OBJECTS
create or replace package body subclassed_objects
as
function get_base_object return base_object
is
o base_object;
begin
o := base_object(null, null, null, null, null);
o.d := sysdate;
o.ts := systimestamp;
select sys_context('USERENV','INSTANCE_NAME')
into o.instance
from dual;
o.db_version := DBMS_DB_VERSION.VERSION;
o.db_release := DBMS_DB_VERSION.RELEASE;
return o;
end get_base_object;
function get_derived_object(i_diff in number) return base_object
is
o base_object;
begin
select derived_object(sysdate,
systimestamp,
sys_context('USERENV','INSTANCE_NAME'),
DBMS_DB_VERSION.VERSION,
DBMS_DB_VERSION.RELEASE,
dbms_random.string('A', 100),
systimestamp+i_diff,
sysdate-i_diff,
DBMS_RANDOM.value(0,999999999))
into o
from dual;
return o;
end get_derived_object;
function inspect_object(i_object in base_object) return varchar2
is
result varchar2(1000);
begin
if (i_object is of(only base_object)) then
result := 'base_object ['|| i_object.val ||']';
elsif (i_object is of(only derived_object)) then
result := 'derived_object ['|| i_object.val ||']';
else
result := 'null or unknown object';
end if;
return result;
end inspect_object;
end subclassed_objects;
Factory API : Calling the PL/SQL package
Using the static factory to get the remote service.Java Calling Class : SubclassedObjectsFactoryApi.java
package plsql_workbench_examples.factoryapi;
import java.sql.Date;
import java.sql.Timestamp;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import factory.ExamplesRPCFactory;
import service.SubclassedObjectsService;
import transferobject.BaseObject;
import transferobject.DerivedObject;
public class SubclassedObjectsFactoryApi {
public static void main(String[] args)
{
System.setProperty("baseURL", "http://localhost:8080");
// Initialize factory class once - after that all services are accessible calling throw the static factory api.
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ExamplesRPCFactory.class)) {
runDemo();
}
catch (Exception e) {
e.printStackTrace();
}
}
private static void runDemo() throws Exception
{
int diff = 10;
SubclassedObjectsService service = ExamplesRPCFactory.getSubclassedObjectsService();
// create a base object from the database function
BaseObject baseObject = service.getBaseObject();
System.out.format("java-inspect: %s [d:%s/ts:%s/instance:%s/version:%d.%d]%n",
baseObject.getClass(),
baseObject.d,
baseObject.ts,
baseObject.instance,
baseObject.dbVersion,
baseObject.dbRelease);
System.out.println("pl/sql inspect : " + service.inspectObject(baseObject));
// create an derived object from the database function
baseObject = service.getDerivedObject(diff);
DerivedObject derivedObject = (DerivedObject) baseObject;
System.out.format("java-inspect : %s [d:%s/ts:%s/instance:%s/version:%d.%d/newS:%s/newTs:%s/newD:%s/newN:%d]%n",
baseObject.getClass(),
baseObject.d,
baseObject.ts,
baseObject.instance,
baseObject.dbVersion,
baseObject.dbRelease,
derivedObject.newS,
derivedObject.newTs,
derivedObject.newD,
derivedObject.newN);
System.out.println("pl/sql inspect : " + service.inspectObject(baseObject));
// inspect of object instantiated in java
derivedObject = new DerivedObject();
derivedObject.d = new Date(System.currentTimeMillis());
derivedObject.instance = "any string";
derivedObject.ts = new Timestamp(System.currentTimeMillis());
derivedObject.dbVersion = 88;
derivedObject.dbRelease = 99;
derivedObject.newD = new Date(0);
derivedObject.newN = 1234567890;
derivedObject.newS = "another string";
derivedObject.newTs = new Timestamp((long) (Math.random() * 1000L * 3600L * 24L * 365L * 50L));
System.out.println("pl/sql inspect () : " + service.inspectObject(derivedObject));
}
}
Spring API : Calling the PL/SQL package
Using Spring annotation to inject the service and call the remote service.Java Calling Class : SubclassedObjectsSpringApi.java
package plsql_workbench_examples.springapi;
import java.sql.Date;
import java.sql.Timestamp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
import service.SubclassedObjectsService;
import transferobject.BaseObject;
import transferobject.DerivedObject;
@Component
public class SubclassedObjectsSpringApi {
@Autowired
private SubclassedObjectsService subclassedObjectsService;
public static void main(String[] args)
{
System.setProperty("baseURL", "http://localhost:8080");
// Register Spring Beans, Spring Context and call demo method
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("factory")) {
ctx.register(SubclassedObjectsSpringApi.class);
SubclassedObjectsSpringApi demo = ctx.getBean(SubclassedObjectsSpringApi.class);
demo.runDemo();
}
catch (Exception e) {
e.printStackTrace();
}
}
private void runDemo()
{
try {
int diff = 10;
// create a base object from the database function
BaseObject baseObject = subclassedObjectsService.getBaseObject();
System.out.format("java-inspect: %s [d:%s/ts:%s/instance:%s/version:%d.%d]%n",
baseObject.getClass(),
baseObject.d,
baseObject.ts,
baseObject.instance,
baseObject.dbVersion,
baseObject.dbRelease);
System.out.println("pl/sql inspect : " + subclassedObjectsService.inspectObject(baseObject));
// create an derived object from the database function
baseObject = subclassedObjectsService.getDerivedObject(diff);
DerivedObject derivedObject = (DerivedObject) baseObject;
System.out.format("java-inspect : %s [d:%s/ts:%s/instance:%s/version:%d.%d/newS:%s/newTs:%s/newD:%s/newN:%d]%n",
baseObject.getClass(),
baseObject.d,
baseObject.ts,
baseObject.instance,
baseObject.dbVersion,
baseObject.dbRelease,
derivedObject.newS,
derivedObject.newTs,
derivedObject.newD,
derivedObject.newN);
System.out.println("pl/sql inspect : " + subclassedObjectsService.inspectObject(baseObject));
// inspect of object instantiated in java
derivedObject = new DerivedObject();
derivedObject.d = new Date(System.currentTimeMillis());
derivedObject.instance = "any string";
derivedObject.ts = new Timestamp(System.currentTimeMillis());
derivedObject.dbVersion = 88;
derivedObject.dbRelease = 99;
derivedObject.newD = new Date(0);
derivedObject.newN = 1234567890;
derivedObject.newS = "another string";
derivedObject.newTs = new Timestamp((long) (Math.random() * 1000L * 3600L * 24L * 365L * 50L));
System.out.println("pl/sql inspect () : " + subclassedObjectsService.inspectObject(derivedObject));
}
catch (Exception e) {
e.printStackTrace();
}
}
}