SlideShare a Scribd company logo
OBJECTVIEW INC.
Persistency Layer
ObjectView
Persistency Layer
Mapping Tool Users’ Guide
Programmers’ Guide
© ObjectView Inc.
www.objectview.ca
Phone 416-436-3288 • Fax 905-881-7515
Table of Contents
MAPPING TOOL USERS’ GUIDE.................................................................................................................4
Introduction........................................................................................................................................................4
Feature Summary...............................................................................................................................................4
MAPPING CONSIDERATIONS......................................................................................................................7
Class Mapping....................................................................................................................................................7
Inheritance Mapping..........................................................................................................................................8
VERTICAL INHERITANCE MAPPING.............................................................................................................................................8
HORIZONTAL INHERITANCE MAPPING.........................................................................................................................................9
DISCRIMINATOR FILTERED INHERITANCE MAPPING.................................................................................................................9
One class to multiple tables mapping..............................................................................................................10
Relationships Mapping....................................................................................................................................10
TYPE - SUBTYPE RELATIONSHIPS..............................................................................................................................................10
PARENT OF A RELATIONSHIP AND OBJECT GRAPHS...................................................................................................................10
Attribute Mapping...........................................................................................................................................11
JDBC TYPE CONVERSIONS ......................................................................................................................................................11
SPECIAL FIELDS.......................................................................................................................................................................11
OBJECTVIEW WORKBENCH, CONFIGURATION AND USER INTERFACE....................................12
ObjectView Settings.........................................................................................................................................12
PROPERTIES FILE. LOCATION AND LOADING ASPECTS...............................................................................................................13
PROPERTIES SYNTAX.................................................................................................................................................................13
Workbench loading..........................................................................................................................................20
Workbench Settings Panel...............................................................................................................................21
UI WIDGETS AND CONTROLS:...................................................................................................................................................22
Inheritance Tree Panel.....................................................................................................................................26
Class Mapping Panel........................................................................................................................................27
Attribute Mapping Panel.................................................................................................................................31
Association Mapping Panel.............................................................................................................................35
ONE-TO-MANY ASSOCIATION MAPPING...................................................................................................................................36
MANY-TO-MANY ASSOCIATION MAPPING.................................................................................................................................39
DB Schema Explorer Panel.............................................................................................................................39
Model Validation Panel....................................................................................................................................40
Model Generation Panel..................................................................................................................................41
Object Explorer Panel......................................................................................................................................42
OBJECTVIEW PERSISTENCY LAYER PROGRAMMERS’ GUIDE..........................................44
Introduction......................................................................................................................................................44
The Sample Model............................................................................................................................................44
Workbench settings..........................................................................................................................................47
PERSISTENT CLASSES................................................................................................................................48
DATABASE CONNECTION..........................................................................................................................50
Let ObjectView obtain a java.sql.Connection................................................................................................51
Passing a java.sql.Connection to ObjectViewPL...........................................................................................52
EXTERNAL TRANSACTION MONITOR INTEGRATION....................................................................................................................52
RETRIEVING AND PERSISTING OBJECTS.............................................................................................54
Retrieving objects.............................................................................................................................................54
RETRIEVING INDIVIDUAL OBJECTS............................................................................................................................................54
RETRIEVING OBJECT COLLECTIONS...........................................................................................................................................54
Saving Objects..................................................................................................................................................55
INSERT ....................................................................................................................................................................................55
UPDATE ..................................................................................................................................................................................56
DELETE ...................................................................................................................................................................................57
Saving Object Graphs......................................................................................................................................58
SAVEALL WITH CHECK..............................................................................................................................................................60
Setting and Retrieving Relationships..............................................................................................................62
MANY TO MANY RELATIONSHIPS................................................................................................................................................64
TYPES AND SUBTYPES. CAST DOWN POLICIES...........................................................................................................................66
RETRIEVING RELATIONSHIPS USING CUSTOMIZED JOIN REQUESTS.............................................................................................66
OBJECT ROLLBACK AND REFRESH. DIRTY AND PERSISTENT STATUSES.................................68
Dirty status........................................................................................................................................................69
Persistency Status.............................................................................................................................................69
Persistent Object Cloning................................................................................................................................69
Transaction Management................................................................................................................................69
Object vs. Database State synchronization.....................................................................................................70
DATABASE TRIGGERS................................................................................................................................................................70
OBJECT PERSISTENT STATE ROLLBACK......................................................................................................................................70
MAPPING FUNCTIONS, STORED PROCEDURES, VIEWS AND AD-HOC SQL................................71
Retrieving objects from stored procedures or functions returning open cursors........................................71
Retrieving objects from stored procedures returning result sets..................................................................74
Retrieving objects from ad-hoc SQL statements............................................................................................75
Retrieving objects from database Views.........................................................................................................75
Retrieving objects from a given java.sql.ResultSet........................................................................................75
LIGHTWEIGHT OBJECTS. PRIMARY KEY OBJECTS.........................................................................75
XML ALTERNATIVE STORE......................................................................................................................77
XML Logging...................................................................................................................................................77
ITERATORS. RETRIEVE FIRST AND NEXT OBJECT...........................................................................78
LOCKING POLICIES.....................................................................................................................................79
Optimistic Locking...........................................................................................................................................79
Pessimistic Locking..........................................................................................................................................81
CACHEING POLICIES..................................................................................................................................81
HOOK METHODS..........................................................................................................................................81
F E A T U R E S U M M A R Y
Mapping Tool Users’ Guide
Introduction
bjectview persistency layer (OVPL) is a 100% java framework for object to
relational mapping. Persistence is attained based on mapping rules specified
by developer at design time. The framework consists of a GUI mapping
tool (called Workbench) and a runtime library. The Workbench is used in design-time
to specify mapping rules while the library supports the runtime functionality.
Workbench also provides a generic user interface for browsing and modifying object
instances for the mapped classes, as well database versus mapping model comparisons
and validations. The product has been first used in 1998 and since then it was
continuously improved and enriched in new features.
O
Feature Summary
Here is a summary of the features OVPL has to offer:
 Full inheritance support. OVPL supports all 3 types of inheritance mappings,
vertical, horizontal and discriminator filtered.
 All types of relationships mappings. One to one, one to many and many to
many relationships, between any two classes, including recursive definitions, and
customized relationships.
 Multithreading safe environment. If used in the middle tier, OVPL can handle
concurrent clients, and fits perfectly in a scalable architecture. Provides client scope
cache access as well per client debugging and logging facilities.
 4 types of cache management. Client session cache, global cache for
immutable objects, SQL-view cache to associate a query with the produced result
and a week references cache that allows garbage collection. Cache is
synchronized with object lifecycle. Relationships can be defined as lazy-initialized
or joins, cached or always refreshed.
Chapter
1
F E A T U R E S U M M A R Y
 Database session pool management. User can opt between an internal session
pool management or for interfacing with external database pools. The internal
implementation deals with time-outs, validation methods, debugging information
and logging.
 Database session management. User can opt for internally managed data-source
connection (when db connections, connection pooling and transactions are
managed internally), external managed database connections (integrated with
external pools using Data-Source interfaces) or for user managed connection
lifecycle. Simultaneous use of multiple data-sources is allowed in user-managed
data-source connection mode.
 Database Transaction support. Transactions can be internally managed,
controlled by user, or externally managed and integrated with a Transaction
Monitor. In user mode, OVPL supports nested transactions. For integration with
other middleware environments (EJB containers), transaction management is
handled by the external TM, who also owns that particular session.
 Object graphs. Persistence by reachability. User can transparently save all
changes made since last access starting from an object root and following all
instantiated relationships in one transactional step, without worrying about the
database operations order. Only modified objects will translate to database calls,
thus minimizing the database I/O. Based on configuration, if an object is deleted
then all its references are removed from an object graph.
 Cascade deletes support. OVPL keeps objects in synch with database if cascade
delete was configured at the database level (triggers or delete constraints).
 Transparent object id management. User does not have to worry at all for id
fields. Primary keys, auto-incrementors, discriminators and foreign keys are
created, assigned and migrated internally.
 Concurrent update control. Optimistic and Pessimistic approach. OVPL
implements the optimistic approach for data concurrent access (using update
counters or timestamp fields) as well the exclusive lock mechanism provided by
RDBMS.
 Support for object rollback. OVPL provides support for object level rollbacks.
Object state before any db access is saved and can be restored.
 No SQL necessary. User does not have to use any SQL commands to attain
persistency. SQL is internally generating as response to method invocations.
5
F E A T U R E S U M M A R Y
 Stored Procedure and Open cursor support. ObjectView PL transparently
(builds objects following the same rules) supports ad-hoc SQL, stored procedures
and open cursors.
 Hooks methods. Pre and post methods to be used at all stages of an object
lifecycle. User can specify business methods to be executed before and after each
access operation.
 Database reverse engineer. It assists in producing mapping schemas based
on database schema. It also compares database schema with the mapping
definition to detect mismatches.
 Built in XML alternate storage. Any object graph (reachable objects) can be
saved to XML format, and can be created back or updated from XML documents,
as an alternative data store or for data exchange and configuration purposes. XML
conversion is also used for debugging: if any database error is reported, current
object state is dumped to the XML format and saved to a predefined file.
 Lightweight objects. Lightweight objects are defined for each domain objects
consisting only from the primary and foreign keys. Lightweight objects have the
same relationships as the domain objects and can be realized to domain objects at
user request.
 Debugging features. OVPL provides logging and debugging features, allowing
object activity tracing and SQL activity reports. If a persistency operation fails,
OVPL logs the object state, SQL executed, thread information and error trace to a
file. If debugging is on, OVPL logs all SQL activity.
 Code Generation and merging. OVPL will merge any user added java code with
the code it generates. It will merge comments added by UML mapping tools
(TogetherJ, Rational XDE).
 Mapping GUI interface, object relationship browsers and editors. The GUI
mapping interface provides automatic object relationship browsing and edit
facilities for all mapped classes.
These features and many others will be covered in detail in the “Programmers
Guide Manual”.
6
F E A T U R E S U M M A R Y
Mapping considerations
y mapping we refer here the activity and the strategies by which are
established the rules behind object to relational communication to attain the
persistency status while preserving object concepts.BIndeed, just using a communication protocol and streaming out requests will make just
part of this task possible, where by mapping, these two worlds managed by different
rules - object and relational - can be linked together to acquire the privileges provided
by each one of them. If in the object world we talk about classes, objects, attributes,
state, behavior, identity, relationships, on the database side, we have notions like tables,
rows, fields, primary and foreign keys. Our goal is to manipulate objects while
respecting OO idioms and attain persistency with less of the effort. Mapping is part of
this exercise; ObjectView PL (OVPL) framework combined with programming
techniques will take care of the rest.
Another advantage of mapping is that it creates a separation between class and
database design, minimizing the impact of changes done in any of the parts. Therefore,
looking from different angles, mapping provides both a unifying and a separation layer.
In the following subtitles, we will be describing mapping techniques from object
language perspective.
Class Mapping
A class can be mapped to one or more tables. If more tables involved, then there must
be some join constraint implicitly or explicitly described to link both tables in a one to
one cardinality. In this way the object persistent state became stored in one row on
each of the involved tables.
ObjectView PL handles two situations where one class is mapped to multiple tables:
when mapping inheritance, or when helper tables are defined. In both cases a one to
Chapter
2

7
F E A T U R E S U M M A R Y
one cardinality join is performed between involved tables based on keys specified at
mapping time.
In any of the class mapping types- one class to one table (view), one class to a subset of
a table (or view) or one class to more than one table-ObjectView PL will manage
consistency between instances and database content, and will transparently update and
migrate foreign key values.
Inheritance Mapping
Mapping inheritance follows the rules described above for class mapping. There are
three accepted ways of mapping class inheritance to tables. They are vertical, horizontal
and discriminator filtered.
Vertical Inheritance Mapping
In vertical inheritance mapping the super-class and each subclass are mapped to a
separate table. Lets consider the following UML diagram:
Business Entity subclasses for vertical mapping model
In this case, the database tables will look like:
Table design for inheritance vertical mapping
8
F E A T U R E S U M M A R Y
ObjectView PL will manage the table join and the foreign keys in all object database
access operations. A widely used variant is to define a discriminator field in the super-
type, to store different values for each subtype. In this way it is possible to tell the
subtype only by inspecting the value of this field, rather than trying to find the
corresponding subtype table to be used in the join statement.
The mandatory conditions for mapping this structure using OVPL are:
 Number of primary keys is the same in each type/subtype table, and
 The subtype primary key s are foreign keys in the super-type table.
In this way the join is based on the primary keys of each table.
Horizontal Inheritance Mapping
In this case, each subclass is mapped to its own table, and there is no table for the
superclass, which is becoming an abstract class.
Tables will look like:
Table design in horizontal mapping
Discriminator Filtered Inheritance Mapping
All classes are mapped to the same table, which contains the fields for the common set
of class attributes. The discriminator field will be used to filter the rows that
correspond to a particular subclass. ObjectView PL is internally managing the filter
field.
Table design for filtered mapping
9
F E A T U R E S U M M A R Y
One class to multiple tables mapping
To be able to map one class to multiple tables, ObjectViewPL requires that the
involved tables can participate in a join based on primary keys. In this case the join
must produce a result set having one row. ObjectViewPL term for a joined table in a
multiple tables class mapping is Helper Map.
Relationships Mapping
ObjectView PL permits mapping of three associations types:
 One to one,
 One to many,
 Many to many.
Type - Subtype relationships
Given two objects in a one to many relationship, saying A -> (m)B, and given that
class B has defined C and D as subclasses, then by calling A.getBSubtypes() a
heterogeneous collection of Cs and/or Ds will be obtained. In this way ObjectView is
instantiating the right subtypes when asked to do so, by managing the inheritance-
subtype conversion.
Parent of a relationship and Object graphs
ObjectView defines as the relationship parent the part responsible with providing of
the foreign key values. In this context, the parent is known as the class exporting the
foreign keys while the child is the class that will import them. Two classes can have
more than one relationship defined between them, each one with its own parent role
played by the same or the other class.
An object graph is defined as the graph of mapped objects that can be obtained by
following relationship links starting from a requester object – the so called reachable
object graph.
ObjectView can handle all changes made to such a graph, involving all persistent
operations in the right database order to perform a full synchronization between object
state and database state. In taking the right steps and finding the right database
operation orders, the parent of relationship concept is used. When necessary, one object
can have more than one database access, for example if involved in self-recursive
relationships where it plays both the parent and child role. ObjectView will discover
and deal correctly with recursive graphs and self-relationships, and offers the assurance
that if the SQL operations are possible to be executed in the context of the existing

10
F E A T U R E S U M M A R Y
database constraints, then a solution to save the graph will always be found. This offers
great advantages to developers who don’t want to spend time creating save methods
themselves to deal with the relationship persistency and operation order aspects for
such graphs, nor to change them if mapping or database changed later or to find that
errors are encountered in methods that were once tested. Imagine an http session
client that updates such a graph state in different web pages, and the complexity to
keep track and save such a graph, compared with the one line of code to save it in the
existing or a new transaction. In literature, object graphs are used to implement the
“Composite Entity” J2EE pattern
(http://java.sun.com/blueprints/corej2eepatterns/Patterns/CompositeEntity.html)
More on this aspect and programming techniques will be presented in the
“ObjectView Programmer s’ Guide”.
Attribute Mapping
By attribute mapping a java attribute is mapped to a database field.
JDBC Type conversions
ObjectView PL permits mapping of all JDBC types. The database – JDBC type
conversion is configurable, such a way that is possible for example to have a String java
attribute mapped to a timestamp or integer database field type.
ObjectView offers the flexibility to create and use your own type converters, in the
event that further computation is needed. In addition is providing a rich set of
converter classes, with the default converter being suggested at mapping time.
Special Fields
A separate role in attribute mapping is played by special attributes like:
 Primary keys
 Autoincrementors: sequences, identity fields, GUIDs, etc.
 Update controllers
 Foreign keys
 Type-subtype discriminators (type-subtype filtering)
 Formulas and read-only fields.

11
F E A T U R E S U M M A R Y
Those fields are managed internally, and their values are supplied by OVPL
framework.
ObjectView Workbench, configuration and user
interface
orkbench is a swing mapping tool application used to assist programmer at
mapping time providing reverse engineering, java method generation and
code merging, mapping validations and database comparison, object
browsing and editing capabilities. Although mapping is possible to be changed using
the provided API by creating/changing simple java methods in the assigned mapping
configuration classes, the Workbench is a great tool with many more features than just
mapping.
W
ObjectView Settings.
We will distinguish between two times in ObjectView application lifecycle:
 Mapping Time. Defined by the time when mapping rules are defined or
changed.
 Runtime. Defined by the time when objects are made persistent based on
mapping configuration.
OVPL settings are a set of properties that are influencing both mapping and runtime
aspects, and are kept in the file named objectview.properties.
We will explain each setting in the “Programmers Guide” for now it will suffice to
know that initial settings loaded in Workbench are coming from this file.
Chapter
3
12
F E A T U R E S U M M A R Y
Properties file. Location and loading aspects
The objectview.properties file is loaded before any of the mapping/runtime activities
becomes available. Its location is searched for in the following steps and order:
 Using the file location specified by the java VM objectview.config parameter.
(-Dobjectview.config = file:/// C:myAppconfigObjectView.properties)
 In the classpath directory location using current classloader.
 In the current user directory (defined by System.getProperty("user.dir" ))
If none of these steps produces a valid location, an error is reported and ObjectView
cannot be initialized.
Properties syntax
Properties are specified in the format KEY=VALUE, where each new KEY must
start on a new line. VALUE is one of the followings:
 A String value, this being the default
 A null value, by leaving the VALUE blank
 An empty string, by specifying “” as VALUE
 The result of a static method evaluation, by specifying the VALUE in the
format KEY=@classMethod ( java_class_name, method_name, arg1, arg2,
arg3,...). Only static methods with string parameters are accepted.
 The value of a system property ( a –D VM defined property), by using the
syntax KEY=@systemProperty(aDefinedSystemPropertyName).
 The result of a conditional expression evaluation using the syntax:
KEY=(defined_Property ? testValue1) value1: (defined_Property ? testValue2)
value3 : , etc
There are two special characters: “” in the last column represents a line continuation,
and “#” in the first column represents a comment line.
Here is the ObjectView.properties file used in the mapping samples presented bellow:
# ObjectView properties file
# compatible version 6.4.44 and above. (v.6.5.44)
# (c) ObjectView Inc. 1997
#
# Prerequisites
# -javax.naming package (JNDI class libraries)
13
F E A T U R E S U M M A R Y
# -javax.sql package (jdbc 2.0, or add JDBC 2.0 optional package)
# -an XML parser
#
# This file is automatically loaded from the objectview.config defined VM parameter if one defined (-
Dobjectview.config=file:///s:myAppconfigObjectView.properties)
# or from the classpath directory location using current classloader,
# or from the current directory (System.getProperty("user.dir" ))
#
# Notes about the content of this file:
# a '' character in last column defines a line continuation.
# a '#' character in first column defines a comment.
# Properties values defined in this file can be obtain as a result of a static java method call, from VM defined
properties, or as a String literal value.
# To define a null value, leave the variable unassigned (property=).
# To define a empty String value use "" (property="" )
# To assign the result of a method evaluation to a defined property, write it in the format : property=@classMethod
( java_class_name, method_name, arg1, arg2, arg3,...). Only static methods with string parameters are accepted.
# To get a property value from System defined properties (VM -D arguments) call
@systemProperty(aDefinedSystemPropertyName)
# To use conditional defined parameters write them in the format: NewProperty=(defined_Property ? testValue)
newValue. If defined_Property has been defined and if is value is testValue then NewProperty=newValue
# To encode 2 or more conditions, use : NewProperty=(defined_Property ? testValue1) newValue1 :
(defined_Property ? testValue2) newValue3 : , etc
#
# -Dobjectview.quietstartup=true
# if a VM system parameter named "objectview.quietstartup" is defined as "true" (-Dobjectview.quietstartup=true),
# ObjectView will not print version and other messages at startup
#
#
#==================================== RUNTIME PROPERTIES ===============================
#-------------------------------------DATABASE CONNECTIVITY----------------------------------------------------------------------------
# there are three object brokers that can be used. A generic ANSI one, and another two for DB2 or Oracle
particularities (JOINS,....)
#if class broker name was defined as the string "DEFAULT_TO_RUNTIME" then the broker is instantiated
based on runtime
#evaluation of the broker definition per objectview.properties file. For example user might define:
#JDB_OBJECT_BROKER=(DB_TYPE ? oracle) com.objectview.jdb.JDBOracleObjectBroker :
(DB_TYPE ? db2) com.objectview.jdb.JDBDB2ObjectBroker
#JDB_OBJECT_BROKER_LIST=(DB_TYPE ? oracle) com.objectview.jdb.JDBOracleObjectBroker :
(DB_TYPE ? db2) com.objectview.jdb.JDBDB2ObjectBroker
# If DB_TYPE=oracle and Broker is DEFAULT_TO_RUNTIME then the oracle broker will be instantiated.
# in this way mapping will not be changed if the application will run with a DB2 databases instead of
Oracle.
# we can define here a variable named DB_TYPE that is retrieved from VM -D defined runtime variables
to be used as a switch for object broker class name
DB_TYPE = @systemProperty(DB_TYPE)
JDB_OBJECT_BROKER=(DB_TYPE ? oracle) com.objectview.jdb.JDBOracleObjectBroker : (DB_TYPE ? db2)
com.objectview.jdb.JDBDB2ObjectBroker : (DB_TYPE ? other) com.objectview.jdb.JDBObjectBroker
JDB_OBJECT_BROKER_LIST=com.objectview.jdb.JDBObjectBroker,com.objectview.jdb.JDBOracleObjectBroker,co
m.objectview.jdb.JDBDB2ObjectBroker
# JDBC driver
JDB_JDBC_DRIVER=(DB_TYPE ? oracle) oracle.jdbc.driver.OracleDriver : (DB_TYPE ? db2)
oracle.jdbc.driver.OracleDriver : (DB_TYPE ? other) sun.jdbc.odbc.JdbcOdbcDriver
DB_CONNECTION_URL=jdbc:oracle:thin:@localhost
14
F E A T U R E S U M M A R Y
DB_CONNECTION_USER_ID=system
DB_CONNECTION_PASSWORD=objectview
# the catalog (database name in most of the cases, sometimes null, sometimes "") used in jdbc metadata
methods. Leave empty for null, Use "" for empty string
DB_CONNECTION_CATALOG=
# the schema name ( in Oracle and DB2 use the chema name, sometimes null, sometimes "") used in jdbc
metadata methods. Leave empty for null, Use "" for empty string
DB_CONNECTION_SCHEMA=
# define here the sql used to initialize each db connection, after opening it, for example in Oracle use:
DB_CONNECTION_INIT_SQL=ALTER SESSION SET CURRENT_SCHEMA= aSchemaName
DB_CONNECTION_INIT_SQL=
# If autocommit true, jdbc driver will commit each SQL sent. If Odbc driver does not have a correspondent
for jdbc setAutoCommit() API, then set the autocommit property on true.
DB_CONNECTION_AUTO_COMMIT=false
# controls how are transactions managed (internally by ObjectView or by an external TM - EJB
container ) .
# Used in combination with DB_CONNECTION_POOL_USE_EXTERNAL_POOL to use the connections
provided and managed by the EJB container.
DB_CONNECTION_EXTERNAL_TRANSACTION_MONITOR=false
# Cursor SQL type for stored procedures returning cursors.
# Particular for specific jdbc implementations. In this case Oracle DB. Please verify its value in the class
oracle.jdbc.OracleTypes.CURSOR
PROP_DB_SQLTYPES_CURSOR=-10
# exclusive locking SQL syntax ( use NOWAIT option when available )
EXCLUSIVE_LOCKING_SQL=FOR UPDATE NOWAIT
#-------------------------------------MAPPING SCHEMA----------------------------------------------------------------------------------------
#maps to initialize. Use a comma separated string if more than one map initializer
JDB_MAPPING_SCHEMA=com.objectview.examples.domain.MappingInitializer
#-------------------------------------INTERNAL CONNECTION POOL SETTINGS------------------------------------------------------
# after how many milliseconds a connection is considered expired. (-1) for never expire
DB_CONNECTION_POOL_EXPIRATION_TIME=86400000
DB_CONNECTION_POOL_INITIAL_SIZE=20
DB_CONNECTION_POOL_GROW_INCREMENT=10
DB_CONNECTION_POOL_MAX_SIZE=1000
DB_CONNECTION_POOL_ACQUIRE_RETRIES=2
#-------------------------------------EXTERNAL CONNECTION POOL ACCESS USING DATASOURCES ----------------------
# set this attribute to true in order to use an external connection pool ( i.e. EJB container)
DB_CONNECTION_POOL_USE_EXTERNAL_POOL=false
INITIAL_CONTEXT_FACTORY=weblogic.jndi.WLInitialContextFactory
PROVIDER_URL=t3://localhost:7001
SECURITY_PRINCIPAL=myUser
SECURITY_CREDENTIALS=myUserCredentials
DATA_SOURCE_JNDI_NAME=dataSourceJndiName
#-------------------------------------LOGGING -----------------------------------------------------------------------------------------------------
# if DB_CONNECTION_DEBUG=true, and session was acquired using JDBConnection pool then log sql
used.
# If VERBOSE_MODE is true, the sql will be sent to System.out,
# otherwise logs to the listener attached to connection pool or to the one attached to the JDBSession
object.
DB_CONNECTION_DEBUG=true
15
F E A T U R E S U M M A R Y
# if DB_CONNECTION_DEBUG is true, then by setting VERBOSE_MODE also true, all sql activity will be
printed to System.out (sql trace)
VERBOSE_MODE=true
# if this is true then the stack trace for opening sessions is log internally for each session and kept inside
OpenedStackTrace session variable.
# if VERBOSE_MODE is true, the stack will be sent to System.out as well.
LOG_SESSION_OPENING_STACK_TRACE=false
# following setting used to print any db activity for instances pertaining to listed classes. This property
settings will help to trace the piece of code where
# an object gets modified, in a multithreaded environment. Set this property using a comma separated list
of the class names to trace. Ex:
INSTANCE_TRACING=com.objectview.sample.Person,com.objectview.sample.Address
INSTANCE_TRACING=
# setting the next property to true will log the xml representation of current object for any save operation
exception. The file will be named objectDump.xml
# and its location will be given by the XML_LOG_FILE_LOCATION setting. XML representation of the
objects that generated save
LOG_TO_XML_IF_SAVE_ERROR=true
# location of the objectDump.xml is given by the next setting.
# The default is to leave it blank, case in which the current working directory will be used instead.
# Usage example: XML_LOG_FILE_LOCATION=@systemProperty(user.home)
XML_LOG_FILE_LOCATION=
# set the xml parser used to create java objects back from xml documents. (Tested with
org.apache.xerces.parsers.DOMParser , com.ibm.xml.parsers.NonValidatingTXDOMParser and
javax.xml.parsers.DocumentBuilder)
# If javax.xml.parsers.DocumentBuilder is used then the parser will be instantiated using the javax.xml
1.4.0 extension.
# The parser must be in the VM classpath. i.e.
XML_PARSER_CLASS=org.apache.xerces.parsers.DOMParser
XML_PARSER_CLASS=javax.xml.parsers.DocumentBuilder
#==================================== MAPPING (DESIGN TIME) PROPERTIES =================
#-------------------------------------WORKBENCH USER INTERFACE SETTINGS -----------------------------------------------------
# path for generating and reading java files (current version and new version)
JDB_IN_DIR=C:objectview.workspaceObjectViewMappingsDemosrc
JDB_OUT_DIR=C:objectview.workspaceObjectViewMappingsDemosrc
# Exclude next tables from database versus schema comparation ( these tables are not mapped, and are
not intended to be, so its no use to mark the differencies )
# Specify them as a comma separated list:
EXCLUDE_TABLES=
# if false cannot save objects to persistent store using Workbench UI. This setting should be used
# in production environments where user should not be able to perform any db operations outside
application environments
WORKBENCH_OBJECT_EDITABLE=true
#-------------------------------------AUTOINCREMENTORS AND CONTROLERS-------------------------------------------------------
# autoincrementor sql (sequence nextValue sql or another sql). This sql is executed before insert sql to get
an ID.
16
F E A T U R E S U M M A R Y
# Can use the following macros inside the definitio string [COLUMN_NAME] for current selected attribute
Column_Name,
# [TABLE_NAME] for current class table name and [CLASS_NAME] for current java class name
# Used to implement Oracle and DB2 sequences. Can be also used as generic like : SELECT MAX() + 1;
# The SQL expression must must return a result set if executed. The value from firt column from first row
is used as the field value.
# To call a java class for an unique ID implementation (GUID) , create a static method to compute the id
and
# specify <@GUID ( java_class_name, method_name)> as for the autoincrementor definition. The
method will be called
# without parameters, and if not found will be called with parameters (String persistentJavaClassName,
JDBSession session). In the second case
# parameters can be used to implement specific ID methods, when a SQL to execute is not enough. For
example can implement different methods
# depending of the target db, being able to switch from one db engine to another at the runtime.
# Samples:
# PRE_INCREMENTOR_SQL=@GUID([CLASS_NAME], getObjectId)
# PRE_INCREMENTOR_SQL=SELECT NEXTVAL for [COLUMN_NAME] FROM DUAL
PRE_INCREMENTOR_SQL=SELECT [COLUMN_NAME].nextval from dual
# post insert SQL. This Sql is used after insert to get an ID value. (Similar to Sybase identity field type)
# must return a result set. The value from firt column from first row is used as the field value
# POST_INCREMENTOR_SQL=SELECT [COLUMN_NAME] = @@identity
# POST_INCREMENTOR_SQL=SELECT @@identity
POST_INCREMENTOR_SQL=SELECT @@identity
#-------------------------------------METADATA BROKERS AND DRIVER SPECIFICS -----------------------------------------------
# all jdbc metadata request brokers that are available (any subclass of JDBGenericRequestBroker).
JDBC_METADATA_BROKERS=com.objectview.jdb.ui.JdbcRequestBroker,com.objectview.jdb.ui.JdbcRequestBroke
rFieldNames,com.objectview.jdb.ui.SybaseAnywhere6
# default request broker for database metadata retrieving
JDB_REQUEST_BROKER=com.objectview.jdb.ui.JdbcRequestBroker
# Field type to java type mapping in case user chooses
JDB_REQUEST_BROKER=com.objectview.jdb.ui.JdbcRequestBroker
# The following dictionary associates a java.sql.Types with a pair of
com.objectview.binders.JDBAttributeSaver respectively com.objectview.binders.JDBAttributeRetriever subclasses.
# Right members of this mapping are subclasses of com.objectview.binders.JDBAttributeSaver and
com.objectview.binders.JDBAttributeRetriever classes.
# These settings can be overwritten at mapping design time , and are specified here only to speed up the
mapping process
DB_TYPE_JAVA_TYPE_TRANSLATION=
BIT, com.objectview.binders.JDBbooleanSaver, com.objectview.binders.JDBbooleanRetriever|
INTEGER, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever|
TINYINT, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever|
SMALLINT, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever|
BIGINT, com.objectview.binders.JDBLongSaver, com.objectview.binders.JDBLongRetriever|
FLOAT, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBdoubleRetriever|
DOUBLE, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBdoubleRetriever|
REAL, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBdoubleRetriever|
DECIMAL, com.objectview.binders.JDBDecimalSaver, com.objectview.binders.JDBDecimalRetriever|
NUMERIC, com.objectview.binders.JDBLongSaver, com.objectview.binders.JDBLongRetriever|
CHAR, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
VARCHAR, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
17
F E A T U R E S U M M A R Y
LONGVARCHAR, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
CLOB, com.objectview.binders.JDBClobSaver, com.objectview.binders.JDBClobRetriever|
BLOB, com.objectview.binders.JDBBlobSaver, com.objectview.binders.JDBBlobRetriever|
BINARY, com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBBinaryRetriever|
VARBINARY, com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBBinaryRetriever|
LONGVARBINARY,com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBBinaryRetriever|
DATE, com.objectview.binders.JDBDateSaver, com.objectview.binders.JDBDateRetriever|
TIMESTAMP, com.objectview.binders.JDBTimestampSaver, com.objectview.binders.JDBTimestampRetriever|
TIME, com.objectview.binders.JDBTimeSaver, com.objectview.binders.JDBTimeRetriever
# naming convention for Update incrementor field used for concurrent update control. Any table field
containing the following string is automatically mapped as an updateController.
UPDATE_CONTROLLER_INCREMENTOR_WILDCARD=UPDATE_NUM
# field name to java type conversion dictionaries. The following mapping takes place
# in case JDB_REQUEST_BROKER=com.objectview.jdb.ui.JdbcRequestBrokerFieldNames setting was
specified.
# The following dictionary specifies a naming to type mapping convention.
# XXX* stands for any field name prefixed with XXX string, *XXX* any field containing XXX, *XXX any
string ending in XXX
# Right members of this mapping are subclasses of com.objectview.binders.JDBAttributeSaver and
com.objectview.binders.JDBAttributeRetriever classes.
# These settings can be overwritten at mapping design time , and are specified here only to speed up the
mapping process
FIELD_NAME_JAVA_TYPE_TRANSLATION=
*RATE, com.objectview.binders.JDBBigDecimalSaver, com.objectview.binders.JDBBigDecimalRetriever|
*AMT, com.objectview.binders.JDBBigDecimalSaver, com.objectview.binders.JDBBigDecimalRetriever|
*B, com.objectview.binders.JDBbooleanToStringSaver,
com.objectview.binders.JDBbooleanFromStringRetriever|
*BOOLEAN, com.objectview.binders.JDBbooleanToIntegerSaver,
com.objectview.binders.JDBbooleanFromIntegerRetriever|
*ID, com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBIntegerRetriever|
*UPDATE_NUM,com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBIntegerRetriever|
*NUMBER, com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBIntegerRetriever|
*SIGN, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever|
*CODE, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*SNUMBER, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*TYPE, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever|
*STYPE, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*STRING, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*LDESC, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*LSTRING, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*SDESC, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*NAME, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever|
*DATE, com.objectview.binders.JDBDateSaver, com.objectview.binders.JDBDateRetriever|
*CLOB, com.objectview.binders.JDBClobSaver, com.objectview.binders.JDBClobRetriever|
*BLOB, com.objectview.binders.JDBBlobSaver, com.objectview.binders.JDBBlobRetriever|
*DATETIME, com.objectview.binders.JDBTimestampSaver, com.objectview.binders.JDBTimestampRetriever
#-------------------------------------TYPE CONVERSIONS, SQL PARAMETERS BINDING-------------------------------------------
# Objectview result set retrieve methods. (implementation of getObject methods for result set)
# the last binder is provided as an example
OBJECTVIEW_RETRIEVE_BINDERS=
com.objectview.binders.JDBStringRetriever,
com.objectview.binders.JDBIntegerRetriever,
com.objectview.binders.JDBintRetriever,
18
F E A T U R E S U M M A R Y
com.objectview.binders.JDBLongRetriever,
com.objectview.binders.JDBdoubleRetriever,
com.objectview.binders.JDBDoubleWrapperRetriever,
com.objectview.binders.JDBDecimalRetriever,
com.objectview.binders.JDBBigDecimalRetriever,
com.objectview.binders.JDBbooleanRetriever,
com.objectview.binders.JDBbooleanFromIntegerRetriever,
com.objectview.binders.JDBbooleanFromStringRetriever,
com.objectview.binders.JDBBooleanWrapperRetriever,
com.objectview.binders.JDBTimestampRetriever,
com.objectview.binders.JDBTimeRetriever,
com.objectview.binders.JDBDateRetriever,
com.objectview.binders.JDBJavaUtilDateFromTimestampRetriever,
com.objectview.binders.JDBcharRetriever,
com.objectview.binders.JDBCharacterRetriever,
com.objectview.binders.JDBBinaryRetriever,
com.objectview.binders.JDBClobRetriever,
com.objectview.binders.JDBBlobRetriever,
com.objectview.binders.JDBTimestampIndirectRetriever,
com.objectview.examples.binders.SimpleStringDecoderRetriever
# ObjectView prepared statement set methods binders. (implementation of setObject methods for
prepared statement).
# the last binder is provided as an example
OBJECTVIEW_SAVE_BINDERS=
com.objectview.binders.JDBStringSaver,
com.objectview.binders.JDBIntegerSaver,
com.objectview.binders.JDBintSaver,
com.objectview.binders.JDBLongSaver,
com.objectview.binders.JDBdoubleSaver,
com.objectview.binders.JDBDoubleWrapperSaver,
com.objectview.binders.JDBDecimalSaver,
com.objectview.binders.JDBBigDecimalSaver,
com.objectview.binders.JDBbooleanSaver,
com.objectview.binders.JDBbooleanToIntegerSaver,
com.objectview.binders.JDBbooleanToStringSaver,
com.objectview.binders.JDBBooleanWrapperSaver,
com.objectview.binders.JDBTimestampSaver,
com.objectview.binders.JDBTimeSaver,
com.objectview.binders.JDBDateSaver,
com.objectview.binders.JDBJavaUtilDateToTimestampSaver,
com.objectview.binders.JDBcharSaver,
com.objectview.binders.JDBCharacterSaver,
com.objectview.binders.JDBBinarySaver,
com.objectview.binders.JDBClobSaver,
com.objectview.binders.JDBBlobSaver,
com.objectview.binders.JDBTimestampIndirectSaver,
com.objectview.examples.binders.SimpleStringEncoderSaver
#---------------------------------REQUIRED PROPERTIES_VERSION---------------------------------------------------------------------
# if -Dobjectview.properties.requiredversion is defined then it must match with the value
# specified by the property named PROPERTIES_VERSION. (This is not a check against objectView
application version)
PROPERTIES_VERSION=1.0
19
F E A T U R E S U M M A R Y
Workbench loading
Based on the IDE you are using, create a batch file, or a run configuration (VisualAge,
Eclipse, Jprobe) and run the class com.objectview.jdb.Workbench to open the
Workbench application. Example of batch file:
For eclipse IDE, here is the run configuration for Oracle mapping sample I have used
in the programming guide.
20
rem in case not already set to point to your JDK instalation
rem set JAVA_HOME=T:JDKsjdk1.3.1
set APP_LIBS=S:eclipse.workspacewebuiDefaultWebAppWEB-INFlib
set APP_CLASSES=S:eclipse.workspacewebuiDefaultWebAppWEB-INFclasses
rem --------------------start ObjectView UI
%JAVA_HOME%binjava -classic -classpath "%APP_CLASSES%;%APP_LIBS%;%APP_LIBS
%xerces.jar; ;%APP_LIBS%oracleclasses12.jar %APP_LIBS%objectView.jar; " -
Dobjectview.config=file:///s:/objectview/config/ObjectView.properties com.objectview.jdb.Workbench
-notrace -outputon
F E A T U R E S U M M A R Y
Workbench Settings Panel
First panel that opens in Workbench application is the Settings panel:
21
F E A T U R E S U M M A R Y
The default settings in this panel are loaded from the objectview.properties file and
then can be changed by the Workbench user. The settings that are changed are not
written back in the properties file, user must update the properties file with the settings
that are changed in order to preserve them.
UI widgets and controls:
 Mapping Initializers. The mapping instructions are kept in java class files
named Mapping Initializers. A mapping initializer is a class that has the
following characteristics:
1. Inherits from com.objectview.jdb.JDBMapInitializer.
2. There is only one map initializer for any java package containing persistent
classes, and a mapping initializer cannot store mapping instructions for
classes in different packages. Relationships between classes in different
packages are permitted, and the order in which these initializers are loaded
is not important.
3. Mapping initializer classes are java source classes produced by the
Workbench tool but can also be created and modified by the user outside
the mapping tool. For each persistent class in the host package there will
22
F E A T U R E S U M M A R Y
be one method present in the initializer class to store the mapping
information.
Mapping initializers are specified in a comma-separated string assigned to the
property named JDB_MAPPING_SCHEMA. Workbench will try to load all
mapping initializers, and will assume that the ones not found are new ones that will
be generated in current Workbench session.
So, to create a new initializer, just add its java class name in the property file or in
the corresponding workbench settings field, in a comma-separated string. Then
press “Reload Maps” button. You will be now able to create persistent classes in
the package managed by the new initializer.
 JDBC database driver. Specify here the name of the java class implementing
the JDBC-compliant driver being used. The driver must be in the workbench
class path. The properties file correspondent setting is JDB_JDBC_DRIVER.
 Catalogue. ObjectView is using JDBC metadata information when available
to assist in mapping process. The catalogue is used in the JDBC methods used
to gather metadata information. (Interchangeable with database name
sometimes) The corresponding property is
DB_CONNECTION_CATALOG.
 Schema. Used for gathering metadata information. The corresponding
property is DB_CONNECTION_SCHEMA.
 Connection init SQL. SQL that will be used to initialize each connection
before being used. For example, in Oracle it can be set to: ALTER SESSION
SET CURRENT_SCHEMA= mySchema.
 JDBC Metadata broker. The corresponding property name is
JDBC_METADATA_BROKERS and consists of a list of two classes to pick
from: com.objectview.jdb.ui.JdbcRequestBroker, and
com.objectview.jdb.ui.JdbcRequestBrokerFieldNames. These classes are
responsible for proposing the data type translation between data types and java
types.
1. In first case the types are converted using the matching pairs specified in
the DB_TYPE_JAVA_TYPE_TRANSLATION property setting. The
conversion is specified associating JDBC types with the ObjectView
conversion classes. For example by default BIT JDBC type is associated
with boolean java type.
2. In the second case, the broker uses naming convention to propose a java
type based on a database field name. In most of the cases, best practice
23
F E A T U R E S U M M A R Y
reasons, DBAs use naming conventions that carry also type information.
For example any date field will end up in ‘DATE’ suffix, any float field will
end up with ‘AMT’ suffix, and so on. It will be the field name that will be
used to make a distinction between a CHAR field holding a string
information (code) or a boolean value. The name java type translation
information is described by the
FIELD_NAME_JAVA_TYPE_TRANSLATION property setting.
The type conversion proposed by the metadata broker is the default one, is part of
the attribute mapping information, and can be changed by user any time when
necessary. Brokers role is mostly in the reverse engineer procedures, and to
ease/assist the mapping task.
 Connect, Disconnect. Connects to the database using the current settings. Once
connected, mapping process is assisted by metadata information, and database
access Workbench functions become available (database comparison, data
browsing and editing). The Workspace might be connected, but the metadata
information might not be available (first sign is when no tables are found after
connect). This might happen because there might not be any metadata available
using current JDBC driver, or userId/pswd supplied has no rights to gather it, or
the metadata information cannot be extracted from current database because the
connection information is not correct. Check the catalog and schema settings as
well. Some databases require null some an empty string for the catalog name.
Leave empty for null and input “” for empty string and reconnect.
Connecting the Workbench to the database enables the
application features related to database access. Those are
assisted mapping, database browsing, object editors, and
database comparison. The database metadata information is
gathered and used to ease the mapping effort, but its
presence is not mandatory for mapping process.
 External Transaction Monitoring. If this flag is set on true by
DB_CONNECTION_EXTERNAL_TRANSACTION_MONITOR global
property or by setting it for a particular session then the transaction can be initiated
and terminated only by an external transaction monitor (i.e. an EJB container).
Such setting is used to integrate transaction management with middleware systems
and is used in combination with external connection poll settings (external
datasources interface settings) to acquire connections created and owned by the
external monitor. In workbench this flag will be rarely used if ever, but the
corresponding property setting is a key configuration in the integration with a
middleware task. This will be covered in more detail in the “Programmer’s
Manual”.

24
F E A T U R E S U M M A R Y
 Auto Commit. This flag is used to call the java.sql.Connection .setAutoCommit()
method. If this flag is on true, there is a commit performed after each SQL sent to
the data serve and no transaction control beyond one SQL command at a time.
 Output Directory. ObjectView generates domain classes and mapping information
data (mapping initializer class) into this directory. Classes generated in this
directory must be loaded back into IDE, if not already an IDE source directory.
 Input Directories. A comma-separated list of directories where ObjectView
searches for the source files used to extract user added content to be merged with
the generated content. Usually the same directory as the “Output Directory” and
the project source directory for the IDE used. If input and output directories point
to the same location, IDE should have a versioning control in place in order to
pull back the last class version if ever needed.
 Erase Output. Press this button to erase the output directory. Pay attention to the
case when input points to the same directory location, and this operation is not
desirable. By erasing previously generated files, it will become more clearly what
are the files being currently generated.
25
F E A T U R E S U M M A R Y
Inheritance Tree Panel
The tree showing in the upper left corner displays all mapped classes, and their
hierarchy up to the JDBPersistentObject class.
 New Map. The result of creating a new map is two fold: a new domain class will be
created, and a new method in the selected map initializer will be created to load
and store the mapping meta-information. To create a new map, select a class from
the class hierarchy tree to become the superclass of the new class being created.
Then press the “New Map” button. On the right side there are three tabs, where
each tab is storing mapping information specific to one of the three main mapping
topics: class wide scope mapping, attribute mapping and association mapping.
 New helper. Helpers are used to map one java class to more than one table. The
helper is mapping the join between any two tables, based on their primary keys.
This join is used to retrieve one java persistent class. Helpers can be added to any
existing maps.
 Table Explorer. If Workbench is connected, select one persistent class in the class
hierarchy tree and press this button to display the table data associated with that
class. If table (join) has more than 10000 rows, a warning message is displayed
instead. Select an individual row from this table and you can open the object
explorer frame.
26
F E A T U R E S U M M A R Y
 Object Explorer. Press this button and the object browsing and editing application
will be open. Details and instructions will be presented in the section “Object
Browsing and Editing Application”.
Class Mapping Panel
The class-mapping panel is used to edit mapping information pertaining to a class for a
new or existing map.
 Class Mapping Initializer. The list of map initializers is coming from the
JDB_MAPPING_SCHEMA property, and can be updated by the settings panel.
As explained earlier, a mapping initializer is tight to a java package, and all
persistent classes from one package have mapping information initialized and
stored in one mapping initializer contained in the same java package. Mapping
initializer can be chosen only once, when a new class map is being created, and
cannot be changed later on. Changing the mapping initializer is somewhat similar
with moving a class to a different package, and this operation cannot be done
using the Workbench (some java IDE will assist you in this scope).
 Related Table. The table mapped by current domain class. There are two special
cases to distinguish here:
27
F E A T U R E S U M M A R Y
1. If table name is left with the default name “tableName”, then the
generated class will not be a persistent class, but will be presented in the
class hierarchy. For example the “AbstractExternalAccount” class in the
above picture is not a persistent class.
2. In case a new helper is created (for an existing class map) the table picked
must be in a one-to-one relationship with the main table, based on a
Primary Key join.
A list of all available tables visible using the userId/passwd connection information
will be presented in the “Related Table” drop-down list control. If a table list is not
available, then the Workspace is not connected, or userId/pswd supplied has no
rights to see them, or the metadata information cannot be extracted from current
database either because it is not available or the connection properties are not
correct. Change login information and reconnect. Anyway, it is possible to map a
table even if no metadata can be extracted.
Once a table has been picked and metadata is retrievable, the available fields are
mapped to attributes, mapping that can be reviewed and changed in the “Attribute
Mapping Panel”.
 Database Name. The name of the database table, view or stored procedure used
to map current domain class. If metadata is not available, this information must be
entered by hand.
 Java Name. The name of the mapped java class, not including the package name
that will be borrowed from the mapping-initializer class name.
 XML Name. The value entered here will be used for the tag name in the xml
representation for objects of this class. By default, if nothing entered, the tag name
used is the java class name.
 Additional Where Clause. String expression in SQL syntax that can be used as
where clause. This where clause will be always used in all attempts to instantiate
objects based on map in discussion. This aspect differentiates this where clause
from the ad-hoc ones that are mostly used as parameters in the API retrieve
methods.
 Max Rows Retrieved. Max rows allowed to be retrieved in a single retrieve
method.
 Broker Class Name. The name of the java class used to translate persistent
method calls to SQL commands. Three classes are provided, but more can be
created. The default class is com.objectview.jdb.JDBObjectBroker, and it can
handle a JDBC compliant driver and a relational database (RDBMS). Another
28
F E A T U R E S U M M A R Y
provided class is com.objectview.jdb.JDBOracleObjectBroker that handles Oracle
particularities (the left outer join symbol is "(+)" instead of “*=”, and
retrieveAllUsingOpenCursor method has a specific implementation). Also a
special one is provided for DB2 particularities.
 Use empty strings instead of Nulls. This is a useful setting for particular database
engines (like Excel spreadsheet).
 Acquire and release DB session internally. Does not expose transaction
context. If set, ObjectView will generate data access methods that will not have a
connection parameter, connections being acquired and released when needed
using the connection properties set provided. This will simplify framework usage,
but will not permit transaction management outside method scope.
 Expose transaction context in generated methods. If set, ObjectView will
generate data access methods that will have a connection parameter, making
possible to integrate transaction management with an external middleware (EJB
container).
 Read-Only Access Class. Only methods for retrieving the persistent state will be
generated, no insert, updates, deletes will be possible for such a class.
 Is a Database View or a Stored Procedure producing a result set. In this case
database access is read only, and a custom SQL will be required as a parameter for
each retrieve method. In fact, only the methods “retrieveAllUsingSQL”,
“retrieveAllUsingStoredProc” and “retrieveAllUsingOpenCursor” will be
generated and available for use.
 DB Session wide Scope. Attach/Detach cache management procedures. By
default, this limits the cache scope to the database session usage time. But because
session has procedures to attach and detach the cache, its scope can be increased,
for example it can be increased for the duration of an http client session, by
detaching and attaching the cache stored in an http session each time a new db
session is acquired or released.
 Global cache. VM wide scope. Objects are only retrieved once, the first time they
are instantiated, and then returned from this global cache for subsequent inquiries.
Should only be used for immutable objects, because object state changes are not
synchronized for multiple users.
 Weak Referenced Global Cache. VM wide scope. Same as above, but objects are
discarded from cache once they are de-referenced.
 SQL subset cache. Objects are cached under the SQL used to retrieve them. This
is like a view applied to the global cache, where subsets of objects are gathered
29
F E A T U R E S U M M A R Y
under the SQL used first time to retrieve them. If exact SQL is used a second time,
objects are retrieved directly from cache, without accessing the database. And
because this represents a view of the global cache, and not a separate cache
container, one object will still be cached only once, only it will be viewed as
belonging to different cache groupings.
 Java Superclass Name. Not editable here, this widget has only an informational
meaning.
 Vertical Mapping Discriminator Value. This is a non mandatory value of the
discriminator field used in inheritance vertical mapping. This value is defined as
having a class scope, and will be held by a static variable being generated together
with the persistent class. The correspondent attribute will be mapped is the
superclass as having “Vertical Mapping Discriminator” flag set on, in the
“Attribute Mapping Panel”. (Note that the attribute is defined in the supertype,
while its value is specified in the subtype). If such a value is specified, it will serve
to automatically cast down objects to their lowest type, and will be used to generate
“isTypeOf” type methods.
30
Attribute Mapping Panel
This panel is used to capture the java attribute to database field mapping information.
 Related Field. This widget is a drop-down list being initialized with all the fields
for the current database table. By picking one field from the list the field metadata
is used to generate the default attribute mapping information. This mapping
information that makes the subject of all widgets in this panel can then be changed
and ultimately saved. The “Related Field” widget is only selectable if Workbench is
connected and if field metadata is available and is only used to gather metadata
information used to ease mapping effort, but its presence is not mandatory for
mapping process.
 Database Name. This is the name of the database field, or the given name of a
computed column in the case this attribute maps a database formula/expression.
This field is pre-filled using metadata information if available, and should be
M A P P I N G T O O L U S E R S ’ G U I D E
entered by user if no metadata information available or if represents a computed
field.
 JDBC Type. Informational scope only. Present only if metadata available.
 Java Name. The name of the java class attribute used to store this field value.
 Java Type. Change the type conversion class -Attribute Retriever- to have this
information changed accordingly.
 Java Initial Value. The literal used to initialize the java variable. The string is
copied identically and place on the right side of the equal sign in variable
declaration statement. For example in case of a String type attribute the
expressions “ObjectView Inc.” or new String (“ObjectView Inc.”) would be valid
initializers.
 User Documentation. Text will be copied in the getter and setter method javadoc
documentation.
 XML Name. This value entered will be used for the tag name in the xml
representation for this attribute. By default, if nothing entered, the tag name used is
the java attribute name.
 Attribute Saver. This class will be used to convert attribute to one of the types
used for binding parameters to a prepared statement. The list of available classes
implementing the JDBAttributeSaverInterface is specified in objectview.properties
file by property OBJECTVIEW_SAVE_BINDERS. Developers can add
customized classes by inheriting one of the existing “Saver” classes or by inheriting
directly from JDBAttributeSaver class. When a custom class is created, that class
can also specify a custom pre-save method (see pre-save method setting bellow).
 Attribute Retriever. This class will be used to convert the value obtained from a
result set to the type used to represent it in the java persistent class. The list of
available classes implementing the JDBAttributeRetrieverInterface is specified in
objectview.properties file by property OBJECTVIEW_RETRIEVE_BINDERS.
Developers can add customized classes by inheriting one of the existing
“Retriever” classes or by inheriting directly from JDBAttributeRetriever class.
When a custom class is created, that class can also specify a custom post-retrieve
method (see post-retrieve method setting bellow).
 Post Retrieve Method. If entered, this user method will be called after retrieving
the field from database. Such a method is only available to customized Attribute
Retrievers (and not the ones provided by OVPL). The only argument for post
retrieve method is the retrieved field value, and the method must be added in the
attribute retriever class.
M A P P I N G T O O L U S E R S ’ G U I D E
 Pre Save Method. If entered, this user method will be called before saving the
field to database. Such a method is only available to customized Attribute Savers
(and not the ones provided by OVPL). The only argument for pre save method is
the java attribute value and the method must be added in the attribute saver class.
 Primary Key. Field is part of the table primary key. In this case it can also be a pre-
increment or post-increment attribute.
 Pre Auto-Incrementor. The attribute value will be obtained before issuing the
insert statement. Usually the value comes from a sequence table or from a third-
party library method invocation in case of a GUID. When the check button is set,
the autoincrementor definition is initialized based on
PRE_INCREMENTOR_SQL property.
 Post Auto-Incrementor. If set, this attribute will have a corresponding null value
in the insert statement, assuming that the field value will be known only after insert
statement execution. Same as for auto-incrementors, the value is computed by
evaluating the expression specified in the “Auto-Incrementor Definition” UI entry
field. This setting is used for Sybase like identity fields. In this case the DB engine
assigns the field value and also provides the mechanism to obtain the value –
usually by issuing a SQL statement. The provided SQL will be issued inside the
same transaction with the insert statement. By default, the initial value is computed
using POST_INCREMENTOR_SQL property definition (after expanding the
table and column name macros in case they are used)
 Read-Only Access. If set, this attribute will be retrieved from database but not
updated when object gets saved back.
 Field Retrieve Definition. This entry field store the expression used for
autoincrementor, identity, read-only or computed fields. Depending on these flags,
its value is interpreted differently as explained bellow:
1. For a pre-autoincrementor field it will store the SQL or java expression
used to get the field value to be used in the insert statement:
a. PRE_INCREMENTOR_SQL=@GUID([AFullQualifiedJavaClassN
ame], aStaticMethod)
b. PRE_INCREMENTOR_SQL=SELECT
[COLUMN_NAME].nextval from dual
In the first case “aStaticMethod” will be called in the java class
“AFullQualifiedJavaClassName”, while in the second case the
SELECT statement will be issued to get the field value. Notice
that the TABLE_NAME, COLUMN_NAME are macros that
M A P P I N G T O O L U S E R S ’ G U I D E
can be specified in the property file and that will expand to real
values based on current column and table selected by UI user in
Workbench (i.e. in design time and not runtime).
2. For a post-autoincrementor (identity) field it will store the SQL used to get
the inserted value. By default field is initialized by expanding
POST_INCREMENTOR_SQL property field.
3. For a read-only field, retrieve definition scope is three fold:
R
ea
d-
O
nl
y
Retriev
e
Definit
ion
Scope
T
r
u
e
False Field is retrieved from database, but inserts
or updates are not possible.
T
r
u
e
True Field is retrieved using the SQL definition
provided, inserts or updates are not
possible.
F
a
l
s
e
True Field is inserted using the SQL definition,
then can it can be updated with any other
value.
 Filtered Mapping Discriminator. Attribute is used for mapping inheritance to the
same table schema. The attribute value for the current subtype must be stored in
“Discriminator Value” field. See “Mapping Considerations” chapter for
inheritance mapping schemas.
 Vertical Mapping Discriminator. Attribute is used for mapping inheritance to
different tables using a join statement and defining a discriminator filter for each
subtype. The attribute value for each subtype must be stored in the corresponding
subclass in the “Vertical Mapping Discriminator Value” field (class mapping UI
panel). See “Mapping Considerations” chapter for inheritance mapping schemas.
M A P P I N G T O O L U S E R S ’ G U I D E
Note that the field is defined in the supertype, while the field values are defined in
each subtype. By using a discriminator, OVPL is capable of casting objects easily;
in this case isSubTypeOf methods are provided in each superclass and subtypes
can be retrieved automatically.
 Not Nullable. If set, attribute cannot take null values. The setting only plays a role
in mapping recursive associations; in this case it will be used to determine the order
in which the SQL statements are to be issued when an object graph is saved.
 Update Controllers. Attributes have the sole meaning to prevent dirty reads
using optimistic locking mechanism. Such a field will be incremented
automatically with each update and the value in memory verified with the
value from database (in the update where clause) each time a new update is
issued.
Attention: Because update controller fields are used in the update
where clause, they must represent a real table column and not a
composed or formula field. Also, if inheritance is mapped to different
tables (vertical approach) then one update controller must be present for
each particular table and defining just one at the supertype level will only
shield for concurrent updates happening at supertype level and not for
any fields saved to subtype tables(s).
Update Counter. If set, the current attribute will be used for optimistic
update control and the attribute value represents an Integer and will be
incremented automatically for each update.
Update Timestamp. Same role as the Update Counter, with the difference
that the current attribute must be of type java.sql.Timestamp and its value
will be stamped with last successfully update datetime.
Association Mapping Panel
This panel is used to configure association mapping information.
M A P P I N G T O O L U S E R S ’ G U I D E
One-To-Many Association Mapping
There are two terms that will be used here: source class and target class. An
association is defined as a relationship between a source class and a target class.
This relationship has a “from cardinality”, a “to cardinality” and a role name.
The role name must be unique and will be used in the role accessors and in the
find methods generated by OVPL. In runtime relationship definition will
translate in a table join, where the join expression is constructed from the
association foreign keys.
 Association Target Class. All mapped classes are gathered in this table the one
that constitutes the target class for current selected association is highlighted.
 Use FK Definitions. When selected, database foreign keys definitions will be used
to assist user in creating the correspondent associations.
 Association Join Definition. This table is used to define the source and target
attribute pairs used in database join that will be used to retrieve the rows from the
association table. The corresponding source attributes and target attributes
must be of the same type.
M A P P I N G T O O L U S E R S ’ G U I D E
 Role Name. Unique name that will designate the attribute holding the association.
The role name will be also be used to generate find methods.
 Order-By Clause. When specified, a one-to-many association is always retrieved
ordered using this expression. The expression used must be a valid SQL order-by
clause (without the keywords ORDER BY) - usually the database fields separated
by comma. The expression specified here represents the default order by, a
constant for the association, unlike the orderBy parameter from association getter
that can be changed within each runtime invocation.
 Where Clause. When specified, this where clause is added to the one used to
retrieve the relationship. The expression used must be a valid SQL where clause
(without the WHERE keyword). When a where clause is specified, the association
represents only a subset of the rows represented by the relationship join. If a new
object is added to such a collection, that object will not be checked to verify that it
complies with the association filter. Like the Order By clause, this represents a
constant for the association retrieval, unlike the where parameter from association
getters that represents a configurable runtime setting.
 XML Name. This value entered will be used for the tag name in the xml
representation for this association. By default, if nothing entered, the tag name
used is the association role name.
 Association Parent. The association parent is the mapped class participanting in
the association definition that is responsible with exporting the foreign key values
to its children. For example in an invoice-invoiceLineItem relationship, the invoice
is the parent of the association and the invoiceId is the foreign key exported in
invoiceLineItem. Workbench will try to guess the parent of relationship based on
some heuristics, but user should review and set it accordingly. The parent setting is
used in saving object graphs. An object of the parent class represents the first
object to be saved in a relationship save. Its primary keys once known are exported
to associated children objects where they are defined as foreign keys.
 Cardinality. The association max cardinality. The possible values are one-to-one,
one-to-many, many-to-one, and many-to-many.
 Child Deletion Rule. This rule only applies to saveAll operation for an object
graph. When the parent of a relation is deleted, there are 3 deletion possible rules
for the associated objects reacheable in the object graph:
1. No Action. This is the default setting.
2. Software Handled Cascade Deletion. When this setting is selected, OVPL will
delete all instantiated children present in the current object graph when the
association’s parent is deleted.
M A P P I N G T O O L U S E R S ’ G U I D E
3. Database Handled Cascade Deletion. Use this rule when the database foreign
key definition behind this association has a similar rule. In this case OVPL
will keep object sate in synch with the database delete trigger action.
Objects deleted by the DB trigger will be marked as deleted.
 Identifiable Relationship. Used to map compositions. A relation is said to be
identifiable when the child object cannot exist without parent object – in database
terms, the foreign key cannot be null (usually FK is part of the PK). This setting is
used in handling object graphs saving order.
 Always Refresh Role. If true, OVPL goes to database for each get association
method call. If false, once the association was retrieved, and if the association role
is represented by a java attribute (“Generate Role Accessors” setting is true), the
previously retrieved value will be returned and no database access will be made
(user still have ways to retrieve/refresh association from db again if he really wants
it).
 Joined with Parent. If true, (prerequisite condition is that association cardinality is
one) the association can be retrieved in the same select statement with the parent.
Each time parent is selected, the associated object is also retrieved.
 Retrieve Subtypes each time possible. This setting is used to force a type-
subtype conversion each time possible. For example if an “Account” class has
subtypes, then person.getAccounts() association call will result in a collection of
Account subtype objects. It is recommended to leave this setting off, because user
has the choice to “subtype” the retrieved collection, only when and if he wants to.
 Generate Pair Association. If selected the reverse relationship will be created
when current association will be saved.
 Generate Role Accessors. This setting applies to java class generation. If set, the
java class will have a java attribute for each association. The attribute name will be
the association role name. If roles are not materialized by java attributes, object
graph saveAll operation is not possible.
 Generate Find Method. This setting applies to java class generation. If set, a
findByXXX method will be generated in the target class. If role accessors are not
generated, then persistent class become a pure “data access object”, no object
graphs operations are possible, roles are not represented by instance attributes –
associations are not represented by objects.
M A P P I N G T O O L U S E R S ’ G U I D E
Many-To-Many Association Mapping
This panel is used to configure many-to-many association mapping. If class
“A” has a one-to-many relationship with class “AB” that has many to one
relationship with a class B, then the many-to-many relationship from class “A”
to class “B” can be created. Class “AB” must be mapped prior to creating the
many-to-many association.
 Passing through Association class. This table will show all cardinality 1
associations having as source the target class for current (selected) association.
Each such association can be used to create a many-to-many association.
 Defined m-to-m Associations. This table holds the selected associations used to
create the many-to-many relationships from the table described above. In the
sample shown in the above screenshot, a many-to-many association was
configured from class BusinessEntity to the class BusinessEntity, passing
association class (table) B2BRelationship. The role name for the many-to-many
association will be “relatedBusinesses”.
DB Schema Explorer Panel
This panel is used to generate class mapping information from database tables
and to compare existing mapping information with current database schema.
M A P P I N G T O O L U S E R S ’ G U I D E
 Select New Tables. All tables that are not mapped to persistent classes are
selected.
 Map Selected Tables. All selected tables from left panel will be used to generate
class mapping. If the class mapping exists, it will be updated, otherwise a new one
will be created.
 Compare Selected. Mapping information is compared against table information;
detected differences are logged in Messages window.
 Update Map from Table Definition. Selected map is compared against selected
table and differences are used to update mapping information accordingly.
Model Validation Panel
Selected maps are validated for errors. The result is displayed on Messages
panel.
M A P P I N G T O O L U S E R S ’ G U I D E
Model Generation Panel
Selected maps are used to generate java classes.
 Add Changes. All maps that were modified since last save will be selected.
 Add All. All classes are generated.
M A P P I N G T O O L U S E R S ’ G U I D E
 Erase Output. If source folder differs from output folder (see settings panel) then
the output directory content can be deleted using this button.
Object Explorer Panel
This panel is a very useful tool for browsing object hierarchies, graphs or to
display any individual object from current database schema. With this toll new
objects can be created and existing ones modified. In order to make this tool
safe for production environments set the property
WORKBENCH_OBJECT_EDITABLE to false.
To edit the attribute values double click the value for the corresponding attribute value,
type in data and press enter to end editing mode.
The left panel displays all defined (mapped) associations. Click on a defined association
to instantiate its roles. Then click on a role to open an object editor for that persistent
object. With this tool becomes very easy to navigate all related objects of a given one.
 Clear Values. Clear all field values.
 From Object. Populate screen from object data.
 To Object. Populate object attributes from screen data.
 New Object. Instantiate a new object of the same class and populate screen
accordingly.
M A P P I N G T O O L U S E R S ’ G U I D E
 Retrieve. Retrieve a new object from database using the screen data entered in the
attribute values to build the where clause.
 Refresh. Read the object again from database and show data on screen.
 Save Tree. Save object graph. Save all modified objects that can be reached from
the current object by navigating instantiated relationships.
 Delete Tree. Delete object graph. Delete all objects that can be reached from the
current object by navigating instantiated relationships.
 Clone. Create a new object having the same attribute values as current one. Will
not save the object to database. Autoincrementors and discriminators will not be
cloned and will be instantiated once the user will choose to save object to database
 Delete. Delete current object from database.
 Close. Close current editor window and all children windows opened from current
one. Will not save objects to database.
P R O G R A M M E R S ’ G U I D E
ObjectView Persistency Layer
Programmers’ Guide
Introduction
his guide explains the ObjectViewPL persistency API. The sample mapping
application provided together with the framework library will be used in this
guide to illustrate the API usage. Before objects can be persisted using OVPL,
mappings must be defined correctly. For help using the Workbench to generate
mapping classes see the chapter 3 – Mapping Tool Users’ Guide.
T
The Sample Model
The pictured bellow sample class model will be used to exemplify ObjectViewPL
features. Let’s say we have a company that is selling services over Internet and we have
modeled the following java business classes:
 BusinessEntity. Defines a business partner or a business customer. It can be
represented by a Company or an individual (Person).
 Member. A Business Entity that has a valid subscription for services we provide.
 Account. Two types of accounts: ExternalAccount used by Members to pay for
the services our company provides, MemberAccount used to keep internal
accounting for members (balance owning, invoice history, default external account
used for automate debit,…). A Member has many MemberAccounts, one of them
defined as the default member account.
 AbstractExternalAccount. An abstract class – no persistent state – introduced
here mainly to show some mapping features.
Chapter
4
P R O G R A M M E R S ’ G U I D E
 B2bRelationship. Models the relationships between two business entities.
parentBusiness and relatedBusiness are the two possible roles - i.e. a person
working for a company can be modeled using parentBusiness role.
Account
- accountId : java.lang.Integer = null
- accountName : java.lang.String = null
- accountType : java.lang.String = null
- balanceAmt : double = 0
- ownerBeId : java.lang.Integer = null
ExternalAccount
- externalAccountId : java.lang.Integer = null
- accountValidityConfirmedB : boolean = false
- externalAccountType : java.lang.String = null
AbstractExternalAccount
+ AbstractExternalAccount ( )
BankAccount
- bankAccountAccountId : java.lang.Integer = null
- accountSnumber : java.lang.String = null
- bankSnumber : java.lang.String = null
- holderName : java.lang.String = null
- transitSnumber : java.lang.String = null
CreditCard
- creditCardAccountId : java.lang.Integer = null
- creditCardNumberRaw : byte = null
- creditCardType : int = 0
- expiryDate : java.sql.Date = null
- holderName : java.lang.String = null
Cheque
MemberAccount
- memberAccountId : java.lang.Integer = null
- defaultPaymentAccountId : java.lang.Integer = null
- memberId : java.lang.Integer = null
- paperBillAddressId : java.lang.Integer = null
- statementFrequencyType : java.lang.String = null
- defaultPaymentAccount
BusinessEntity
- beId : java.lang.Integer = null
- beType : java.lang.String = null
- notesString : java.lang.String = null
+ isPerson ( )
- businessEntity
Person
- personBeId : java.lang.Integer = null
- ageType : java.lang.String = null
- birthDate : java.sql.Date = null
- childrenNumber : int = 0
- firstName : java.lang.String = null
- genderType : java.lang.String = null
- lastName : java.lang.String = null
- maritalStatusType : java.lang.String = null
- socialSecuritySnumber : java.lang.String = null
- memo : java.lang.String = null
...
...
Company
- companyBeId : java.lang.Integer = null
- companyName : java.lang.String = null
- contactPersonBeId : java.lang.Integer = null
- totalRevenueType : java.lang.String = null
B2bRelationship
- beId : java.lang.Integer = null
- relatedBeId : java.lang.Integer = null
- relationshipStype : java.lang.String = null
- parentBusiness
- relatedBusiness
Member
- memberId : java.lang.Integer = null
- businessEntityId : java.lang.Integer = null
- defaultMemberAccountId : java.lang.Integer = null
- lastVisitDatetime : java.sql.Timestamp = null
- loginPassword : java.lang.String = null
- loginString : java.lang.String = null
- member
- businessEntity
- defaultMemberAccount
- member
Mapping Example - Class Diagram
P R O G R A M M E R S ’ G U I D E
Mapping Example - Database Diagram
P R O G R A M M E R S ’ G U I D E
Workbench settings
Here are the projects properties and run configurations created for eclipse IDE I have
used to run the samples described in the chapters bellow.
Bellow please find the settings used to configure ObjectViewMappingsDemo. The
libraries used reflect my environment:
P R O G R A M M E R S ’ G U I D E
Persistent Classes
ersistent classes are generated using the OVPL mapping tool. See previous
chapter for the mapping rules and tool usage screenshots and the section
referring to ObjectView properties. Let’s look at a generated class:Ppackage com.objectview.examples.domain;
import com.objectview.jdb.*; //===ObjectView generated===
import com.objectview.util.*; //===ObjectView generated===
import java.sql.*; //===ObjectView generated===
import java.util.*; //===ObjectView generated===
public class B2bRelationship extends com.objectview.jdb.JDBPersistentObject //===ObjectView generated===
{ //===ObjectView generated===
private java.lang.Integer beId=null;//===ObjectView generated===
private java.lang.Integer relatedBeId=null;//===ObjectView generated===
private java.lang.String relationshipStype=null;//===ObjectView generated===
public static final String FLD_BE_ID="BE_ID";//===ObjectView generated===
public static final String ATTR_beId="beId";//===ObjectView generated===
public static final String FLD_RELATED_BE_ID="RELATED_BE_ID";//===ObjectView generated===
public static final String ATTR_relatedBeId="relatedBeId";//===ObjectView generated===
public static final String FLD_RELATIONSHIP_STYPE="RELATIONSHIP_STYPE";//===ObjectView
generated===
public static final String ATTR_relationshipStype="relationshipStype";//===ObjectView generated===
private com.objectview.examples.domain.BusinessEntity parentBusiness=null;//===ObjectView
generated===
private com.objectview.examples.domain.BusinessEntity relatedBusiness=null;//===ObjectView
generated===
//===ObjectView generated begin===
/**
* Persistent Attribute: JDBAttributeMap { beId >> BE_ID }
* Primary Key.
* Not nullable db value
* @showas hidden
* @objectview:method.id 10.1.getBeId
* @return java.lang.Integer
*/
public java.lang.Integer getBeId () {
// user.code.begin {1}.10.1.getBeId
// user.code.end {1}.10.1.getBeId
return beId;
P R O G R A M M E R S ’ G U I D E
} //===ObjectView generated end===
…..
//===ObjectView generated begin===
/**
* Class method for retrieving all objects of this type based on a custom sql
* it will try to instantiate all objects based on the result set comming for the sql sent
* @objectview:method.id 26.2.retrieve
* @showas hidden
*/
public static java.util.Vector retrieveAllUsingSQL ( JDBSession session, String sqlString ) throws SQLException,
RollbackException, ObjectAccessException {
java.util.Vector collection = JDBPersistentObject.retrieveAllUsingSQL
( "com.objectview.examples.domain.B2bRelationship", session, sqlString ) ;
// user.code.begin {1}.26.2.retrieve
// user.code.end {1}.26.2.retrieve
return collection;
} //===ObjectView generated end===
}
To make possible further changes and code to be added to generated classes, each line
or code block generated automatically by the mapping tool is being marked with a
special comment. Lines are marked with the comment //===ObjectView generated===
blocks are captured between //===ObjectView generated begin=== and
//===ObjectView generated end===.
You may add any imports, fields, methods, inner classes as desired. You may also
change part of the method signature by adding new Exceptions thrown and you may
add new interfaces to the implements class definition.
If extra code needs to be added inside generated methods - in order to be preserved
following next class generation operation - it must be added between // user code begin
and // user code end comments.
JavaDoc comments added for each attribute will also be preserved at next class source
generation – this because some UML tools (i.e. TogetherJ, Rational XDE, etc) will add
their own comments to java source files to keep java source and model in synch.
In the code shown bellow one can see the user added code in blue color:
package com.objectview.examples.domain;
import com.objectview.jdb.*; //===ObjectView generated===
import com.objectview.util.*; //===ObjectView generated===
import java.sql.*; //===ObjectView generated===
import java.util.*; //===ObjectView generated===
import mypackage;
public class B2bRelationship extends com.objectview.jdb.JDBPersistentObject //===ObjectView generated===
implements MyInterface
{ //===ObjectView generated===
/**
ID 10000101
**/
private java.lang.Integer beId=null;//===ObjectView generated===
private int myAttribute;
private java.lang.Integer relatedBeId=null;//===ObjectView generated===
private java.lang.String relationshipStype=null;//===ObjectView generated===
public static final String FLD_BE_ID="BE_ID";//===ObjectView generated===
public static final String ATTR_beId="beId";//===ObjectView generated===
public static final String FLD_RELATED_BE_ID="RELATED_BE_ID";//===ObjectView generated===
P R O G R A M M E R S ’ G U I D E
public static final String ATTR_relatedBeId="relatedBeId";//===ObjectView generated===
public static final String FLD_RELATIONSHIP_STYPE="RELATIONSHIP_STYPE";//===ObjectView
generated===
public static final String ATTR_relationshipStype="relationshipStype";//===ObjectView generated===
private com.objectview.examples.domain.BusinessEntity parentBusiness=null;//===ObjectView
generated===
private com.objectview.examples.domain.BusinessEntity relatedBusiness=null;//===ObjectView
generated===
//===ObjectView generated begin===
/**
* Persistent Attribute: JDBAttributeMap { beId >> BE_ID }
* Primary Key.
* Not nullable db value
* @showas hidden
* @objectview:method.id 10.1.getBeId
* @return java.lang.Integer
*/
public java.lang.Integer getBeId () {
// user.code.begin {1}.10.1.getBeId
System.out.println(“I’ve been here”);
// user.code.end {1}.10.1.getBeId
return beId;
} //===ObjectView generated end===
…..
private void myMethod() {
// do something
}
//===ObjectView generated begin===
/**
* Class method for retrieving all objects of this type based on a custom sql
* it will try to instantiate all objects based on the result set comming for the sql sent
* @objectview:method.id 26.2.retrieve
* @showas hidden
*/
public static java.util.Vector retrieveAllUsingSQL ( JDBSession session, String sqlString ) throws SQLException,
RollbackException, ObjectAccessException , MyException{
java.util.Vector collection = JDBPersistentObject.retrieveAllUsingSQL
( "com.objectview.examples.domain.B2bRelationship", session, sqlString ) ;
// user.code.begin {1}.26.2.retrieve
throw new MyException(“No worries”);
// user.code.end {1}.26.2.retrieve
return collection;
} //===ObjectView generated end===
}
Database Connection
atabase connections are wrapped within the JDBSession class. The
JDBSession class responsibilities are: opening and closing a
java.sql.Connection, commit control, instance cacheing, connection pooling.
There are 2 ways to create a database connection using JDBSession:
D
 Let ObjectViewPL obtain a java.sql.Connection.
 Passing a java.sql.Connection object to JDBSession constructor.
P R O G R A M M E R S ’ G U I D E
Let ObjectView obtain a java.sql.Connection
This is the default method and it uses the objectview.properties settings to obtain the
database connection. The method used in this case is JDBSystem.acquireConnection() with
no other parameters.
There are mainly two ways of configuring ObjectViewPL properties to obtain a
java.sql.Connection:
1. Obtain a connection using java.sql.DriverManager. The configured properties
in this case are:
• DB_CONNECTION_POOL_USE_EXTERNAL_POOL=false
• JDB_JDBC_DRIVER
• DB_CONNECTION_URL
• DB_CONNECTION_USER_ID
• DB_CONNECTION_PASSWORD
2. Obtain a connection from and external pool using datasource interfaces. In
this case the necessary properties that needs to be configured are:
• DB_CONNECTION_POOL_USE_EXTERNAL_POOL=true
• INITIAL_CONTEXT_FACTORY
• PROVIDER_URL
• SECURITY_PRINCIPAL
• SECURITY_CREDENTIALS
• DATA_SOURCE_JNDI_NAME
After properties are configured, the default method to acquire a session is
JDBSystem.acquireConnection(), as the following code fragment illustrates:
…..
JDBSession session = null;
try {
session = JDBSystem.acquireConnection();
Hashtable where = new Hashtable(3);
where.put(Member.ATTR_loginString, "login1");
try {
Vector v = Member.retrieveAll(session, where);
for (Iterator iter = v.iterator(); iter.hasNext();) {
Member element = (Member) iter.next();
}
} catch (RollbackException e1) {
e1.printStackTrace();
P R O G R A M M E R S ’ G U I D E
} catch (ObjectAccessException e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
} catch (ObjectPoolException e) {
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
Passing a java.sql.Connection to ObjectViewPL
This method is used to create a JDBSession object after we have obtained a
java.sql.Connection object (wrap an existing java.sql.Connection). The connection can
be obtained from an external datasource (i.e. owned by an EJB container) or using the
jdbc API. This method of connecting ObjectViewPL is used to facilitate working with
different data sources. For example read an Excell file and save its content in a
RDBMS. The method used to connect using an existing java.sql.Connection is
JDBSystem.acquireConnection(connection, isExternalMonitor). If isExternalMonitor parameter is
true, this tells ObjectViewPL that transactions are managed externally and any calls to
JDBSession.begin/commitTransaction() are ignored.
External Transaction Monitor Integration
User can configure ObjectviewPL to connect to an external data source and obtain
database connections from and external connection pool or obtain such connections
outside ObjectViewPL and let persistent mechanism know that transactions are
managed outside.
ObjectViewPL permits integration with and external transaction
monitor thus allowing the user to embrace all the benefits from
such integration.
Important: if a connection is obtained from an external transaction monitor and
managed externally, then user must let ObjectViewPL be aware of this fact by using
JDBSession.acquireConnection(java.sql.Connection conn, boolean externalTransactionMonitor)
method and setting the second parameter to true.
public class ConnectionDemo {

P R O G R A M M E R S ’ G U I D E
public static void main(String[] args) {
JDBSession jdbSession = null;
try {
Connection conn = getConnectionFromExternalPool();
// obtain a JDBSession object from extrenal pool, let ObjectViewPL know
// the connection was obatained from an external pool in order to let transactions
// be managed by the application server's transaction monitor.
jdbSession = JDBSystem.acquireConnection( conn, true);
System.out.println(jdbSession);
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ObjectPoolException e1) {
e1.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(jdbSession);
} catch (RollbackUncommitedSession e2) {
e2.printStackTrace();
} catch (SQLException e2) {
e2.printStackTrace();
}
}
}
/**
* This method show how to obtain a Connection from an external datasource.
* I have used the weblogic server to configure a connection pool for my local oracle XE database
* and set the datasource jndi name to <com.objectview.demoDataSource>.
*
* The connection factory, provider url and jndi name can be set in objectview.properties file
* and if the DB_CONNECTION_POOL_USE_EXTERNAL_POOL property is set to true then the
* java.sql.Connection will always be obtained from the external pool
* when using the method JDBSystem.acquireConnection().
*
* @return
* @throws NamingException
* @throws SQLException
*/
private static java.sql.Connection getConnectionFromExternalPool() throws NamingException,
SQLException {
Context ctx = null;
Hashtable ht = new Hashtable();
ht.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
ht.put(javax.naming.Context.PROVIDER_URL,
"t3://localhost:7001");
ctx = new javax.naming.InitialContext(ht);
DataSource ds = (javax.sql.DataSource) ctx.lookup ("com.objectview.demoDataSource");
java.sql.Connection conn = ds.getConnection();
P R O G R A M M E R S ’ G U I D E
return conn;
}
}
Retrieving and Persisting Objects
bjectviewPL provides methods for storing, deleting and retrieving objects
from persistent storage for all mapped types. Mappings are created using
the OVPL mapping tool. See previous chapter for the mapping rules and
tool usage screenshots and the section referring to ObjectView properties. From
database point of view ObjectviewPL methods translate in four types of requests:
selects (joins), inserts, updates and deletes. From object point of view there are two
types of methods: save and retrieve.
O
Retrieving objects
To retrieve persistent state ObjectView creates Java objects and populates them with
database fields based on mapping configuration.
Retrieving individual objects
When primary keys are used, ObjectViewPL will instantiate one object based on
primary key value. The generated methods to retrieve objects based on primary key
value are:
 retrieve(Object pkValue)
 retrieve(Hastable pkValueDict)
 findByPrimaryKey(Object pkValue1, Object pkValue2, …)
 retrieveAll(Hashtable whereDict) if whereDict consists of primary keys.
If primary keys consists of more than one key, only retrieve(Hastable pkValueDict)
method will be generated and a Hashtable consisting of fieldName-objectValue pairs
must be created and passed as parameter. However, if finders are generated (see
mapping Workbench application guide) then a findByPrimaryKey() method will be
generated having one parameter for each primary key.
If a Hashtable is to be build and send as method parameter, then the keys represent the
java attribute names and the values the corresponding attribute value.
Retrieving object collections
To retrieve object collections use the retrieveAll() methods. In its most generic form
this method signature is :
P R O G R A M M E R S ’ G U I D E
 retrieveAll ( JDBSession session, Hashtable whereDict, String orderBy, String
customWhereClause ).
 retrieveAllUsingSQL ( JDBSession session, String sqlString )
The whereDict parameter is a Hashtable having the keys as the java attribute names and
the values the corresponding values to be used in the where clause, orderBy parameter
represents the order by clause and will be appended to the generated SQL statement,
customWhereClause represents the additional where clause to be added to the generated
one. It is recommended to use ANSI SQL format for any supply SQL fragment for
portability among different databases.
If the whole SQL is given then the objects are instantiated from result set matching
attribute names. If objects represent a type-subtype mapping using different tables,
then a join should be supplied to involve all tables. If helper tables where used in
mapping the candidate java class, then the join should include any helper table
mapped.
To see some java code examples of retrieving objects look at the java examples
supplied or included in this documentation bellow Saving Objects paragraph.
Saving Objects
The method used to change object’s persistent state or status is the save() method. Call
this method on any persistent object (mapped with ObjectViewPL) and
ObjectViewPL will translate the call to the right database operation.
Insert
To create a new objects use null or customized constructor, set the attributes to desired
values and call save method against that object. If set so in mapping, autoincrementors
and primary keys will be retrieved prior or after the save operation and will be set in the
corresponding object’s attribute.
Here is a code snippet to illustrate a database insert:
public static void insertDemo() {
JDBSession session = null;
try {
session = JDBSystem.acquireConnection();
// create a new person. Do no set incrementors or discriminators since they
// are handled by ObjectViewPL.
Person person = new Person();
person.setFirstName("Donald");
person.setLastName("Duck");
person.setGenderType("M");
person.setMaritalStatusType("M");
person.setSocialSecuritySnumber("1112222");
person.save(session);
P R O G R A M M E R S ’ G U I D E
testPersonId=person.getPersonBeId();
// Person is persisted and PK and discriminator values are set.
System.out.println(person.toXml(false));
} catch (ObjectPoolException e) {
e.printStackTrace();
} catch (RollbackException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ConcurrencyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ObjectAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Do not set any autoincrementors or discriminators directly if a
policy to obtain a value for such fields was defined in mapping.
ObjectViewPL will retrieve and set these values. However if IDs
are set they will be used (at user request) instead and ObjectViewPL
will not try to obtain new ones. The special fields user does not
need to care about setting their values are:
 Primary keys
 Autoincrementors: sequences, identity fields, GUIDs, etc.
 Update controllers
 Foreign keys
 Type-subtype discriminators (type-subtype filtering)
 Formulas and read-only fields.
Update
To update an object first you need to retrieve that object from database – so, for the
next save operation to be an update request, object must be retrieved from database
first. Then modify any persistent attributes and call the save method to make the
changes persistent.

P R O G R A M M E R S ’ G U I D E
public static void updateDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// retrieve a person from database. We will use a primary key to retrieve one
// object and not a collection.
Person person = (Person) Person.retrieve(session, testPersonId);
person.setFirstName("Duffy");
person.setMemo("Donald Duck incognito");
person.save(session);
System.out.println(person.toXml(false));
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Only objects that have been modified from last retrieve operation
will be saved to database. ObjectViewPL keeps the last committed
state of an objects and in order to minimize database I/O by
issuing unnecessary statements will check current state against
committed state.
Delete
Like update, to delete an object must first retrieve that object from database (only
persistent objects can be deleted). There are two methods to do a delete:
1. Call the delete method
2. Mark the object for deletion an call the save method
public static void deleteDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// retrieve a person from database. We will use a primary

P R O G R A M M E R S ’ G U I D E
// key to retrieve one object and not a collection.
Person person = (Person) Person.retrieve(session, testPersonId);
person.delete(session);
// person object is not persistent
System.out.println("Persistent status:" + person.isPersistent());
System.out.println(person.toXml(false));
// the next save() operation against person object will be an insert.
// to obtain a new id we must set null to the PersonBeId field, otherwise
// the old Id will bereused.
person.setPersonBeId(null); // !! if this not set, old id will be used.
person.save(session);
System.out.println("Persistent status:" + person.isPersistent());
System.out.println("Person Id:" + person.getPersonBeId());
// now mark object for deletion to be deleted by next save() operation
person.markForDeletion();
person.save(session);
System.out.println("Persistent status:" + person.isPersistent());
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Saving Object Graphs
From database point of view saving an object graph consists of inserts, updates, deletes
operations issued in one transaction for an entire object graph. From java point of
view an object graph consists of all objects in VM memory that can be reached
following mapped relationships starting from a given object.
The method used for this operation is saveAll method from JDBPersistentObject class.
This method saves an object and all its instantiated relationships to the database in the
same db transaction. Only related objects that have been modified since the last
retrieve operation will be saved to database.
The order of the performed operations is:
P R O G R A M M E R S ’ G U I D E
 -Delete objects marked for deletion and cascade deletes (if configured so in
mapping) dependents. Remove object references for deleted objects for the
objects for which markForDeletionAndRemoveReferences() method was called
before issuing saveAll().
 -Insert new objects and modify existing ones.
 -Export keys to children (dependents in relationships) after saving.
 -Import keys from parents after saving.
Recursive relationships are handled in the following way:
If 2 classes have 2 relationships defined, on different keys, and each association have a different parent,
then the one that will be saved first is the one configured as identifiable when association was mapped in
ObjectView Workbench. The parent object will be saved twice, once to export its keys and second time
with the imported keys from recursive relation.
If you need to add more behaviour than the one described here to this method, then
subclass saveAll( JDBSession session) method to add your custom code and then call
super.saveAll( session) method to have all happening in one transaction. Just make
sure all methods called inside saveAll(session) are called with the same session object to
have all database operations handled in the same transaction context.
To remove references of deleted objects in the context of an object graph, call the
method markForDeletionAndRemoveReferences() and then call saveAll();
public static void saveAllDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// retrieve a person from database.
Person person = (Person) Person.retrieve(session, new Integer(2));
// make some changes to this object
person.setFirstName("Duffy");
person.setLastName("Duck");
// retrieve associated accounts
for (Iterator iter = person.getAccountsSubType(session).iterator(); iter.hasNext();) {
Account account = (Account) iter.next();
if (account.isExternalAccount()) {
if ( ((ExternalAccount)account).isCreditCard()) {
// this was added in a previous run of this method
account.markForDeletionAndRemoveReferences();
} else {
account.setAccountName("Duffy Duck");
}
}
}
// add another account (the previous one we marked for deletion)
P R O G R A M M E R S ’ G U I D E
CreditCard cc = new CreditCard();
cc.setAccountName("Duffy's Mastercard");
cc.setHolderName("Duffy Duck");
cc.setCreditCardType(1);
cc.setExpiryDate(new Date(System.currentTimeMillis()));
cc.setBalanceAmt(100);
person.addToAccounts(cc, session);
// persist all changes (insert, update, delete)
person.saveAll(session);
// print graph in xml format, including relationships
// We should find only 2 accounts. One was modified, one deleted, one added.
System.out.println(person.toXml(true));
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
SaveAll with check
Same as saveAll method but ObjectViewPL will check the persistent state against DB
for each object to be saved. If object is found in database then an update will be issued,
otherwise an insert.
This method is useful for saving object graphs from one database to another one, or
for XML imports, or in any case when object was not retrieved from the same
database in which is to be saved but they might exist there.
This method makes used of the checkPersistentStatus() method and calls it prior to saving
the object graph.
public static void importDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// retrieve a person from database.
Person person = (Person) Person.retrieve(session, new Integer(2));
// make some changes to this object
person.setFirstName("Donald");
person.setLastName("Duck");
P R O G R A M M E R S ’ G U I D E
person.setMemo("endagered species"); // this will go to the help table
// retrieve associated accounts
person.getAccountsSubType(session);
// export to xml
String xml = person.toXml(true);
// convert xml back to objects
Vector objs = Person.fromXml(xml);
JDBPersistentObject importedObj = (JDBPersistentObject) objs.firstElement();
// now import this back to DB
// use the saveWithCheck option to perform updates of existing objects
importedObj.saveAllWithCheck(session);
System.out.println(importedObj.toXml(true));
// now get another set of objects from the same xml String
Vector objs2= Person.fromXml(xml);
Person importedDuck2 = (Person) objs2.firstElement();
importedDuck2.setFirstName("Donald The Second");
importedDuck2.setLastName("Cloned Duck");
// if we save this object graph without the check option we get brand new
// objects in database,because the next save operation
// will results in inserts since they represent new objects that were
// build in memory and not retrieved directly from database.
// But first, we must make the PK's null because by default if PKs are set
// by the user ObjectViewPL will not try to obtain new ones.
// ObjectViewPL provides a method for this purpose only.
// resetAutoincrementors(boolean includeRelations);
importedDuck2.resetAutoincrementors(true);
// now we can get the new object graph insert
importedDuck2.saveAll(session);
System.out.println(importedDuck2.toXml(true));
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
P R O G R A M M E R S ’ G U I D E
ObjectViewPL provides methods to handle object graphs. Object
graphs combined with xml serialization can be used to in export-
import operations. ObjectViewPL can handle recursive
associations. All primary and foreign keys are handled internally and
transparent for the user.
Setting and Retrieving Relationships
Relationships are set at the object level and are persisted calling the save or saveAll
operations.
At the object level relationships are set/reset using the provided (generated) setters and
getters. When a relationship between to persistent objects is set the foreign keys are
migrated automatically – if objects are new, they will migrate in the save operation.
There is no need for user to manage object ids (primary and foreign keys).
 To add an object to an existing set of related objects, use the addToxxx()
generated methods. This method will not persist any changed made. To make
the changed persistent user needs to call save() operation for each object that
imported the value for its foreign key from a parent object. A simpler way is to
call saveAll on parent graph.
 To delete a related object use the deleteXxx() generated method on the parent
object. This method will delete the related object from database and from
object referenced roles collection.
 To instantiate a relationships call the generated relationship getter.
 To retrieve roles as individual collections (not set in any object context) use the
finders generated methods.
Relations can be obtain from database together with the parent object (in the same
select/join statement) to speed up access and minimize I/O if configured so in the
mapping process.
public static void relationshipsDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// retrieve a person from database.
Person person = (Person) Person.retrieve(session, new Integer(2));
// now add a new account
CreditCard newCC = new CreditCard();
newCC.setCreditCardType(1);
newCC.setExpiryDate(new Date(System.currentTimeMillis()));
newCC.setHolderName(person.getFirstName()+" " + person.getLastName());
// retrieve existing accounts and add this new one to relationship collection

P R O G R A M M E R S ’ G U I D E
// notice that because accounts relationship was mapped as to retrieve subtypes
// each time, the accounts subtypes are retrieved in the accounts collection.
person.addToAccounts(newCC,session);
// persist changes. this will insert the new account in the database
// and will set the foreign key ownerBeId
person.saveAll(session);
// if account would have been a persistent object already
CreditCard newCC2 = new CreditCard();
newCC.setCreditCardType(2);
newCC2.setExpiryDate(new Date(System.currentTimeMillis()));
newCC2.setHolderName(person.getFirstName()+" " + person.getLastName() + " VISA");
// save account first
newCC2.save(session);
// set relationship
person.addToAccounts(newCC2, session);
// save account back in database to persist the relation
//(store the ownerBeId foreign key)
newCC2.save(session);
// show person with the new added credit cards
System.out.println(person.toXml(true));
// now delete the two credit cards added previously
person.deleteAccount(newCC, session);
person.deleteAccount(newCC2, session);
// show person without the above credit cards
System.out.println(person.toXml(true));
// call the relation getter with a custom where clause
// Notice that because the where clause changed,
// relation will be instantiated again
person.getAccounts(session,null,Account.FLD_BALANCE_AMT+"=100" );
System.out.println(person.toXml(true));
// to force retrieving the roles from database again, reset the related roles to null
person.setAccounts(null);
person.getAccounts(session); // will retrieve accounts from db again.
System.out.println(person.toXml(true));
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
P R O G R A M M E R S ’ G U I D E
}
Aside of the where clause and order by clause set in mapping that has effect for all
retrieve operations involving that particular relation, user can set (or add) a different
where clause and order by clause to have effect on current retrieve operation using
relationships getters like: person.getAccounts ( JDBSession aSession, String customOrderBy,
String customWhere). Because relations are cached in the role instance variable, each time
the relationship getter is called with a different where clause, ObjectViewPL will
refresh the relation from database.
Relationships can be retrieved using the generated finders (see Mapping Tool User
Guide) case in which one findBy… method will be generated for each relationship.
However, calling the finders will not instantiate the role attributes (relation will not be
cached nor set at the object level) and object graphs will not be instantiated nor can
they be used. User is free to choose which method is best to use (instantiated roles or
finders) based on application constraints such as memory trace, serialization, and so
on.
Many to many relationships
ObjectViewPL maps this type of association using an association class. The generated
association class is treated like any other persistent class, except there are additional
methods generated in the main classes to set and get the many-to-many relationships.
The association class may have additional attributes to describe the business state of
the association itself. In this case association class is a business class and the many-to-
many relationship in discussion will be set and get through the association class
explicitly.
public static void manyToManyDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
Company company = (Company) Company.findByPrimaryKey(session, new Integer(7));
// we have defined a many-to-many relationship to the same class. This is
// a special case of relationship, oftere referred as circular relationship.
// We would like to show that saveAll handles correctly such object graph.
// To make things even more complicated, many-to-many relationship is
// defined at the supertype level.
// The roles can be Companies or Persons, both subtypes of BusinessEntity
BusinessEntity be = (BusinessEntity) company;
// get the many to many relationships
Vector relatedBes = be.getRelatedBusinesses(session);
for (Iterator iter = relatedBes.iterator(); iter.hasNext();) {
P R O G R A M M E R S ’ G U I D E
BusinessEntity relatedBe = (BusinessEntity) iter.next();
}
// add another related business
Company newComp = new Company();
newComp.setCompanyName("ABC French Delicatessen");
newComp.setNotesString("catering");
relatedBes.add(newComp);
be.setRelatedBusinesses(session,relatedBes); // must be called
be.saveAll(session);
System.out.println(company.toXml(true));
// now remove the just added company to the related businesses
// this method will remove the b2b relationship from both
// database and object graph
be.deleteRelatedBusiness(newComp, session);
System.out.println(company.toXml(true));
// also remove the new added company
newComp.delete(session);
// another way of setting a many to many realationships is
// working directly with the association class
// This method will be used if association class has
// also a business meaning - i.e. has attributes to describe
// the relationship. In our case such an attribute is relationshipType
// lets create a new business entity,
// lets say a Contract mediator person
Person mediator = new Person();
mediator.setFirstName("Joe");
mediator.setLastName("Mediator");
mediator.setGenderType("M");
mediator.setMaritalStatusType("S");
// create a new association class
B2bRelationship b2bRel = new B2bRelationship();
b2bRel.setRelatedBusiness((BusinessEntity)mediator);
// set association attribute
b2bRel.setRelationshipStype("mediator");
be.addToB2bRelationships(b2bRel, session);
// of course objects can be saved individually, but saveAll is making
// save operation easier.
be.saveAll(session);
System.out.println(company.toXml(true));
// now delete the just added person (mediator) relationship
be.deleteRelatedBusiness(mediator, session);
System.out.println(company.toXml(true));
// also delete the new added Person (mediator)
mediator.delete(session);
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
P R O G R A M M E R S ’ G U I D E
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Types and Subtypes. Cast down policies.
In the case objects involved in relationships represent hierarchies mapped as java
inheritance, user has a choice of instantiating the supertype or the subtype for each
such object. Why would you want to instantiate a superType and not the subtype? The
answer relies on performance reasons. Lets say that in order to get to a business object
C you need to pass object B in a relationship chain like A->B->C. Lets also say that B
is a type-subtype hierarchy mapped to different tables. In this case it would not be
necessary to retrieve the whole B type-subtype hierarchy just to retrieve the foreign key
needing to retrieve C object. B in this case will only serve as a pas-by step and user
might consider useful to avoid retrieving the B hierarchy tree.
However if user chose to map the relationship as always retrieving subtype (see
Workbench mapping application) then subtypes will always be retrieved.
Once the user retrieved subtypes he can always retrieve the whole object subtype
hierarchy is he/she wishes so by calling castDownToSubtype() methods.
A subtype version of the association role getter is also generated for the case when
related object is mapped as a type-subtype hierarchy.
Retrieving relationships using customized join requests
Another way of minimizing database i/o and improving performances in critical
situations is to retrieve associations using a custom join. The method to use in this case
is retrieveJoinedRoles ( JoinRequest[] joinRequests ) and calling the method will result in only
one select statement issued and processed for all objects retrieved.
The joinRequests parameter is a Vector with JoinRequest objects. (See the JoinRequest
class comment for usage description).
Because it uses only one Select statement consisting of multiple table join, this method
has some limitations:
P R O G R A M M E R S ’ G U I D E
 Cannot have more than one one-to-many relationship in the request
 Only first relation in the request is allowed to be a one-to-many relationship
 Can only have one subtype castdown in the request.
Examples of an accepted join request:
A (*) B (1)C(1)D(subtypes)
Example of a rejected join requests:
A  (*) B (*)C -more that one one-to-many relations
A  B (*)C D -one-to-many relation not the first one in request
A  D(subtypes)  E(subtypes) -more than one subtype requested
RetrieveJoinedRoles() method stores the retrieved associated objects in each parent object
as relationship roles. This means that after this method completes, results are cached in
role variables - so for example after executing this method for a join configuration: A
--> (*) B -->(1)C --- (1)D(subtypes), A.getBs() will return the B objects without
going to database, as well C.getDsSubtype().
Java code example:
Company company2 = (Company) Company.findByPrimaryKey(session, new Integer(7));
BusinessEntity be2 = (BusinessEntity) company2;
// JoinRequest( String roleName,
// String customOrderBy,
// String customWhereClause ,
// boolean castDown ) {
JoinRequest[] jr2 = new com.objectview.jdb.JoinRequest[] {
new JoinRequest("b2bRelationships",
B2bRelationship.FLD_RELATIONSHIP_STYPE+ " desc",null, false ),
new JoinRequest("relatedBusiness", null,null, true ),
new JoinRequest("member", null,null, false ),
new JoinRequest("defaultMemberAccount", null,null, false ),
new JoinRequest("defaultPaymentAccount", null,null, false )
};
// retrieve all roles described above in one sql statement
be2.retrieveJoinedRoles(jr2, session);
// lets see what roles were retrieved
System.out.println(company2.toXml(true));
The example above will produce the following SQL:
P R O G R A M M E R S ’ G U I D E
SELECT
B2B_RELATIONSHIP1.BE_ID,B2B_RELATIONSHIP1.RELATED_BE_ID,
B2B_RELATIONSHIP1.RELATIONSHIP_STYPE,BUSINESS_ENTITY2.BE_ID,
BUSINESS_ENTITY2.BE_TYPE,BUSINESS_ENTITY2.NOTES_STRING,
BUSINESS_ENTITY2.ROW_UPDATE_NUMBER,
PERSON1.PERSON_BE_ID,PERSON1.AGE_TYPE,PERSON1.BIRTH_DATE,PERSON1.CHILDREN_NUMBER,
PERSON1.FIRST_NAME,PERSON1.GENDER_TYPE,PERSON1.LAST_NAME,
PERSON1.MARITAL_STATUS_TYPE,PERSON1.SOCIAL_SECURITY_SNUMBER,
EX1_PERSON_MEMO1.PERSON_BE_ID,EX1_PERSON_MEMO1.MEMO,
MEMBER1.MEMBER_ID,MEMBER1.BUSINESS_ENTITY_ID,MEMBER1.DEFAULT_MEMBER_ACCOUNT_ID,
MEMBER1.LAST_VISIT_DATETIME,MEMBER1.LOGIN_PASSWORD,MEMBER1.LOGIN_STRING,
BUSINESS_ENTITY3.BE_ID,BUSINESS_ENTITY3.BE_TYPE,BUSINESS_ENTITY3.NOTES_STRING,
BUSINESS_ENTITY3.ROW_UPDATE_NUMBER,ACCOUNT1.ACCOUNT_ID,ACCOUNT1.ACCOUNT_NAME,
ACCOUNT1.ACCOUNT_TYPE,ACCOUNT1.BALANCE_AMT,
ACCOUNT1.LAST_UPDATE_DATETIME,ACCOUNT1.OWNER_BE_ID,ACCOUNT1.ROW_UPDATE_NUMBER,
MEMBER_ACCOUNT1.MEMBER_ACCOUNT_ID,MEMBER_ACCOUNT1.DEFAULT_PAYMENT_ACCOUNT_ID,
MEMBER_ACCOUNT1.MEMBER_ID,MEMBER_ACCOUNT1.PAPER_BILL_ADDRESS_ID,
MEMBER_ACCOUNT1.STATEMENT_FREQUENCY_TYPE,ACCOUNT2.ACCOUNT_ID,
ACCOUNT2.ACCOUNT_NAME,ACCOUNT2.ACCOUNT_TYPE,ACCOUNT2.BALANCE_AMT,
ACCOUNT2.LAST_UPDATE_DATETIME,ACCOUNT2.OWNER_BE_ID,ACCOUNT2.ROW_UPDATE_NUMBER,
EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_ID,
EXTERNAL_ACCOUNT1.ACCOUNT_VALIDITY_CONFIRMED_B,
EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_TYPE,EXTERNAL_ACCOUNT1.LAST_UPDATE_DATETIME,
EXTERNAL_ACCOUNT1.ROW_UPDATE_NUMBER
FROM BUSINESS_ENTITY BUSINESS_ENTITY1,
COMPANY COMPANY1,
B2B_RELATIONSHIP B2B_RELATIONSHIP1,
BUSINESS_ENTITY BUSINESS_ENTITY2,
PERSON PERSON1,
EX1_PERSON_MEMO EX1_PERSON_MEMO1,
MEMBER MEMBER1,
BUSINESS_ENTITY BUSINESS_ENTITY3,
ACCOUNT ACCOUNT1,
MEMBER_ACCOUNT MEMBER_ACCOUNT1,
ACCOUNT ACCOUNT2,
EXTERNAL_ACCOUNT EXTERNAL_ACCOUNT1
WHERE COMPANY1.COMPANY_BE_ID=? AND
COMPANY1.COMPANY_BE_ID=BUSINESS_ENTITY1.BE_ID AND
BUSINESS_ENTITY1.BE_ID=B2B_RELATIONSHIP1.BE_ID AND
PERSON1.PERSON_BE_ID=BUSINESS_ENTITY2.BE_ID AND
PERSON1.PERSON_BE_ID=EX1_PERSON_MEMO1.PERSON_BE_ID AND
B2B_RELATIONSHIP1.RELATED_BE_ID=BUSINESS_ENTITY2.BE_I AND
BUSINESS_ENTITY2.BE_TYPE=? AND
BUSINESS_ENTITY3.BE_ID=MEMBER1.BUSINESS_ENTITY_ID AND
MEMBER1.BUSINESS_ENTITY_ID(+)=BUSINESS_ENTITY3.BE_ID AND
MEMBER_ACCOUNT1.MEMBER_ACCOUNT_ID=ACCOUNT1.ACCOUNT_ID AND
MEMBER1.DEFAULT_MEMBER_ACCOUNT_ID=MEMBER_ACCOUNT1.MEMBER_ACCOUNT_ID AND
EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_ID=ACCOUNT2.ACCOUNT_ID AND
MEMBER_ACCOUNT1.DEFAULT_PAYMENT_ACCOUNT_ID=EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_ID
ORDER BY RELATIONSHIP_STYPE desc
FOR THE PARAMETER VALUES :’P’ ,7
Object Rollback and Refresh. Dirty and Persistent
Statuses.
bjectviewPL provides methods for restoring the persisted state from
memory or from database. To restore the persisted state ObjectViewPL
stores in memory the current persistent state in an internal variable called
commitDict.
O
P R O G R A M M E R S ’ G U I D E
The last persisted object state can be retrieved calling JDBPersistentObject.getCommitDict().
Dirty status
To avoid unnecessary database calls an object is stored in database only if it was
modified since last database call. Dirty status is updated in each set method. To force
the dirty status to the desired value call JDBPersistentObject.setDirty(boolean state); To check
the ObjectViewPL internal computed dirty status call the method isModified().
Persistency Status
If object was retrieved from database its persistent status becomes true and next save
operation will result in a call to an update or a delete statement.
User can change this flag (otherwise not recommended) only in cases when default
behaviour has to be changed (imported objects,…) Persistency status can be checked
and modified using isPersistent() and isPersistent(boolean status) methods.
Persistent Object Cloning
To create a copy in memory of an existing persisted object, use the
JDBPersistentObject.newCopy() method. Primary keys, update controllers and
autoincrementors will not be copied. After newCopy() the save() operation will result
in an update statement.
Transaction Management
Transactions can be managed using ObjectViewPL API or can be managed by an
external transaction monitor. For transactions internally managed, ObjectViewPL
supports embedded transactions so user does not need to modify existing code to be
able to wrap existing transactional units.
The methods used for internal transaction management are:
 JDBSession.beginTransaction() - begin an embedded transaction. If a transaction is
already started, then ObjectViewPL will not start another one but will join the
existing transaction. ObjectViewPL rolls back automatically in case of any
error or in cases when a database connection id closed without explicitly calling
commit or rollback.
 JDBSession.commitTransaction() - Commits the open transaction. If transaction is
embedded only commits if this call represents the most exterior level.
 JDBSession.rollback() – Rollbacks exiting transaction. Rollback is always
executed regardless of the level was called in case of embedded transactions.
P R O G R A M M E R S ’ G U I D E
Object vs. Database State synchronization
If objects or database state is modified independently then the state synchronization
should be performed as a separate step. State synchronization can be achieved using
the following methods:
 object.refresh() and object.refreshAll() – This method refresh the object/objectgraph
persistent attributes from database.
 object. checkPersistentStatus() – This method checks and updates persistent status,
commitDict and dirtyStatus.
 object. isPersistent ( boolean aBoolean ) – If object is in database the persistent flag
is true.
 child delete strategy in association mapping
Database Triggers
If database triggers are deleting or modifying rows, ObjectViewPL can be kept in
synch using association mapping delete strategy policy, object refresh or
checkPersistentStatus methods. For example if the delete trigger of a certain table is
deleting the associated rows then ObjectViewPL should not issue any delete
operations for associated roles but rely of the trigger to do the deletion while updating
object status as deleted from database.
Object persistent state rollback
ObjectViewPL saves last successful database access operation fields to an internal
dictionary that can be used to rollback persistent status. The internal variable used to
save persistent state is called commitDict and can be retrieved using method
JDBPersistentObject.getCommitDict(). The internal use for this variable is two fold: to
prevent unnecessary updates if no fields were modified since last database read, and to
restore object persistent state to the last database read. The method to be used for
restoring persistent state is JDBPersistentObject.rollbackToLastPersistentState().
public static void objectRollbackPersistentState() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// get a BusinessEntity representing a Person.
Person person = (Person) Person.findByPrimaryKey(session, new Integer(2));
person.setNotesString("Parking card declared lost");
person.setFirstName("Beautified");
person.setLastName("Changed Also");
System.out.println(person.toXml());
// put the last read values back
person.rollbackToLastPersistentState();
System.out.println(person.toXml());
P R O G R A M M E R S ’ G U I D E
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Mapping Functions, Stored Procedures, Views and
Ad-hoc SQL
bjectviewPL provides methods for managing stored procedures, open
cursors queries and ad-hoc SQL. If Stored procedures returns result sets
then they can be mapped as readOnly persistent classes.OFor stored procedures returning result sets (or open cursors) user has two options: to
map the result set columns to a new persistent java class, or to use an existing domain
class already mapped.
For stored procedures returning rows from a temporary table separately mapped to a
java persistent object, map database name is the (global) temporary table name and java
attributes database names are the result set column names. In this case if returned
result set metadata changes, mapping should change accordingly.
When a stored procedure returns result sets that were already mapped to domain
objects, then existing domain object mapping can be used to retrieve stored procedure
result set data.
Retrieving objects from stored procedures or functions
returning open cursors
The methods used for retrieving objects from an open cursor result set are
retrieveAllUsingOpenCursor() static methods defined in JDBPersistentObject subclasses.
The sequence is:
execute storedProcString ( bind parameters )
retrieve the cursor and build objects by iterating the resultSet
P R O G R A M M E R S ’ G U I D E
close cursor ( that will free Oracle memory )
Bellow you find the code of an Oracle function returning an open cursor to be used as
a sample.
Attention: if a stored procedure is used instead of a function to return an open cursor,
than first parameter must be an output parameter of cursor type and the actual
procedure in parameters are staring from position number 2. In this case
retrieveAllUsingOpenCursor must be called with isFunction boolean parameter false
CREATE OR REPLACE PACKAGE objectview_pkg AS
/******************************************************************************
NAME: objectview_pkg
PURPOSE: Testing OPEN CURSOR PROCEDURE MAPPING
AUTHOR: Adrian Faur
To test the function use:
DECLARE
RetVal OBJECTVIEW_PKG.cursor_type;
BE_TYPE_INPUT_CODE VARCHAR2(200);
BEGIN
BE_TYPE_INPUT_CODE := 'C';
RetVal := SYSTEM.OBJECTVIEW_PKG.BE_FOR_TYPE_FUNC ( BE_TYPE_INPUT_CODE );
COMMIT;
END;
******************************************************************************/
TYPE cursor_type IS REF CURSOR;
FUNCTION BE_FOR_TYPE_FUNC (BE_TYPE_INPUT_CODE IN VARCHAR2) RETURN cursor_type;
PROCEDURE BE_FOR_TYPE_PROC (BE_TYPE_INPUT_CODE IN VARCHAR2, O_RESULT_SET OUT cursor_type);
END objectview_pkg;
/
CREATE OR REPLACE PACKAGE BODY OBJECTVIEW_PKG AS
FUNCTION BE_FOR_TYPE_FUNC ( BE_TYPE_INPUT_CODE IN VARCHAR2 ) RETURN cursor_type IS
cur_result cursor_type;
BEGIN
OPEN cur_result FOR
SELECT *
FROM BUSINESS_ENTITY
WHERE BUSINESS_ENTITY.BE_TYPE = BE_TYPE_INPUT_CODE;
RETURN cur_result;
END;
/***** PROCEDURE ****************************************/
PROCEDURE BE_FOR_TYPE_PROC (BE_TYPE_INPUT_CODE IN VARCHAR2, O_RESULT_SET OUT CURSOR_TYPE) AS
BEGIN
OPEN O_RESULT_SET FOR
SELECT *
FROM BUSINESS_ENTITY
WHERE BUSINESS_ENTITY.BE_TYPE = BE_TYPE_INPUT_CODE;
P R O G R A M M E R S ’ G U I D E
END;
END OBJECTVIEW_PKG;
/
Here is the java code that uses this function to retrieve the objects:
public static void storedProcMappingDemo() {
JDBSession session = null;
try {
session = JDBSystem.acquireConnection();
Vector businessEntities=null;
// Assumption: The objectview_pkg was created and compiled. Source file can be found
// in config/OracleXE/StoredProcedureExamples.sql
// call the open cursor function BE_FOR_TYPE_FUNC
Vector param = new Vector(1);
param.addElement("C"); // companies only
// Attention! If function name not found,
// grant permissions,create a public synonym or use fully qualified names.
businessEntities = JDBPersistentObject.retrieveAllUsingOpenCursor (
BusinessEntity.class.getName(),
session,
"SYSTEM.OBJECTVIEW_PKG.BE_FOR_TYPE_FUNC" ,
param, true
);
for (Iterator iter = businessEntities.iterator(); iter.hasNext();) {
BusinessEntity be = (BusinessEntity) iter.next();
System.out.println(be.toXml(false));
}
// Now call the stored procedure instead, that produces the same result
param.removeAllElements();
param.addElement(null); // returned cursor
param.addElement("C"); // companies only
businessEntities = JDBPersistentObject.retrieveAllUsingOpenCursor(
BusinessEntity.class.getName(),
session,
"SYSTEM.OBJECTVIEW_PKG.BE_FOR_TYPE_PROC" ,
param,
false
);
for (Iterator iter = businessEntities.iterator(); iter.hasNext();) {
BusinessEntity be = (BusinessEntity) iter.next();
System.out.println(be.toXml(false));
}
} catch (ObjectViewApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
P R O G R A M M E R S ’ G U I D E
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Retrieving objects from stored procedures returning result
sets
The method used to return java objects mapped to the stored procedure result set is
JDBPesristentObject.retrieveAllUsingStoredProc(String className, JDBSession session, String
procName , Vector parameters).
In Sybase and SQLServer the last select statement issued in a stored procedure before
returning control, generates the result set returned to caller. DB2 uses session scope
temporary tables for storing result sets.
This method can be used in all cases when a stored procedure
returns a result set without any additional parameters for binding
the result set. This method can be used in all cases where the code
bellow can be used to call a stored procedure using jdbc:
// Prepare the CallableStatement.
CallableStatement cs =
con.prepareCall ("{ call StoredProcName(param1,…)} ");
// Call and Process the result set
ResultSet rs = cs.executeQuery();
A separate case that needs discussion represents Oracle database stored procedures. In
Oracle result sets can be returned from a stored procedure by using (global) temporary
tables and associated constraint “ON COMMIT DELETE ROWS”. To implement
this behaviour, JDBOracleObjectBroker must be used as the object broker for the
corresponding domain object mapping. There is a bug in Oracle 8.? where commit
does not always delete rows from temporary table defined with constraint “ON
COMMIT DELETE ROWS”. So, to fix it, instead of "SELECT * FROM
TEMP_TABLE" ObjectViewPL uses "SELECT * FROM TEMP_TABLE where
session_id = ( select SID from v$session where audsid = userenv('SESSIONID'))";

P R O G R A M M E R S ’ G U I D E
Attention: To fix the bug described above, put a '#' in front of stored procedure name
before supplying procName parameter to retrieveAllUsingStoredProc() method and map the
class to use com.objectview.jdb.JDBOracleObjectBroker supplied class.
Retrieving objects from ad-hoc SQL statements
JDBPersistentObject. retrieveAllUsingSQL ( String className, JDBSession session,
String sqlString ) method can be used to retrieve objects from any SQL returning a
result set. All result set columns whose names that can be matched to a java attribute
of the given object using mapping information will be retrieved and set into object
context.
Retrieving objects from database Views
Views can be mapped to domain objects like any other tables, but in order to flag the
objects as read-only (only SELECT statements accepted), user should set the “Is a
database view or a stored procedure producing a result set” checkbox in mapping configuration
(see Class Mapping Panel chapter of Mapping Tool Users’ Guide). In order to retrieve
the objects use can call the retrieveAllUsingSQL() method and supply the “Select *
from View_name” as the parameter representing the sqlString parameter.
Retrieving objects from a given java.sql.ResultSet
This is the most generic method for instantiating mapped java objects from a given
result set. This method will try to build objects according to mapping information. The
same method is used to instantiate objects for all other ObjectViewPL method calls,
regardless of SQL form (joins, stored procedures, ad-hoc SQL, etc), as along as they
produce a result set.
This method will become very handy in cases when ObjectView does not cover
specific requirements for constructing or issuing the SQL.
The method to call in this case is JDBPersistentObject. buildObjects( ResultSet rs,
JDBClassMap map, JDBSession session ).
Lightweight Objects. Primary Key Objects.
All JDBPersistentObjects generated by ObjectViewPL are “java.io.Serializable”
objects. They can be serialized to storage media or sockets. When memory footprint or
i/o is a particular concern, a new type of objects can be used as proxies to the real
domain objects. These objects are instances of the class JDBPersistentObjectKey. A
JDBPersistentObjectKey will always know how to retrieve its corresponding persistent
object once it was created. To create JDBPersistentObjectKey one can use the two
constructors provided or corresponding retrieve methods:
 public JDBPersistentObjectKey( NullWrapperDictionary aKeyDict, String className ).
className represents the domain object class name, aKeyDict is a special
P R O G R A M M E R S ’ G U I D E
java.util.Hashtable subclass that accepts null values for any given key. The keyDict
entries are pairs of (key,value) where key is the javaAttributeName of the primary
key (at:#pkJavaAttributeName put:pkValue).
 JDBPersistentObjectKey( JDBPersistentObject po). This constructor is used when the
persistent object is known.
 retrieveAllKeys ( String className, JDBSession session, Hashtable whereDict, String orderBy,
String customWhereClause, Vector persistentObjects ).
Parameters:
1) className is the java full class name ( including package ) for the
JDBPersistentObject(s) to be retrieved.
2) session database session
3) whereDict is a dictionary used to create the where clause for the select
statement. Its keys represent java attribute names visibles in the className,
and its values represent the values used in where clause. If whereDict is null or
empty, a select all will take place.
4) orderBy is the order by string for the select clause. It is appended as it is
provided. Do not Include ORDER BY text, but the comma separated
database fields only.
5) customWhereClause is an extra string to be appended to the where clause
6) persistentObjects. Vector with persistent objects previously retrieved. In this
case ,the objects are refreshed and returned. No new objects will be created.
Please find a usage sample bellow:
public static void objectKeyDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// create a JDBPersistentObjectKey to represents a known database Person object
NullWrapperDictionary personKeyDict = new NullWrapperDictionary(1);
personKeyDict.put(Person.ATTR_personBeId, new Integer(2));
JDBPersistentObjectKey pok =
new JDBPersistentObjectKey(personKeyDict, Person.class.getName());
// retrieve the person object from database.
Person person = (Person) pok.getPersistentObject(session);
System.out.println(person.toXml(false));
P R O G R A M M E R S ’ G U I D E
// instead of retrieving all persons from database, retrieve only the primary keys objects.
// we can then later retrieve the corresponding object behind each keyObject.
Vector keys= JDBPersistentObject.retrieveAllKeys(Person.class.getName(), session);
for (Iterator iter = keys.iterator(); iter.hasNext();) {
JDBPersistentObjectKey objectKey = (JDBPersistentObjectKey) iter.next();
System.out.println(objectKey);
Person p = (Person) objectKey.getPersistentObject(session);
System.out.println(p.toXml(false));
}
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
XML alternative store
bjectviewPL provides methods for writing and reading persistent object
state to xml format. These methods are toXml() and fromXml() static
methods from JDBPersistentObject class.OXML Logging
If property LOG_TO_XML_IF_SAVE_ERROR was to true, then the xml
representation of the domain object involved in an ObjectViewApplicationException
will be written to a file named objectDump.xml. Here is a sample of such file:
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Thread: Thread[AWT-EventQueue-0,6,main] @:2004-07-12 17:43:52.425 @:com.objectview.example2.Ex1Person
{name=adrian3}
INSERT INTO EX1_PERSON_EXTENSION ( NAME,MEMO ) VALUES ( ?,? )_VALUES_ :adrian3 , memories from
Japan , ;rollback transaction
-->
<com.objectview.example2.Ex1Person>
<name>adrian3</name>
<memo>memories from Japan</memo>
</com.objectview.example2.Ex1Person>
P R O G R A M M E R S ’ G U I D E
The content of this file should be correlated with the error file created by user upon
catching the exception and that is why the SQL, thread and timestamp information are
printed together with the object dump information.
Iterators. Retrieve first and next object.
hen objects need to be retrieved and processed one by one and in a certain
order, then an iterator must be defined. ObjectViewPL has methods that
helps creating an iterator to retrieve objects in the alphabetically order of
the primary key values.
W
The methods to use are:
 JDBPersistentObject.retrieveFirst ( String className, JDBSession session,
String additionalWhereClause ).
o className java.lang.String. The class name of the domain object to be
retrieved
o session com.objectview.jdb.JDBSession
o additionalWhereClause SQL string where clause to be appended to
default one issued by this method
 JDBPersistentObject.retrieveNext ( String className, JDBSession session,
Object key, String additionalWhereClause )
o className java.lang.String. The class name of the domain object to be
retrieved
o session com.objectview.jdb.JDBSession
o key java.lang.Object. The primary key value
o additionalWhereClause SQL string where clause to be appended to
default one issued by this method
Please find a usage example bellow:
public static void iteratorDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// get first BusinessEntity representing a Person.
P R O G R A M M E R S ’ G U I D E
BusinessEntity be = (BusinessEntity) BusinessEntity.retrieveFirst(
BusinessEntity.class.getName(),
session,
BusinessEntity.FLD_BE_TYPE+"='P'");
System.out.println(be.toXml());
// retrieve all next Business entities representing persons one by one
while (be != null ) {
be = (BusinessEntity) be.retrieveNext(BusinessEntity.FLD_BE_TYPE+"='P'");
if (be!=null)
System.out.println(be.toXml());
}
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
Locking policies
ocking mechanisms for both optimistic and pessimistic approaches are covered
in ObjectView by separate methods and/or mapping configurations.L
Optimistic Locking
It is implemented using update control fields of type Integer or Timestamp. To
configure an update controller field see Attribute Mapping paragraph on Mapping
Tool Users’ Guide. Optimistic locking is used to prevent dirty reads.
Attention: Because update controller field is used in the update where clause, it must
represent a real table column and not a composed or formula field. Also, if inheritance
is mapped to different tables (vertical approach) then one update controller must be
present for each particular table and defining just one at the super-type level will only
shield for concurrent updates happening at super-type level and not for any fields
saved to subtype tables(s).
Here is a sample of how such field could be used:
P R O G R A M M E R S ’ G U I D E
public static void optimisticLockingDemo() {
JDBSession session = null;
try {
// obtain a database connection based on objectview.properties settings
session = JDBSystem.acquireConnection();
// get a BusinessEntity representing a Person.
// Attention we only have defined an update controller at Busines_entity
// table level - only updating fields from this table can trigger
// a ConcurrencyException and no checking is made for updating fields
// from Person or Company subtype tables.
Person person1 = (Person) Person.findByPrimaryKey(session, new Integer(2));
// instantiate another object representing the same table row.
Person person2 = (Person) Person.findByPrimaryKey(session, new Integer(2));
// modify both of them and try to save them back to database. Second
// update should fail
person1.setNotesString("Parking card lost");
person2.setNotesString("Reissued parking card");
person1.save(session);
try {
person2.save(session);
} catch (ConcurrencyException e) {
// re-read object from database
System.out.println("ConcurrencyException catched");
person2.refresh(session);
System.out.println("Curent Note is:" + person2.getNotesString());
person2.setNotesString("Reissued parking card");
person2.save(session);
System.out.println(person2.toXml());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ObjectViewApplicationException e) {
e.printStackTrace();
} finally {
try {
JDBSystem.releaseConnection(session);
} catch (RollbackUncommitedSession e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
P R O G R A M M E R S ’ G U I D E
Pessimistic Locking
This type of locking is obtained by issuing special SQL syntax specific to database
engine. This SQL string will be appended to the select statement created internally by
ObjectView for the particular object involved and its syntax is specified in the
ObjectView property EXCLUSIVE_LOCKING_SQL.
By default the "FOR UPDATE NOWAIT" value was specified in the property file.
The NOWAIT option is recommended because it offers a better error message
handling that can be used to avoid dead-locks. Dead-locks can occur especially for the
objects that are persisted in more than one table and requires a join select. With
NOWAIT option these locks can be avoided. User should catch the SQLException
thrown by this method and interpret accordingly, eventually retrying a number of
times. For example, the most common Oracle SQL exception thrown in this case is:
java.sql.SQLException: ORA-00054: resource busy and acquire with NOWAIT specified
Cacheing policies
bjectviewPL caches objects using mapping preferences. See Class Mapping
Panel in Mapping Tool Users’ Guide for different types of cacheing.O
Hook methods
ook methods are user written methods having certain name and syntax
automatically called by ObjectViewPL in the object’s main lifecycle points.
In order to be called, the hook method must be implemented by user in the
particular domain class. Hook methods will be called for any instance of such class.
These methods are:
H
 preSave(JDBSession session). Method is called before issuing any insert, update or
delete.
 preInsert(JDBSession session). Method is called before any insert.
 preUpdate(JDBSession session). Method called before update operation.
 preDelete(JDBSession session). Method called before delete operation.
P R O G R A M M E R S ’ G U I D E
 postInsert(JDBSession session). Method called after insert operation.
 postUpade(JDBSession session). Method called after update operation.
 postDelete(JDBSession session). Method called after delete operation.
 postSave(JDBSession session). Method called after any insert, update or delete.
 postRetrieve(JDBSession session). Method called after any retrieve operation.

More Related Content

PDF
Acrobat document
PDF
Protective Device Coordination
PDF
Cscart 224 community
PDF
Etap 16-getting-started
PDF
AppLoader User Guide
PDF
Facility Planning Project - Tefal Pot Production
PDF
Jak úspěšně absolvovat výběrové řízení
PDF
160713_Fabien DAUZOU diploma
Acrobat document
Protective Device Coordination
Cscart 224 community
Etap 16-getting-started
AppLoader User Guide
Facility Planning Project - Tefal Pot Production
Jak úspěšně absolvovat výběrové řízení
160713_Fabien DAUZOU diploma

Viewers also liked (17)

PPT
не с глаголами
PPTX
Projet du Shift pour la décarbonation de l'Europe
DOCX
Lineas de investigacion
PDF
Hippie fashion declaraciones ayer y hoy
PDF
Brochure Easy Scan Pf400
DOCX
Entorno a herramienta del software
DOCX
Sterrett Resume
PDF
CV - Engelsk
PDF
Resume jk2016
PPTX
синтаксические-нормы
PDF
Manual simulacion h._caselli_g
PDF
Recommendation Letter EPFL
PPT
вид глагола
PDF
Rapport de stage Amir
PPTX
а каренина презентация із світової літератури
PPT
Представники реалізму ХІХ ст.
PPTX
входной контроль
не с глаголами
Projet du Shift pour la décarbonation de l'Europe
Lineas de investigacion
Hippie fashion declaraciones ayer y hoy
Brochure Easy Scan Pf400
Entorno a herramienta del software
Sterrett Resume
CV - Engelsk
Resume jk2016
синтаксические-нормы
Manual simulacion h._caselli_g
Recommendation Letter EPFL
вид глагола
Rapport de stage Amir
а каренина презентация із світової літератури
Представники реалізму ХІХ ст.
входной контроль
Ad

ObjectViewPLManual

  • 2. Mapping Tool Users’ Guide Programmers’ Guide © ObjectView Inc. www.objectview.ca Phone 416-436-3288 • Fax 905-881-7515
  • 3. Table of Contents MAPPING TOOL USERS’ GUIDE.................................................................................................................4 Introduction........................................................................................................................................................4 Feature Summary...............................................................................................................................................4 MAPPING CONSIDERATIONS......................................................................................................................7 Class Mapping....................................................................................................................................................7 Inheritance Mapping..........................................................................................................................................8 VERTICAL INHERITANCE MAPPING.............................................................................................................................................8 HORIZONTAL INHERITANCE MAPPING.........................................................................................................................................9 DISCRIMINATOR FILTERED INHERITANCE MAPPING.................................................................................................................9 One class to multiple tables mapping..............................................................................................................10 Relationships Mapping....................................................................................................................................10 TYPE - SUBTYPE RELATIONSHIPS..............................................................................................................................................10 PARENT OF A RELATIONSHIP AND OBJECT GRAPHS...................................................................................................................10 Attribute Mapping...........................................................................................................................................11 JDBC TYPE CONVERSIONS ......................................................................................................................................................11 SPECIAL FIELDS.......................................................................................................................................................................11 OBJECTVIEW WORKBENCH, CONFIGURATION AND USER INTERFACE....................................12 ObjectView Settings.........................................................................................................................................12 PROPERTIES FILE. LOCATION AND LOADING ASPECTS...............................................................................................................13 PROPERTIES SYNTAX.................................................................................................................................................................13 Workbench loading..........................................................................................................................................20 Workbench Settings Panel...............................................................................................................................21 UI WIDGETS AND CONTROLS:...................................................................................................................................................22 Inheritance Tree Panel.....................................................................................................................................26 Class Mapping Panel........................................................................................................................................27 Attribute Mapping Panel.................................................................................................................................31 Association Mapping Panel.............................................................................................................................35 ONE-TO-MANY ASSOCIATION MAPPING...................................................................................................................................36 MANY-TO-MANY ASSOCIATION MAPPING.................................................................................................................................39 DB Schema Explorer Panel.............................................................................................................................39 Model Validation Panel....................................................................................................................................40
  • 4. Model Generation Panel..................................................................................................................................41 Object Explorer Panel......................................................................................................................................42 OBJECTVIEW PERSISTENCY LAYER PROGRAMMERS’ GUIDE..........................................44 Introduction......................................................................................................................................................44 The Sample Model............................................................................................................................................44 Workbench settings..........................................................................................................................................47 PERSISTENT CLASSES................................................................................................................................48 DATABASE CONNECTION..........................................................................................................................50 Let ObjectView obtain a java.sql.Connection................................................................................................51 Passing a java.sql.Connection to ObjectViewPL...........................................................................................52 EXTERNAL TRANSACTION MONITOR INTEGRATION....................................................................................................................52 RETRIEVING AND PERSISTING OBJECTS.............................................................................................54 Retrieving objects.............................................................................................................................................54 RETRIEVING INDIVIDUAL OBJECTS............................................................................................................................................54 RETRIEVING OBJECT COLLECTIONS...........................................................................................................................................54 Saving Objects..................................................................................................................................................55 INSERT ....................................................................................................................................................................................55 UPDATE ..................................................................................................................................................................................56 DELETE ...................................................................................................................................................................................57 Saving Object Graphs......................................................................................................................................58 SAVEALL WITH CHECK..............................................................................................................................................................60 Setting and Retrieving Relationships..............................................................................................................62 MANY TO MANY RELATIONSHIPS................................................................................................................................................64 TYPES AND SUBTYPES. CAST DOWN POLICIES...........................................................................................................................66 RETRIEVING RELATIONSHIPS USING CUSTOMIZED JOIN REQUESTS.............................................................................................66 OBJECT ROLLBACK AND REFRESH. DIRTY AND PERSISTENT STATUSES.................................68 Dirty status........................................................................................................................................................69 Persistency Status.............................................................................................................................................69 Persistent Object Cloning................................................................................................................................69 Transaction Management................................................................................................................................69 Object vs. Database State synchronization.....................................................................................................70 DATABASE TRIGGERS................................................................................................................................................................70 OBJECT PERSISTENT STATE ROLLBACK......................................................................................................................................70 MAPPING FUNCTIONS, STORED PROCEDURES, VIEWS AND AD-HOC SQL................................71
  • 5. Retrieving objects from stored procedures or functions returning open cursors........................................71 Retrieving objects from stored procedures returning result sets..................................................................74 Retrieving objects from ad-hoc SQL statements............................................................................................75 Retrieving objects from database Views.........................................................................................................75 Retrieving objects from a given java.sql.ResultSet........................................................................................75 LIGHTWEIGHT OBJECTS. PRIMARY KEY OBJECTS.........................................................................75 XML ALTERNATIVE STORE......................................................................................................................77 XML Logging...................................................................................................................................................77 ITERATORS. RETRIEVE FIRST AND NEXT OBJECT...........................................................................78 LOCKING POLICIES.....................................................................................................................................79 Optimistic Locking...........................................................................................................................................79 Pessimistic Locking..........................................................................................................................................81 CACHEING POLICIES..................................................................................................................................81 HOOK METHODS..........................................................................................................................................81
  • 6. F E A T U R E S U M M A R Y Mapping Tool Users’ Guide Introduction bjectview persistency layer (OVPL) is a 100% java framework for object to relational mapping. Persistence is attained based on mapping rules specified by developer at design time. The framework consists of a GUI mapping tool (called Workbench) and a runtime library. The Workbench is used in design-time to specify mapping rules while the library supports the runtime functionality. Workbench also provides a generic user interface for browsing and modifying object instances for the mapped classes, as well database versus mapping model comparisons and validations. The product has been first used in 1998 and since then it was continuously improved and enriched in new features. O Feature Summary Here is a summary of the features OVPL has to offer:  Full inheritance support. OVPL supports all 3 types of inheritance mappings, vertical, horizontal and discriminator filtered.  All types of relationships mappings. One to one, one to many and many to many relationships, between any two classes, including recursive definitions, and customized relationships.  Multithreading safe environment. If used in the middle tier, OVPL can handle concurrent clients, and fits perfectly in a scalable architecture. Provides client scope cache access as well per client debugging and logging facilities.  4 types of cache management. Client session cache, global cache for immutable objects, SQL-view cache to associate a query with the produced result and a week references cache that allows garbage collection. Cache is synchronized with object lifecycle. Relationships can be defined as lazy-initialized or joins, cached or always refreshed. Chapter 1
  • 7. F E A T U R E S U M M A R Y  Database session pool management. User can opt between an internal session pool management or for interfacing with external database pools. The internal implementation deals with time-outs, validation methods, debugging information and logging.  Database session management. User can opt for internally managed data-source connection (when db connections, connection pooling and transactions are managed internally), external managed database connections (integrated with external pools using Data-Source interfaces) or for user managed connection lifecycle. Simultaneous use of multiple data-sources is allowed in user-managed data-source connection mode.  Database Transaction support. Transactions can be internally managed, controlled by user, or externally managed and integrated with a Transaction Monitor. In user mode, OVPL supports nested transactions. For integration with other middleware environments (EJB containers), transaction management is handled by the external TM, who also owns that particular session.  Object graphs. Persistence by reachability. User can transparently save all changes made since last access starting from an object root and following all instantiated relationships in one transactional step, without worrying about the database operations order. Only modified objects will translate to database calls, thus minimizing the database I/O. Based on configuration, if an object is deleted then all its references are removed from an object graph.  Cascade deletes support. OVPL keeps objects in synch with database if cascade delete was configured at the database level (triggers or delete constraints).  Transparent object id management. User does not have to worry at all for id fields. Primary keys, auto-incrementors, discriminators and foreign keys are created, assigned and migrated internally.  Concurrent update control. Optimistic and Pessimistic approach. OVPL implements the optimistic approach for data concurrent access (using update counters or timestamp fields) as well the exclusive lock mechanism provided by RDBMS.  Support for object rollback. OVPL provides support for object level rollbacks. Object state before any db access is saved and can be restored.  No SQL necessary. User does not have to use any SQL commands to attain persistency. SQL is internally generating as response to method invocations. 5
  • 8. F E A T U R E S U M M A R Y  Stored Procedure and Open cursor support. ObjectView PL transparently (builds objects following the same rules) supports ad-hoc SQL, stored procedures and open cursors.  Hooks methods. Pre and post methods to be used at all stages of an object lifecycle. User can specify business methods to be executed before and after each access operation.  Database reverse engineer. It assists in producing mapping schemas based on database schema. It also compares database schema with the mapping definition to detect mismatches.  Built in XML alternate storage. Any object graph (reachable objects) can be saved to XML format, and can be created back or updated from XML documents, as an alternative data store or for data exchange and configuration purposes. XML conversion is also used for debugging: if any database error is reported, current object state is dumped to the XML format and saved to a predefined file.  Lightweight objects. Lightweight objects are defined for each domain objects consisting only from the primary and foreign keys. Lightweight objects have the same relationships as the domain objects and can be realized to domain objects at user request.  Debugging features. OVPL provides logging and debugging features, allowing object activity tracing and SQL activity reports. If a persistency operation fails, OVPL logs the object state, SQL executed, thread information and error trace to a file. If debugging is on, OVPL logs all SQL activity.  Code Generation and merging. OVPL will merge any user added java code with the code it generates. It will merge comments added by UML mapping tools (TogetherJ, Rational XDE).  Mapping GUI interface, object relationship browsers and editors. The GUI mapping interface provides automatic object relationship browsing and edit facilities for all mapped classes. These features and many others will be covered in detail in the “Programmers Guide Manual”. 6
  • 9. F E A T U R E S U M M A R Y Mapping considerations y mapping we refer here the activity and the strategies by which are established the rules behind object to relational communication to attain the persistency status while preserving object concepts.BIndeed, just using a communication protocol and streaming out requests will make just part of this task possible, where by mapping, these two worlds managed by different rules - object and relational - can be linked together to acquire the privileges provided by each one of them. If in the object world we talk about classes, objects, attributes, state, behavior, identity, relationships, on the database side, we have notions like tables, rows, fields, primary and foreign keys. Our goal is to manipulate objects while respecting OO idioms and attain persistency with less of the effort. Mapping is part of this exercise; ObjectView PL (OVPL) framework combined with programming techniques will take care of the rest. Another advantage of mapping is that it creates a separation between class and database design, minimizing the impact of changes done in any of the parts. Therefore, looking from different angles, mapping provides both a unifying and a separation layer. In the following subtitles, we will be describing mapping techniques from object language perspective. Class Mapping A class can be mapped to one or more tables. If more tables involved, then there must be some join constraint implicitly or explicitly described to link both tables in a one to one cardinality. In this way the object persistent state became stored in one row on each of the involved tables. ObjectView PL handles two situations where one class is mapped to multiple tables: when mapping inheritance, or when helper tables are defined. In both cases a one to Chapter 2  7
  • 10. F E A T U R E S U M M A R Y one cardinality join is performed between involved tables based on keys specified at mapping time. In any of the class mapping types- one class to one table (view), one class to a subset of a table (or view) or one class to more than one table-ObjectView PL will manage consistency between instances and database content, and will transparently update and migrate foreign key values. Inheritance Mapping Mapping inheritance follows the rules described above for class mapping. There are three accepted ways of mapping class inheritance to tables. They are vertical, horizontal and discriminator filtered. Vertical Inheritance Mapping In vertical inheritance mapping the super-class and each subclass are mapped to a separate table. Lets consider the following UML diagram: Business Entity subclasses for vertical mapping model In this case, the database tables will look like: Table design for inheritance vertical mapping 8
  • 11. F E A T U R E S U M M A R Y ObjectView PL will manage the table join and the foreign keys in all object database access operations. A widely used variant is to define a discriminator field in the super- type, to store different values for each subtype. In this way it is possible to tell the subtype only by inspecting the value of this field, rather than trying to find the corresponding subtype table to be used in the join statement. The mandatory conditions for mapping this structure using OVPL are:  Number of primary keys is the same in each type/subtype table, and  The subtype primary key s are foreign keys in the super-type table. In this way the join is based on the primary keys of each table. Horizontal Inheritance Mapping In this case, each subclass is mapped to its own table, and there is no table for the superclass, which is becoming an abstract class. Tables will look like: Table design in horizontal mapping Discriminator Filtered Inheritance Mapping All classes are mapped to the same table, which contains the fields for the common set of class attributes. The discriminator field will be used to filter the rows that correspond to a particular subclass. ObjectView PL is internally managing the filter field. Table design for filtered mapping 9
  • 12. F E A T U R E S U M M A R Y One class to multiple tables mapping To be able to map one class to multiple tables, ObjectViewPL requires that the involved tables can participate in a join based on primary keys. In this case the join must produce a result set having one row. ObjectViewPL term for a joined table in a multiple tables class mapping is Helper Map. Relationships Mapping ObjectView PL permits mapping of three associations types:  One to one,  One to many,  Many to many. Type - Subtype relationships Given two objects in a one to many relationship, saying A -> (m)B, and given that class B has defined C and D as subclasses, then by calling A.getBSubtypes() a heterogeneous collection of Cs and/or Ds will be obtained. In this way ObjectView is instantiating the right subtypes when asked to do so, by managing the inheritance- subtype conversion. Parent of a relationship and Object graphs ObjectView defines as the relationship parent the part responsible with providing of the foreign key values. In this context, the parent is known as the class exporting the foreign keys while the child is the class that will import them. Two classes can have more than one relationship defined between them, each one with its own parent role played by the same or the other class. An object graph is defined as the graph of mapped objects that can be obtained by following relationship links starting from a requester object – the so called reachable object graph. ObjectView can handle all changes made to such a graph, involving all persistent operations in the right database order to perform a full synchronization between object state and database state. In taking the right steps and finding the right database operation orders, the parent of relationship concept is used. When necessary, one object can have more than one database access, for example if involved in self-recursive relationships where it plays both the parent and child role. ObjectView will discover and deal correctly with recursive graphs and self-relationships, and offers the assurance that if the SQL operations are possible to be executed in the context of the existing  10
  • 13. F E A T U R E S U M M A R Y database constraints, then a solution to save the graph will always be found. This offers great advantages to developers who don’t want to spend time creating save methods themselves to deal with the relationship persistency and operation order aspects for such graphs, nor to change them if mapping or database changed later or to find that errors are encountered in methods that were once tested. Imagine an http session client that updates such a graph state in different web pages, and the complexity to keep track and save such a graph, compared with the one line of code to save it in the existing or a new transaction. In literature, object graphs are used to implement the “Composite Entity” J2EE pattern (http://java.sun.com/blueprints/corej2eepatterns/Patterns/CompositeEntity.html) More on this aspect and programming techniques will be presented in the “ObjectView Programmer s’ Guide”. Attribute Mapping By attribute mapping a java attribute is mapped to a database field. JDBC Type conversions ObjectView PL permits mapping of all JDBC types. The database – JDBC type conversion is configurable, such a way that is possible for example to have a String java attribute mapped to a timestamp or integer database field type. ObjectView offers the flexibility to create and use your own type converters, in the event that further computation is needed. In addition is providing a rich set of converter classes, with the default converter being suggested at mapping time. Special Fields A separate role in attribute mapping is played by special attributes like:  Primary keys  Autoincrementors: sequences, identity fields, GUIDs, etc.  Update controllers  Foreign keys  Type-subtype discriminators (type-subtype filtering)  Formulas and read-only fields.  11
  • 14. F E A T U R E S U M M A R Y Those fields are managed internally, and their values are supplied by OVPL framework. ObjectView Workbench, configuration and user interface orkbench is a swing mapping tool application used to assist programmer at mapping time providing reverse engineering, java method generation and code merging, mapping validations and database comparison, object browsing and editing capabilities. Although mapping is possible to be changed using the provided API by creating/changing simple java methods in the assigned mapping configuration classes, the Workbench is a great tool with many more features than just mapping. W ObjectView Settings. We will distinguish between two times in ObjectView application lifecycle:  Mapping Time. Defined by the time when mapping rules are defined or changed.  Runtime. Defined by the time when objects are made persistent based on mapping configuration. OVPL settings are a set of properties that are influencing both mapping and runtime aspects, and are kept in the file named objectview.properties. We will explain each setting in the “Programmers Guide” for now it will suffice to know that initial settings loaded in Workbench are coming from this file. Chapter 3 12
  • 15. F E A T U R E S U M M A R Y Properties file. Location and loading aspects The objectview.properties file is loaded before any of the mapping/runtime activities becomes available. Its location is searched for in the following steps and order:  Using the file location specified by the java VM objectview.config parameter. (-Dobjectview.config = file:/// C:myAppconfigObjectView.properties)  In the classpath directory location using current classloader.  In the current user directory (defined by System.getProperty("user.dir" )) If none of these steps produces a valid location, an error is reported and ObjectView cannot be initialized. Properties syntax Properties are specified in the format KEY=VALUE, where each new KEY must start on a new line. VALUE is one of the followings:  A String value, this being the default  A null value, by leaving the VALUE blank  An empty string, by specifying “” as VALUE  The result of a static method evaluation, by specifying the VALUE in the format KEY=@classMethod ( java_class_name, method_name, arg1, arg2, arg3,...). Only static methods with string parameters are accepted.  The value of a system property ( a –D VM defined property), by using the syntax KEY=@systemProperty(aDefinedSystemPropertyName).  The result of a conditional expression evaluation using the syntax: KEY=(defined_Property ? testValue1) value1: (defined_Property ? testValue2) value3 : , etc There are two special characters: “” in the last column represents a line continuation, and “#” in the first column represents a comment line. Here is the ObjectView.properties file used in the mapping samples presented bellow: # ObjectView properties file # compatible version 6.4.44 and above. (v.6.5.44) # (c) ObjectView Inc. 1997 # # Prerequisites # -javax.naming package (JNDI class libraries) 13
  • 16. F E A T U R E S U M M A R Y # -javax.sql package (jdbc 2.0, or add JDBC 2.0 optional package) # -an XML parser # # This file is automatically loaded from the objectview.config defined VM parameter if one defined (- Dobjectview.config=file:///s:myAppconfigObjectView.properties) # or from the classpath directory location using current classloader, # or from the current directory (System.getProperty("user.dir" )) # # Notes about the content of this file: # a '' character in last column defines a line continuation. # a '#' character in first column defines a comment. # Properties values defined in this file can be obtain as a result of a static java method call, from VM defined properties, or as a String literal value. # To define a null value, leave the variable unassigned (property=). # To define a empty String value use "" (property="" ) # To assign the result of a method evaluation to a defined property, write it in the format : property=@classMethod ( java_class_name, method_name, arg1, arg2, arg3,...). Only static methods with string parameters are accepted. # To get a property value from System defined properties (VM -D arguments) call @systemProperty(aDefinedSystemPropertyName) # To use conditional defined parameters write them in the format: NewProperty=(defined_Property ? testValue) newValue. If defined_Property has been defined and if is value is testValue then NewProperty=newValue # To encode 2 or more conditions, use : NewProperty=(defined_Property ? testValue1) newValue1 : (defined_Property ? testValue2) newValue3 : , etc # # -Dobjectview.quietstartup=true # if a VM system parameter named "objectview.quietstartup" is defined as "true" (-Dobjectview.quietstartup=true), # ObjectView will not print version and other messages at startup # # #==================================== RUNTIME PROPERTIES =============================== #-------------------------------------DATABASE CONNECTIVITY---------------------------------------------------------------------------- # there are three object brokers that can be used. A generic ANSI one, and another two for DB2 or Oracle particularities (JOINS,....) #if class broker name was defined as the string "DEFAULT_TO_RUNTIME" then the broker is instantiated based on runtime #evaluation of the broker definition per objectview.properties file. For example user might define: #JDB_OBJECT_BROKER=(DB_TYPE ? oracle) com.objectview.jdb.JDBOracleObjectBroker : (DB_TYPE ? db2) com.objectview.jdb.JDBDB2ObjectBroker #JDB_OBJECT_BROKER_LIST=(DB_TYPE ? oracle) com.objectview.jdb.JDBOracleObjectBroker : (DB_TYPE ? db2) com.objectview.jdb.JDBDB2ObjectBroker # If DB_TYPE=oracle and Broker is DEFAULT_TO_RUNTIME then the oracle broker will be instantiated. # in this way mapping will not be changed if the application will run with a DB2 databases instead of Oracle. # we can define here a variable named DB_TYPE that is retrieved from VM -D defined runtime variables to be used as a switch for object broker class name DB_TYPE = @systemProperty(DB_TYPE) JDB_OBJECT_BROKER=(DB_TYPE ? oracle) com.objectview.jdb.JDBOracleObjectBroker : (DB_TYPE ? db2) com.objectview.jdb.JDBDB2ObjectBroker : (DB_TYPE ? other) com.objectview.jdb.JDBObjectBroker JDB_OBJECT_BROKER_LIST=com.objectview.jdb.JDBObjectBroker,com.objectview.jdb.JDBOracleObjectBroker,co m.objectview.jdb.JDBDB2ObjectBroker # JDBC driver JDB_JDBC_DRIVER=(DB_TYPE ? oracle) oracle.jdbc.driver.OracleDriver : (DB_TYPE ? db2) oracle.jdbc.driver.OracleDriver : (DB_TYPE ? other) sun.jdbc.odbc.JdbcOdbcDriver DB_CONNECTION_URL=jdbc:oracle:thin:@localhost 14
  • 17. F E A T U R E S U M M A R Y DB_CONNECTION_USER_ID=system DB_CONNECTION_PASSWORD=objectview # the catalog (database name in most of the cases, sometimes null, sometimes "") used in jdbc metadata methods. Leave empty for null, Use "" for empty string DB_CONNECTION_CATALOG= # the schema name ( in Oracle and DB2 use the chema name, sometimes null, sometimes "") used in jdbc metadata methods. Leave empty for null, Use "" for empty string DB_CONNECTION_SCHEMA= # define here the sql used to initialize each db connection, after opening it, for example in Oracle use: DB_CONNECTION_INIT_SQL=ALTER SESSION SET CURRENT_SCHEMA= aSchemaName DB_CONNECTION_INIT_SQL= # If autocommit true, jdbc driver will commit each SQL sent. If Odbc driver does not have a correspondent for jdbc setAutoCommit() API, then set the autocommit property on true. DB_CONNECTION_AUTO_COMMIT=false # controls how are transactions managed (internally by ObjectView or by an external TM - EJB container ) . # Used in combination with DB_CONNECTION_POOL_USE_EXTERNAL_POOL to use the connections provided and managed by the EJB container. DB_CONNECTION_EXTERNAL_TRANSACTION_MONITOR=false # Cursor SQL type for stored procedures returning cursors. # Particular for specific jdbc implementations. In this case Oracle DB. Please verify its value in the class oracle.jdbc.OracleTypes.CURSOR PROP_DB_SQLTYPES_CURSOR=-10 # exclusive locking SQL syntax ( use NOWAIT option when available ) EXCLUSIVE_LOCKING_SQL=FOR UPDATE NOWAIT #-------------------------------------MAPPING SCHEMA---------------------------------------------------------------------------------------- #maps to initialize. Use a comma separated string if more than one map initializer JDB_MAPPING_SCHEMA=com.objectview.examples.domain.MappingInitializer #-------------------------------------INTERNAL CONNECTION POOL SETTINGS------------------------------------------------------ # after how many milliseconds a connection is considered expired. (-1) for never expire DB_CONNECTION_POOL_EXPIRATION_TIME=86400000 DB_CONNECTION_POOL_INITIAL_SIZE=20 DB_CONNECTION_POOL_GROW_INCREMENT=10 DB_CONNECTION_POOL_MAX_SIZE=1000 DB_CONNECTION_POOL_ACQUIRE_RETRIES=2 #-------------------------------------EXTERNAL CONNECTION POOL ACCESS USING DATASOURCES ---------------------- # set this attribute to true in order to use an external connection pool ( i.e. EJB container) DB_CONNECTION_POOL_USE_EXTERNAL_POOL=false INITIAL_CONTEXT_FACTORY=weblogic.jndi.WLInitialContextFactory PROVIDER_URL=t3://localhost:7001 SECURITY_PRINCIPAL=myUser SECURITY_CREDENTIALS=myUserCredentials DATA_SOURCE_JNDI_NAME=dataSourceJndiName #-------------------------------------LOGGING ----------------------------------------------------------------------------------------------------- # if DB_CONNECTION_DEBUG=true, and session was acquired using JDBConnection pool then log sql used. # If VERBOSE_MODE is true, the sql will be sent to System.out, # otherwise logs to the listener attached to connection pool or to the one attached to the JDBSession object. DB_CONNECTION_DEBUG=true 15
  • 18. F E A T U R E S U M M A R Y # if DB_CONNECTION_DEBUG is true, then by setting VERBOSE_MODE also true, all sql activity will be printed to System.out (sql trace) VERBOSE_MODE=true # if this is true then the stack trace for opening sessions is log internally for each session and kept inside OpenedStackTrace session variable. # if VERBOSE_MODE is true, the stack will be sent to System.out as well. LOG_SESSION_OPENING_STACK_TRACE=false # following setting used to print any db activity for instances pertaining to listed classes. This property settings will help to trace the piece of code where # an object gets modified, in a multithreaded environment. Set this property using a comma separated list of the class names to trace. Ex: INSTANCE_TRACING=com.objectview.sample.Person,com.objectview.sample.Address INSTANCE_TRACING= # setting the next property to true will log the xml representation of current object for any save operation exception. The file will be named objectDump.xml # and its location will be given by the XML_LOG_FILE_LOCATION setting. XML representation of the objects that generated save LOG_TO_XML_IF_SAVE_ERROR=true # location of the objectDump.xml is given by the next setting. # The default is to leave it blank, case in which the current working directory will be used instead. # Usage example: XML_LOG_FILE_LOCATION=@systemProperty(user.home) XML_LOG_FILE_LOCATION= # set the xml parser used to create java objects back from xml documents. (Tested with org.apache.xerces.parsers.DOMParser , com.ibm.xml.parsers.NonValidatingTXDOMParser and javax.xml.parsers.DocumentBuilder) # If javax.xml.parsers.DocumentBuilder is used then the parser will be instantiated using the javax.xml 1.4.0 extension. # The parser must be in the VM classpath. i.e. XML_PARSER_CLASS=org.apache.xerces.parsers.DOMParser XML_PARSER_CLASS=javax.xml.parsers.DocumentBuilder #==================================== MAPPING (DESIGN TIME) PROPERTIES ================= #-------------------------------------WORKBENCH USER INTERFACE SETTINGS ----------------------------------------------------- # path for generating and reading java files (current version and new version) JDB_IN_DIR=C:objectview.workspaceObjectViewMappingsDemosrc JDB_OUT_DIR=C:objectview.workspaceObjectViewMappingsDemosrc # Exclude next tables from database versus schema comparation ( these tables are not mapped, and are not intended to be, so its no use to mark the differencies ) # Specify them as a comma separated list: EXCLUDE_TABLES= # if false cannot save objects to persistent store using Workbench UI. This setting should be used # in production environments where user should not be able to perform any db operations outside application environments WORKBENCH_OBJECT_EDITABLE=true #-------------------------------------AUTOINCREMENTORS AND CONTROLERS------------------------------------------------------- # autoincrementor sql (sequence nextValue sql or another sql). This sql is executed before insert sql to get an ID. 16
  • 19. F E A T U R E S U M M A R Y # Can use the following macros inside the definitio string [COLUMN_NAME] for current selected attribute Column_Name, # [TABLE_NAME] for current class table name and [CLASS_NAME] for current java class name # Used to implement Oracle and DB2 sequences. Can be also used as generic like : SELECT MAX() + 1; # The SQL expression must must return a result set if executed. The value from firt column from first row is used as the field value. # To call a java class for an unique ID implementation (GUID) , create a static method to compute the id and # specify <@GUID ( java_class_name, method_name)> as for the autoincrementor definition. The method will be called # without parameters, and if not found will be called with parameters (String persistentJavaClassName, JDBSession session). In the second case # parameters can be used to implement specific ID methods, when a SQL to execute is not enough. For example can implement different methods # depending of the target db, being able to switch from one db engine to another at the runtime. # Samples: # PRE_INCREMENTOR_SQL=@GUID([CLASS_NAME], getObjectId) # PRE_INCREMENTOR_SQL=SELECT NEXTVAL for [COLUMN_NAME] FROM DUAL PRE_INCREMENTOR_SQL=SELECT [COLUMN_NAME].nextval from dual # post insert SQL. This Sql is used after insert to get an ID value. (Similar to Sybase identity field type) # must return a result set. The value from firt column from first row is used as the field value # POST_INCREMENTOR_SQL=SELECT [COLUMN_NAME] = @@identity # POST_INCREMENTOR_SQL=SELECT @@identity POST_INCREMENTOR_SQL=SELECT @@identity #-------------------------------------METADATA BROKERS AND DRIVER SPECIFICS ----------------------------------------------- # all jdbc metadata request brokers that are available (any subclass of JDBGenericRequestBroker). JDBC_METADATA_BROKERS=com.objectview.jdb.ui.JdbcRequestBroker,com.objectview.jdb.ui.JdbcRequestBroke rFieldNames,com.objectview.jdb.ui.SybaseAnywhere6 # default request broker for database metadata retrieving JDB_REQUEST_BROKER=com.objectview.jdb.ui.JdbcRequestBroker # Field type to java type mapping in case user chooses JDB_REQUEST_BROKER=com.objectview.jdb.ui.JdbcRequestBroker # The following dictionary associates a java.sql.Types with a pair of com.objectview.binders.JDBAttributeSaver respectively com.objectview.binders.JDBAttributeRetriever subclasses. # Right members of this mapping are subclasses of com.objectview.binders.JDBAttributeSaver and com.objectview.binders.JDBAttributeRetriever classes. # These settings can be overwritten at mapping design time , and are specified here only to speed up the mapping process DB_TYPE_JAVA_TYPE_TRANSLATION= BIT, com.objectview.binders.JDBbooleanSaver, com.objectview.binders.JDBbooleanRetriever| INTEGER, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever| TINYINT, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever| SMALLINT, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever| BIGINT, com.objectview.binders.JDBLongSaver, com.objectview.binders.JDBLongRetriever| FLOAT, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBdoubleRetriever| DOUBLE, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBdoubleRetriever| REAL, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBdoubleRetriever| DECIMAL, com.objectview.binders.JDBDecimalSaver, com.objectview.binders.JDBDecimalRetriever| NUMERIC, com.objectview.binders.JDBLongSaver, com.objectview.binders.JDBLongRetriever| CHAR, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| VARCHAR, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| 17
  • 20. F E A T U R E S U M M A R Y LONGVARCHAR, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| CLOB, com.objectview.binders.JDBClobSaver, com.objectview.binders.JDBClobRetriever| BLOB, com.objectview.binders.JDBBlobSaver, com.objectview.binders.JDBBlobRetriever| BINARY, com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBBinaryRetriever| VARBINARY, com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBBinaryRetriever| LONGVARBINARY,com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBBinaryRetriever| DATE, com.objectview.binders.JDBDateSaver, com.objectview.binders.JDBDateRetriever| TIMESTAMP, com.objectview.binders.JDBTimestampSaver, com.objectview.binders.JDBTimestampRetriever| TIME, com.objectview.binders.JDBTimeSaver, com.objectview.binders.JDBTimeRetriever # naming convention for Update incrementor field used for concurrent update control. Any table field containing the following string is automatically mapped as an updateController. UPDATE_CONTROLLER_INCREMENTOR_WILDCARD=UPDATE_NUM # field name to java type conversion dictionaries. The following mapping takes place # in case JDB_REQUEST_BROKER=com.objectview.jdb.ui.JdbcRequestBrokerFieldNames setting was specified. # The following dictionary specifies a naming to type mapping convention. # XXX* stands for any field name prefixed with XXX string, *XXX* any field containing XXX, *XXX any string ending in XXX # Right members of this mapping are subclasses of com.objectview.binders.JDBAttributeSaver and com.objectview.binders.JDBAttributeRetriever classes. # These settings can be overwritten at mapping design time , and are specified here only to speed up the mapping process FIELD_NAME_JAVA_TYPE_TRANSLATION= *RATE, com.objectview.binders.JDBBigDecimalSaver, com.objectview.binders.JDBBigDecimalRetriever| *AMT, com.objectview.binders.JDBBigDecimalSaver, com.objectview.binders.JDBBigDecimalRetriever| *B, com.objectview.binders.JDBbooleanToStringSaver, com.objectview.binders.JDBbooleanFromStringRetriever| *BOOLEAN, com.objectview.binders.JDBbooleanToIntegerSaver, com.objectview.binders.JDBbooleanFromIntegerRetriever| *ID, com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBIntegerRetriever| *UPDATE_NUM,com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBIntegerRetriever| *NUMBER, com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBIntegerRetriever| *SIGN, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever| *CODE, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *SNUMBER, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *TYPE, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBintRetriever| *STYPE, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *STRING, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *LDESC, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *LSTRING, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *SDESC, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *NAME, com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBStringRetriever| *DATE, com.objectview.binders.JDBDateSaver, com.objectview.binders.JDBDateRetriever| *CLOB, com.objectview.binders.JDBClobSaver, com.objectview.binders.JDBClobRetriever| *BLOB, com.objectview.binders.JDBBlobSaver, com.objectview.binders.JDBBlobRetriever| *DATETIME, com.objectview.binders.JDBTimestampSaver, com.objectview.binders.JDBTimestampRetriever #-------------------------------------TYPE CONVERSIONS, SQL PARAMETERS BINDING------------------------------------------- # Objectview result set retrieve methods. (implementation of getObject methods for result set) # the last binder is provided as an example OBJECTVIEW_RETRIEVE_BINDERS= com.objectview.binders.JDBStringRetriever, com.objectview.binders.JDBIntegerRetriever, com.objectview.binders.JDBintRetriever, 18
  • 21. F E A T U R E S U M M A R Y com.objectview.binders.JDBLongRetriever, com.objectview.binders.JDBdoubleRetriever, com.objectview.binders.JDBDoubleWrapperRetriever, com.objectview.binders.JDBDecimalRetriever, com.objectview.binders.JDBBigDecimalRetriever, com.objectview.binders.JDBbooleanRetriever, com.objectview.binders.JDBbooleanFromIntegerRetriever, com.objectview.binders.JDBbooleanFromStringRetriever, com.objectview.binders.JDBBooleanWrapperRetriever, com.objectview.binders.JDBTimestampRetriever, com.objectview.binders.JDBTimeRetriever, com.objectview.binders.JDBDateRetriever, com.objectview.binders.JDBJavaUtilDateFromTimestampRetriever, com.objectview.binders.JDBcharRetriever, com.objectview.binders.JDBCharacterRetriever, com.objectview.binders.JDBBinaryRetriever, com.objectview.binders.JDBClobRetriever, com.objectview.binders.JDBBlobRetriever, com.objectview.binders.JDBTimestampIndirectRetriever, com.objectview.examples.binders.SimpleStringDecoderRetriever # ObjectView prepared statement set methods binders. (implementation of setObject methods for prepared statement). # the last binder is provided as an example OBJECTVIEW_SAVE_BINDERS= com.objectview.binders.JDBStringSaver, com.objectview.binders.JDBIntegerSaver, com.objectview.binders.JDBintSaver, com.objectview.binders.JDBLongSaver, com.objectview.binders.JDBdoubleSaver, com.objectview.binders.JDBDoubleWrapperSaver, com.objectview.binders.JDBDecimalSaver, com.objectview.binders.JDBBigDecimalSaver, com.objectview.binders.JDBbooleanSaver, com.objectview.binders.JDBbooleanToIntegerSaver, com.objectview.binders.JDBbooleanToStringSaver, com.objectview.binders.JDBBooleanWrapperSaver, com.objectview.binders.JDBTimestampSaver, com.objectview.binders.JDBTimeSaver, com.objectview.binders.JDBDateSaver, com.objectview.binders.JDBJavaUtilDateToTimestampSaver, com.objectview.binders.JDBcharSaver, com.objectview.binders.JDBCharacterSaver, com.objectview.binders.JDBBinarySaver, com.objectview.binders.JDBClobSaver, com.objectview.binders.JDBBlobSaver, com.objectview.binders.JDBTimestampIndirectSaver, com.objectview.examples.binders.SimpleStringEncoderSaver #---------------------------------REQUIRED PROPERTIES_VERSION--------------------------------------------------------------------- # if -Dobjectview.properties.requiredversion is defined then it must match with the value # specified by the property named PROPERTIES_VERSION. (This is not a check against objectView application version) PROPERTIES_VERSION=1.0 19
  • 22. F E A T U R E S U M M A R Y Workbench loading Based on the IDE you are using, create a batch file, or a run configuration (VisualAge, Eclipse, Jprobe) and run the class com.objectview.jdb.Workbench to open the Workbench application. Example of batch file: For eclipse IDE, here is the run configuration for Oracle mapping sample I have used in the programming guide. 20 rem in case not already set to point to your JDK instalation rem set JAVA_HOME=T:JDKsjdk1.3.1 set APP_LIBS=S:eclipse.workspacewebuiDefaultWebAppWEB-INFlib set APP_CLASSES=S:eclipse.workspacewebuiDefaultWebAppWEB-INFclasses rem --------------------start ObjectView UI %JAVA_HOME%binjava -classic -classpath "%APP_CLASSES%;%APP_LIBS%;%APP_LIBS %xerces.jar; ;%APP_LIBS%oracleclasses12.jar %APP_LIBS%objectView.jar; " - Dobjectview.config=file:///s:/objectview/config/ObjectView.properties com.objectview.jdb.Workbench -notrace -outputon
  • 23. F E A T U R E S U M M A R Y Workbench Settings Panel First panel that opens in Workbench application is the Settings panel: 21
  • 24. F E A T U R E S U M M A R Y The default settings in this panel are loaded from the objectview.properties file and then can be changed by the Workbench user. The settings that are changed are not written back in the properties file, user must update the properties file with the settings that are changed in order to preserve them. UI widgets and controls:  Mapping Initializers. The mapping instructions are kept in java class files named Mapping Initializers. A mapping initializer is a class that has the following characteristics: 1. Inherits from com.objectview.jdb.JDBMapInitializer. 2. There is only one map initializer for any java package containing persistent classes, and a mapping initializer cannot store mapping instructions for classes in different packages. Relationships between classes in different packages are permitted, and the order in which these initializers are loaded is not important. 3. Mapping initializer classes are java source classes produced by the Workbench tool but can also be created and modified by the user outside the mapping tool. For each persistent class in the host package there will 22
  • 25. F E A T U R E S U M M A R Y be one method present in the initializer class to store the mapping information. Mapping initializers are specified in a comma-separated string assigned to the property named JDB_MAPPING_SCHEMA. Workbench will try to load all mapping initializers, and will assume that the ones not found are new ones that will be generated in current Workbench session. So, to create a new initializer, just add its java class name in the property file or in the corresponding workbench settings field, in a comma-separated string. Then press “Reload Maps” button. You will be now able to create persistent classes in the package managed by the new initializer.  JDBC database driver. Specify here the name of the java class implementing the JDBC-compliant driver being used. The driver must be in the workbench class path. The properties file correspondent setting is JDB_JDBC_DRIVER.  Catalogue. ObjectView is using JDBC metadata information when available to assist in mapping process. The catalogue is used in the JDBC methods used to gather metadata information. (Interchangeable with database name sometimes) The corresponding property is DB_CONNECTION_CATALOG.  Schema. Used for gathering metadata information. The corresponding property is DB_CONNECTION_SCHEMA.  Connection init SQL. SQL that will be used to initialize each connection before being used. For example, in Oracle it can be set to: ALTER SESSION SET CURRENT_SCHEMA= mySchema.  JDBC Metadata broker. The corresponding property name is JDBC_METADATA_BROKERS and consists of a list of two classes to pick from: com.objectview.jdb.ui.JdbcRequestBroker, and com.objectview.jdb.ui.JdbcRequestBrokerFieldNames. These classes are responsible for proposing the data type translation between data types and java types. 1. In first case the types are converted using the matching pairs specified in the DB_TYPE_JAVA_TYPE_TRANSLATION property setting. The conversion is specified associating JDBC types with the ObjectView conversion classes. For example by default BIT JDBC type is associated with boolean java type. 2. In the second case, the broker uses naming convention to propose a java type based on a database field name. In most of the cases, best practice 23
  • 26. F E A T U R E S U M M A R Y reasons, DBAs use naming conventions that carry also type information. For example any date field will end up in ‘DATE’ suffix, any float field will end up with ‘AMT’ suffix, and so on. It will be the field name that will be used to make a distinction between a CHAR field holding a string information (code) or a boolean value. The name java type translation information is described by the FIELD_NAME_JAVA_TYPE_TRANSLATION property setting. The type conversion proposed by the metadata broker is the default one, is part of the attribute mapping information, and can be changed by user any time when necessary. Brokers role is mostly in the reverse engineer procedures, and to ease/assist the mapping task.  Connect, Disconnect. Connects to the database using the current settings. Once connected, mapping process is assisted by metadata information, and database access Workbench functions become available (database comparison, data browsing and editing). The Workspace might be connected, but the metadata information might not be available (first sign is when no tables are found after connect). This might happen because there might not be any metadata available using current JDBC driver, or userId/pswd supplied has no rights to gather it, or the metadata information cannot be extracted from current database because the connection information is not correct. Check the catalog and schema settings as well. Some databases require null some an empty string for the catalog name. Leave empty for null and input “” for empty string and reconnect. Connecting the Workbench to the database enables the application features related to database access. Those are assisted mapping, database browsing, object editors, and database comparison. The database metadata information is gathered and used to ease the mapping effort, but its presence is not mandatory for mapping process.  External Transaction Monitoring. If this flag is set on true by DB_CONNECTION_EXTERNAL_TRANSACTION_MONITOR global property or by setting it for a particular session then the transaction can be initiated and terminated only by an external transaction monitor (i.e. an EJB container). Such setting is used to integrate transaction management with middleware systems and is used in combination with external connection poll settings (external datasources interface settings) to acquire connections created and owned by the external monitor. In workbench this flag will be rarely used if ever, but the corresponding property setting is a key configuration in the integration with a middleware task. This will be covered in more detail in the “Programmer’s Manual”.  24
  • 27. F E A T U R E S U M M A R Y  Auto Commit. This flag is used to call the java.sql.Connection .setAutoCommit() method. If this flag is on true, there is a commit performed after each SQL sent to the data serve and no transaction control beyond one SQL command at a time.  Output Directory. ObjectView generates domain classes and mapping information data (mapping initializer class) into this directory. Classes generated in this directory must be loaded back into IDE, if not already an IDE source directory.  Input Directories. A comma-separated list of directories where ObjectView searches for the source files used to extract user added content to be merged with the generated content. Usually the same directory as the “Output Directory” and the project source directory for the IDE used. If input and output directories point to the same location, IDE should have a versioning control in place in order to pull back the last class version if ever needed.  Erase Output. Press this button to erase the output directory. Pay attention to the case when input points to the same directory location, and this operation is not desirable. By erasing previously generated files, it will become more clearly what are the files being currently generated. 25
  • 28. F E A T U R E S U M M A R Y Inheritance Tree Panel The tree showing in the upper left corner displays all mapped classes, and their hierarchy up to the JDBPersistentObject class.  New Map. The result of creating a new map is two fold: a new domain class will be created, and a new method in the selected map initializer will be created to load and store the mapping meta-information. To create a new map, select a class from the class hierarchy tree to become the superclass of the new class being created. Then press the “New Map” button. On the right side there are three tabs, where each tab is storing mapping information specific to one of the three main mapping topics: class wide scope mapping, attribute mapping and association mapping.  New helper. Helpers are used to map one java class to more than one table. The helper is mapping the join between any two tables, based on their primary keys. This join is used to retrieve one java persistent class. Helpers can be added to any existing maps.  Table Explorer. If Workbench is connected, select one persistent class in the class hierarchy tree and press this button to display the table data associated with that class. If table (join) has more than 10000 rows, a warning message is displayed instead. Select an individual row from this table and you can open the object explorer frame. 26
  • 29. F E A T U R E S U M M A R Y  Object Explorer. Press this button and the object browsing and editing application will be open. Details and instructions will be presented in the section “Object Browsing and Editing Application”. Class Mapping Panel The class-mapping panel is used to edit mapping information pertaining to a class for a new or existing map.  Class Mapping Initializer. The list of map initializers is coming from the JDB_MAPPING_SCHEMA property, and can be updated by the settings panel. As explained earlier, a mapping initializer is tight to a java package, and all persistent classes from one package have mapping information initialized and stored in one mapping initializer contained in the same java package. Mapping initializer can be chosen only once, when a new class map is being created, and cannot be changed later on. Changing the mapping initializer is somewhat similar with moving a class to a different package, and this operation cannot be done using the Workbench (some java IDE will assist you in this scope).  Related Table. The table mapped by current domain class. There are two special cases to distinguish here: 27
  • 30. F E A T U R E S U M M A R Y 1. If table name is left with the default name “tableName”, then the generated class will not be a persistent class, but will be presented in the class hierarchy. For example the “AbstractExternalAccount” class in the above picture is not a persistent class. 2. In case a new helper is created (for an existing class map) the table picked must be in a one-to-one relationship with the main table, based on a Primary Key join. A list of all available tables visible using the userId/passwd connection information will be presented in the “Related Table” drop-down list control. If a table list is not available, then the Workspace is not connected, or userId/pswd supplied has no rights to see them, or the metadata information cannot be extracted from current database either because it is not available or the connection properties are not correct. Change login information and reconnect. Anyway, it is possible to map a table even if no metadata can be extracted. Once a table has been picked and metadata is retrievable, the available fields are mapped to attributes, mapping that can be reviewed and changed in the “Attribute Mapping Panel”.  Database Name. The name of the database table, view or stored procedure used to map current domain class. If metadata is not available, this information must be entered by hand.  Java Name. The name of the mapped java class, not including the package name that will be borrowed from the mapping-initializer class name.  XML Name. The value entered here will be used for the tag name in the xml representation for objects of this class. By default, if nothing entered, the tag name used is the java class name.  Additional Where Clause. String expression in SQL syntax that can be used as where clause. This where clause will be always used in all attempts to instantiate objects based on map in discussion. This aspect differentiates this where clause from the ad-hoc ones that are mostly used as parameters in the API retrieve methods.  Max Rows Retrieved. Max rows allowed to be retrieved in a single retrieve method.  Broker Class Name. The name of the java class used to translate persistent method calls to SQL commands. Three classes are provided, but more can be created. The default class is com.objectview.jdb.JDBObjectBroker, and it can handle a JDBC compliant driver and a relational database (RDBMS). Another 28
  • 31. F E A T U R E S U M M A R Y provided class is com.objectview.jdb.JDBOracleObjectBroker that handles Oracle particularities (the left outer join symbol is "(+)" instead of “*=”, and retrieveAllUsingOpenCursor method has a specific implementation). Also a special one is provided for DB2 particularities.  Use empty strings instead of Nulls. This is a useful setting for particular database engines (like Excel spreadsheet).  Acquire and release DB session internally. Does not expose transaction context. If set, ObjectView will generate data access methods that will not have a connection parameter, connections being acquired and released when needed using the connection properties set provided. This will simplify framework usage, but will not permit transaction management outside method scope.  Expose transaction context in generated methods. If set, ObjectView will generate data access methods that will have a connection parameter, making possible to integrate transaction management with an external middleware (EJB container).  Read-Only Access Class. Only methods for retrieving the persistent state will be generated, no insert, updates, deletes will be possible for such a class.  Is a Database View or a Stored Procedure producing a result set. In this case database access is read only, and a custom SQL will be required as a parameter for each retrieve method. In fact, only the methods “retrieveAllUsingSQL”, “retrieveAllUsingStoredProc” and “retrieveAllUsingOpenCursor” will be generated and available for use.  DB Session wide Scope. Attach/Detach cache management procedures. By default, this limits the cache scope to the database session usage time. But because session has procedures to attach and detach the cache, its scope can be increased, for example it can be increased for the duration of an http client session, by detaching and attaching the cache stored in an http session each time a new db session is acquired or released.  Global cache. VM wide scope. Objects are only retrieved once, the first time they are instantiated, and then returned from this global cache for subsequent inquiries. Should only be used for immutable objects, because object state changes are not synchronized for multiple users.  Weak Referenced Global Cache. VM wide scope. Same as above, but objects are discarded from cache once they are de-referenced.  SQL subset cache. Objects are cached under the SQL used to retrieve them. This is like a view applied to the global cache, where subsets of objects are gathered 29
  • 32. F E A T U R E S U M M A R Y under the SQL used first time to retrieve them. If exact SQL is used a second time, objects are retrieved directly from cache, without accessing the database. And because this represents a view of the global cache, and not a separate cache container, one object will still be cached only once, only it will be viewed as belonging to different cache groupings.  Java Superclass Name. Not editable here, this widget has only an informational meaning.  Vertical Mapping Discriminator Value. This is a non mandatory value of the discriminator field used in inheritance vertical mapping. This value is defined as having a class scope, and will be held by a static variable being generated together with the persistent class. The correspondent attribute will be mapped is the superclass as having “Vertical Mapping Discriminator” flag set on, in the “Attribute Mapping Panel”. (Note that the attribute is defined in the supertype, while its value is specified in the subtype). If such a value is specified, it will serve to automatically cast down objects to their lowest type, and will be used to generate “isTypeOf” type methods. 30
  • 33. Attribute Mapping Panel This panel is used to capture the java attribute to database field mapping information.  Related Field. This widget is a drop-down list being initialized with all the fields for the current database table. By picking one field from the list the field metadata is used to generate the default attribute mapping information. This mapping information that makes the subject of all widgets in this panel can then be changed and ultimately saved. The “Related Field” widget is only selectable if Workbench is connected and if field metadata is available and is only used to gather metadata information used to ease mapping effort, but its presence is not mandatory for mapping process.  Database Name. This is the name of the database field, or the given name of a computed column in the case this attribute maps a database formula/expression. This field is pre-filled using metadata information if available, and should be
  • 34. M A P P I N G T O O L U S E R S ’ G U I D E entered by user if no metadata information available or if represents a computed field.  JDBC Type. Informational scope only. Present only if metadata available.  Java Name. The name of the java class attribute used to store this field value.  Java Type. Change the type conversion class -Attribute Retriever- to have this information changed accordingly.  Java Initial Value. The literal used to initialize the java variable. The string is copied identically and place on the right side of the equal sign in variable declaration statement. For example in case of a String type attribute the expressions “ObjectView Inc.” or new String (“ObjectView Inc.”) would be valid initializers.  User Documentation. Text will be copied in the getter and setter method javadoc documentation.  XML Name. This value entered will be used for the tag name in the xml representation for this attribute. By default, if nothing entered, the tag name used is the java attribute name.  Attribute Saver. This class will be used to convert attribute to one of the types used for binding parameters to a prepared statement. The list of available classes implementing the JDBAttributeSaverInterface is specified in objectview.properties file by property OBJECTVIEW_SAVE_BINDERS. Developers can add customized classes by inheriting one of the existing “Saver” classes or by inheriting directly from JDBAttributeSaver class. When a custom class is created, that class can also specify a custom pre-save method (see pre-save method setting bellow).  Attribute Retriever. This class will be used to convert the value obtained from a result set to the type used to represent it in the java persistent class. The list of available classes implementing the JDBAttributeRetrieverInterface is specified in objectview.properties file by property OBJECTVIEW_RETRIEVE_BINDERS. Developers can add customized classes by inheriting one of the existing “Retriever” classes or by inheriting directly from JDBAttributeRetriever class. When a custom class is created, that class can also specify a custom post-retrieve method (see post-retrieve method setting bellow).  Post Retrieve Method. If entered, this user method will be called after retrieving the field from database. Such a method is only available to customized Attribute Retrievers (and not the ones provided by OVPL). The only argument for post retrieve method is the retrieved field value, and the method must be added in the attribute retriever class.
  • 35. M A P P I N G T O O L U S E R S ’ G U I D E  Pre Save Method. If entered, this user method will be called before saving the field to database. Such a method is only available to customized Attribute Savers (and not the ones provided by OVPL). The only argument for pre save method is the java attribute value and the method must be added in the attribute saver class.  Primary Key. Field is part of the table primary key. In this case it can also be a pre- increment or post-increment attribute.  Pre Auto-Incrementor. The attribute value will be obtained before issuing the insert statement. Usually the value comes from a sequence table or from a third- party library method invocation in case of a GUID. When the check button is set, the autoincrementor definition is initialized based on PRE_INCREMENTOR_SQL property.  Post Auto-Incrementor. If set, this attribute will have a corresponding null value in the insert statement, assuming that the field value will be known only after insert statement execution. Same as for auto-incrementors, the value is computed by evaluating the expression specified in the “Auto-Incrementor Definition” UI entry field. This setting is used for Sybase like identity fields. In this case the DB engine assigns the field value and also provides the mechanism to obtain the value – usually by issuing a SQL statement. The provided SQL will be issued inside the same transaction with the insert statement. By default, the initial value is computed using POST_INCREMENTOR_SQL property definition (after expanding the table and column name macros in case they are used)  Read-Only Access. If set, this attribute will be retrieved from database but not updated when object gets saved back.  Field Retrieve Definition. This entry field store the expression used for autoincrementor, identity, read-only or computed fields. Depending on these flags, its value is interpreted differently as explained bellow: 1. For a pre-autoincrementor field it will store the SQL or java expression used to get the field value to be used in the insert statement: a. PRE_INCREMENTOR_SQL=@GUID([AFullQualifiedJavaClassN ame], aStaticMethod) b. PRE_INCREMENTOR_SQL=SELECT [COLUMN_NAME].nextval from dual In the first case “aStaticMethod” will be called in the java class “AFullQualifiedJavaClassName”, while in the second case the SELECT statement will be issued to get the field value. Notice that the TABLE_NAME, COLUMN_NAME are macros that
  • 36. M A P P I N G T O O L U S E R S ’ G U I D E can be specified in the property file and that will expand to real values based on current column and table selected by UI user in Workbench (i.e. in design time and not runtime). 2. For a post-autoincrementor (identity) field it will store the SQL used to get the inserted value. By default field is initialized by expanding POST_INCREMENTOR_SQL property field. 3. For a read-only field, retrieve definition scope is three fold: R ea d- O nl y Retriev e Definit ion Scope T r u e False Field is retrieved from database, but inserts or updates are not possible. T r u e True Field is retrieved using the SQL definition provided, inserts or updates are not possible. F a l s e True Field is inserted using the SQL definition, then can it can be updated with any other value.  Filtered Mapping Discriminator. Attribute is used for mapping inheritance to the same table schema. The attribute value for the current subtype must be stored in “Discriminator Value” field. See “Mapping Considerations” chapter for inheritance mapping schemas.  Vertical Mapping Discriminator. Attribute is used for mapping inheritance to different tables using a join statement and defining a discriminator filter for each subtype. The attribute value for each subtype must be stored in the corresponding subclass in the “Vertical Mapping Discriminator Value” field (class mapping UI panel). See “Mapping Considerations” chapter for inheritance mapping schemas.
  • 37. M A P P I N G T O O L U S E R S ’ G U I D E Note that the field is defined in the supertype, while the field values are defined in each subtype. By using a discriminator, OVPL is capable of casting objects easily; in this case isSubTypeOf methods are provided in each superclass and subtypes can be retrieved automatically.  Not Nullable. If set, attribute cannot take null values. The setting only plays a role in mapping recursive associations; in this case it will be used to determine the order in which the SQL statements are to be issued when an object graph is saved.  Update Controllers. Attributes have the sole meaning to prevent dirty reads using optimistic locking mechanism. Such a field will be incremented automatically with each update and the value in memory verified with the value from database (in the update where clause) each time a new update is issued. Attention: Because update controller fields are used in the update where clause, they must represent a real table column and not a composed or formula field. Also, if inheritance is mapped to different tables (vertical approach) then one update controller must be present for each particular table and defining just one at the supertype level will only shield for concurrent updates happening at supertype level and not for any fields saved to subtype tables(s). Update Counter. If set, the current attribute will be used for optimistic update control and the attribute value represents an Integer and will be incremented automatically for each update. Update Timestamp. Same role as the Update Counter, with the difference that the current attribute must be of type java.sql.Timestamp and its value will be stamped with last successfully update datetime. Association Mapping Panel This panel is used to configure association mapping information.
  • 38. M A P P I N G T O O L U S E R S ’ G U I D E One-To-Many Association Mapping There are two terms that will be used here: source class and target class. An association is defined as a relationship between a source class and a target class. This relationship has a “from cardinality”, a “to cardinality” and a role name. The role name must be unique and will be used in the role accessors and in the find methods generated by OVPL. In runtime relationship definition will translate in a table join, where the join expression is constructed from the association foreign keys.  Association Target Class. All mapped classes are gathered in this table the one that constitutes the target class for current selected association is highlighted.  Use FK Definitions. When selected, database foreign keys definitions will be used to assist user in creating the correspondent associations.  Association Join Definition. This table is used to define the source and target attribute pairs used in database join that will be used to retrieve the rows from the association table. The corresponding source attributes and target attributes must be of the same type.
  • 39. M A P P I N G T O O L U S E R S ’ G U I D E  Role Name. Unique name that will designate the attribute holding the association. The role name will be also be used to generate find methods.  Order-By Clause. When specified, a one-to-many association is always retrieved ordered using this expression. The expression used must be a valid SQL order-by clause (without the keywords ORDER BY) - usually the database fields separated by comma. The expression specified here represents the default order by, a constant for the association, unlike the orderBy parameter from association getter that can be changed within each runtime invocation.  Where Clause. When specified, this where clause is added to the one used to retrieve the relationship. The expression used must be a valid SQL where clause (without the WHERE keyword). When a where clause is specified, the association represents only a subset of the rows represented by the relationship join. If a new object is added to such a collection, that object will not be checked to verify that it complies with the association filter. Like the Order By clause, this represents a constant for the association retrieval, unlike the where parameter from association getters that represents a configurable runtime setting.  XML Name. This value entered will be used for the tag name in the xml representation for this association. By default, if nothing entered, the tag name used is the association role name.  Association Parent. The association parent is the mapped class participanting in the association definition that is responsible with exporting the foreign key values to its children. For example in an invoice-invoiceLineItem relationship, the invoice is the parent of the association and the invoiceId is the foreign key exported in invoiceLineItem. Workbench will try to guess the parent of relationship based on some heuristics, but user should review and set it accordingly. The parent setting is used in saving object graphs. An object of the parent class represents the first object to be saved in a relationship save. Its primary keys once known are exported to associated children objects where they are defined as foreign keys.  Cardinality. The association max cardinality. The possible values are one-to-one, one-to-many, many-to-one, and many-to-many.  Child Deletion Rule. This rule only applies to saveAll operation for an object graph. When the parent of a relation is deleted, there are 3 deletion possible rules for the associated objects reacheable in the object graph: 1. No Action. This is the default setting. 2. Software Handled Cascade Deletion. When this setting is selected, OVPL will delete all instantiated children present in the current object graph when the association’s parent is deleted.
  • 40. M A P P I N G T O O L U S E R S ’ G U I D E 3. Database Handled Cascade Deletion. Use this rule when the database foreign key definition behind this association has a similar rule. In this case OVPL will keep object sate in synch with the database delete trigger action. Objects deleted by the DB trigger will be marked as deleted.  Identifiable Relationship. Used to map compositions. A relation is said to be identifiable when the child object cannot exist without parent object – in database terms, the foreign key cannot be null (usually FK is part of the PK). This setting is used in handling object graphs saving order.  Always Refresh Role. If true, OVPL goes to database for each get association method call. If false, once the association was retrieved, and if the association role is represented by a java attribute (“Generate Role Accessors” setting is true), the previously retrieved value will be returned and no database access will be made (user still have ways to retrieve/refresh association from db again if he really wants it).  Joined with Parent. If true, (prerequisite condition is that association cardinality is one) the association can be retrieved in the same select statement with the parent. Each time parent is selected, the associated object is also retrieved.  Retrieve Subtypes each time possible. This setting is used to force a type- subtype conversion each time possible. For example if an “Account” class has subtypes, then person.getAccounts() association call will result in a collection of Account subtype objects. It is recommended to leave this setting off, because user has the choice to “subtype” the retrieved collection, only when and if he wants to.  Generate Pair Association. If selected the reverse relationship will be created when current association will be saved.  Generate Role Accessors. This setting applies to java class generation. If set, the java class will have a java attribute for each association. The attribute name will be the association role name. If roles are not materialized by java attributes, object graph saveAll operation is not possible.  Generate Find Method. This setting applies to java class generation. If set, a findByXXX method will be generated in the target class. If role accessors are not generated, then persistent class become a pure “data access object”, no object graphs operations are possible, roles are not represented by instance attributes – associations are not represented by objects.
  • 41. M A P P I N G T O O L U S E R S ’ G U I D E Many-To-Many Association Mapping This panel is used to configure many-to-many association mapping. If class “A” has a one-to-many relationship with class “AB” that has many to one relationship with a class B, then the many-to-many relationship from class “A” to class “B” can be created. Class “AB” must be mapped prior to creating the many-to-many association.  Passing through Association class. This table will show all cardinality 1 associations having as source the target class for current (selected) association. Each such association can be used to create a many-to-many association.  Defined m-to-m Associations. This table holds the selected associations used to create the many-to-many relationships from the table described above. In the sample shown in the above screenshot, a many-to-many association was configured from class BusinessEntity to the class BusinessEntity, passing association class (table) B2BRelationship. The role name for the many-to-many association will be “relatedBusinesses”. DB Schema Explorer Panel This panel is used to generate class mapping information from database tables and to compare existing mapping information with current database schema.
  • 42. M A P P I N G T O O L U S E R S ’ G U I D E  Select New Tables. All tables that are not mapped to persistent classes are selected.  Map Selected Tables. All selected tables from left panel will be used to generate class mapping. If the class mapping exists, it will be updated, otherwise a new one will be created.  Compare Selected. Mapping information is compared against table information; detected differences are logged in Messages window.  Update Map from Table Definition. Selected map is compared against selected table and differences are used to update mapping information accordingly. Model Validation Panel Selected maps are validated for errors. The result is displayed on Messages panel.
  • 43. M A P P I N G T O O L U S E R S ’ G U I D E Model Generation Panel Selected maps are used to generate java classes.  Add Changes. All maps that were modified since last save will be selected.  Add All. All classes are generated.
  • 44. M A P P I N G T O O L U S E R S ’ G U I D E  Erase Output. If source folder differs from output folder (see settings panel) then the output directory content can be deleted using this button. Object Explorer Panel This panel is a very useful tool for browsing object hierarchies, graphs or to display any individual object from current database schema. With this toll new objects can be created and existing ones modified. In order to make this tool safe for production environments set the property WORKBENCH_OBJECT_EDITABLE to false. To edit the attribute values double click the value for the corresponding attribute value, type in data and press enter to end editing mode. The left panel displays all defined (mapped) associations. Click on a defined association to instantiate its roles. Then click on a role to open an object editor for that persistent object. With this tool becomes very easy to navigate all related objects of a given one.  Clear Values. Clear all field values.  From Object. Populate screen from object data.  To Object. Populate object attributes from screen data.  New Object. Instantiate a new object of the same class and populate screen accordingly.
  • 45. M A P P I N G T O O L U S E R S ’ G U I D E  Retrieve. Retrieve a new object from database using the screen data entered in the attribute values to build the where clause.  Refresh. Read the object again from database and show data on screen.  Save Tree. Save object graph. Save all modified objects that can be reached from the current object by navigating instantiated relationships.  Delete Tree. Delete object graph. Delete all objects that can be reached from the current object by navigating instantiated relationships.  Clone. Create a new object having the same attribute values as current one. Will not save the object to database. Autoincrementors and discriminators will not be cloned and will be instantiated once the user will choose to save object to database  Delete. Delete current object from database.  Close. Close current editor window and all children windows opened from current one. Will not save objects to database.
  • 46. P R O G R A M M E R S ’ G U I D E ObjectView Persistency Layer Programmers’ Guide Introduction his guide explains the ObjectViewPL persistency API. The sample mapping application provided together with the framework library will be used in this guide to illustrate the API usage. Before objects can be persisted using OVPL, mappings must be defined correctly. For help using the Workbench to generate mapping classes see the chapter 3 – Mapping Tool Users’ Guide. T The Sample Model The pictured bellow sample class model will be used to exemplify ObjectViewPL features. Let’s say we have a company that is selling services over Internet and we have modeled the following java business classes:  BusinessEntity. Defines a business partner or a business customer. It can be represented by a Company or an individual (Person).  Member. A Business Entity that has a valid subscription for services we provide.  Account. Two types of accounts: ExternalAccount used by Members to pay for the services our company provides, MemberAccount used to keep internal accounting for members (balance owning, invoice history, default external account used for automate debit,…). A Member has many MemberAccounts, one of them defined as the default member account.  AbstractExternalAccount. An abstract class – no persistent state – introduced here mainly to show some mapping features. Chapter 4
  • 47. P R O G R A M M E R S ’ G U I D E  B2bRelationship. Models the relationships between two business entities. parentBusiness and relatedBusiness are the two possible roles - i.e. a person working for a company can be modeled using parentBusiness role. Account - accountId : java.lang.Integer = null - accountName : java.lang.String = null - accountType : java.lang.String = null - balanceAmt : double = 0 - ownerBeId : java.lang.Integer = null ExternalAccount - externalAccountId : java.lang.Integer = null - accountValidityConfirmedB : boolean = false - externalAccountType : java.lang.String = null AbstractExternalAccount + AbstractExternalAccount ( ) BankAccount - bankAccountAccountId : java.lang.Integer = null - accountSnumber : java.lang.String = null - bankSnumber : java.lang.String = null - holderName : java.lang.String = null - transitSnumber : java.lang.String = null CreditCard - creditCardAccountId : java.lang.Integer = null - creditCardNumberRaw : byte = null - creditCardType : int = 0 - expiryDate : java.sql.Date = null - holderName : java.lang.String = null Cheque MemberAccount - memberAccountId : java.lang.Integer = null - defaultPaymentAccountId : java.lang.Integer = null - memberId : java.lang.Integer = null - paperBillAddressId : java.lang.Integer = null - statementFrequencyType : java.lang.String = null - defaultPaymentAccount BusinessEntity - beId : java.lang.Integer = null - beType : java.lang.String = null - notesString : java.lang.String = null + isPerson ( ) - businessEntity Person - personBeId : java.lang.Integer = null - ageType : java.lang.String = null - birthDate : java.sql.Date = null - childrenNumber : int = 0 - firstName : java.lang.String = null - genderType : java.lang.String = null - lastName : java.lang.String = null - maritalStatusType : java.lang.String = null - socialSecuritySnumber : java.lang.String = null - memo : java.lang.String = null ... ... Company - companyBeId : java.lang.Integer = null - companyName : java.lang.String = null - contactPersonBeId : java.lang.Integer = null - totalRevenueType : java.lang.String = null B2bRelationship - beId : java.lang.Integer = null - relatedBeId : java.lang.Integer = null - relationshipStype : java.lang.String = null - parentBusiness - relatedBusiness Member - memberId : java.lang.Integer = null - businessEntityId : java.lang.Integer = null - defaultMemberAccountId : java.lang.Integer = null - lastVisitDatetime : java.sql.Timestamp = null - loginPassword : java.lang.String = null - loginString : java.lang.String = null - member - businessEntity - defaultMemberAccount - member Mapping Example - Class Diagram
  • 48. P R O G R A M M E R S ’ G U I D E Mapping Example - Database Diagram
  • 49. P R O G R A M M E R S ’ G U I D E Workbench settings Here are the projects properties and run configurations created for eclipse IDE I have used to run the samples described in the chapters bellow. Bellow please find the settings used to configure ObjectViewMappingsDemo. The libraries used reflect my environment:
  • 50. P R O G R A M M E R S ’ G U I D E Persistent Classes ersistent classes are generated using the OVPL mapping tool. See previous chapter for the mapping rules and tool usage screenshots and the section referring to ObjectView properties. Let’s look at a generated class:Ppackage com.objectview.examples.domain; import com.objectview.jdb.*; //===ObjectView generated=== import com.objectview.util.*; //===ObjectView generated=== import java.sql.*; //===ObjectView generated=== import java.util.*; //===ObjectView generated=== public class B2bRelationship extends com.objectview.jdb.JDBPersistentObject //===ObjectView generated=== { //===ObjectView generated=== private java.lang.Integer beId=null;//===ObjectView generated=== private java.lang.Integer relatedBeId=null;//===ObjectView generated=== private java.lang.String relationshipStype=null;//===ObjectView generated=== public static final String FLD_BE_ID="BE_ID";//===ObjectView generated=== public static final String ATTR_beId="beId";//===ObjectView generated=== public static final String FLD_RELATED_BE_ID="RELATED_BE_ID";//===ObjectView generated=== public static final String ATTR_relatedBeId="relatedBeId";//===ObjectView generated=== public static final String FLD_RELATIONSHIP_STYPE="RELATIONSHIP_STYPE";//===ObjectView generated=== public static final String ATTR_relationshipStype="relationshipStype";//===ObjectView generated=== private com.objectview.examples.domain.BusinessEntity parentBusiness=null;//===ObjectView generated=== private com.objectview.examples.domain.BusinessEntity relatedBusiness=null;//===ObjectView generated=== //===ObjectView generated begin=== /** * Persistent Attribute: JDBAttributeMap { beId >> BE_ID } * Primary Key. * Not nullable db value * @showas hidden * @objectview:method.id 10.1.getBeId * @return java.lang.Integer */ public java.lang.Integer getBeId () { // user.code.begin {1}.10.1.getBeId // user.code.end {1}.10.1.getBeId return beId;
  • 51. P R O G R A M M E R S ’ G U I D E } //===ObjectView generated end=== ….. //===ObjectView generated begin=== /** * Class method for retrieving all objects of this type based on a custom sql * it will try to instantiate all objects based on the result set comming for the sql sent * @objectview:method.id 26.2.retrieve * @showas hidden */ public static java.util.Vector retrieveAllUsingSQL ( JDBSession session, String sqlString ) throws SQLException, RollbackException, ObjectAccessException { java.util.Vector collection = JDBPersistentObject.retrieveAllUsingSQL ( "com.objectview.examples.domain.B2bRelationship", session, sqlString ) ; // user.code.begin {1}.26.2.retrieve // user.code.end {1}.26.2.retrieve return collection; } //===ObjectView generated end=== } To make possible further changes and code to be added to generated classes, each line or code block generated automatically by the mapping tool is being marked with a special comment. Lines are marked with the comment //===ObjectView generated=== blocks are captured between //===ObjectView generated begin=== and //===ObjectView generated end===. You may add any imports, fields, methods, inner classes as desired. You may also change part of the method signature by adding new Exceptions thrown and you may add new interfaces to the implements class definition. If extra code needs to be added inside generated methods - in order to be preserved following next class generation operation - it must be added between // user code begin and // user code end comments. JavaDoc comments added for each attribute will also be preserved at next class source generation – this because some UML tools (i.e. TogetherJ, Rational XDE, etc) will add their own comments to java source files to keep java source and model in synch. In the code shown bellow one can see the user added code in blue color: package com.objectview.examples.domain; import com.objectview.jdb.*; //===ObjectView generated=== import com.objectview.util.*; //===ObjectView generated=== import java.sql.*; //===ObjectView generated=== import java.util.*; //===ObjectView generated=== import mypackage; public class B2bRelationship extends com.objectview.jdb.JDBPersistentObject //===ObjectView generated=== implements MyInterface { //===ObjectView generated=== /** ID 10000101 **/ private java.lang.Integer beId=null;//===ObjectView generated=== private int myAttribute; private java.lang.Integer relatedBeId=null;//===ObjectView generated=== private java.lang.String relationshipStype=null;//===ObjectView generated=== public static final String FLD_BE_ID="BE_ID";//===ObjectView generated=== public static final String ATTR_beId="beId";//===ObjectView generated=== public static final String FLD_RELATED_BE_ID="RELATED_BE_ID";//===ObjectView generated===
  • 52. P R O G R A M M E R S ’ G U I D E public static final String ATTR_relatedBeId="relatedBeId";//===ObjectView generated=== public static final String FLD_RELATIONSHIP_STYPE="RELATIONSHIP_STYPE";//===ObjectView generated=== public static final String ATTR_relationshipStype="relationshipStype";//===ObjectView generated=== private com.objectview.examples.domain.BusinessEntity parentBusiness=null;//===ObjectView generated=== private com.objectview.examples.domain.BusinessEntity relatedBusiness=null;//===ObjectView generated=== //===ObjectView generated begin=== /** * Persistent Attribute: JDBAttributeMap { beId >> BE_ID } * Primary Key. * Not nullable db value * @showas hidden * @objectview:method.id 10.1.getBeId * @return java.lang.Integer */ public java.lang.Integer getBeId () { // user.code.begin {1}.10.1.getBeId System.out.println(“I’ve been here”); // user.code.end {1}.10.1.getBeId return beId; } //===ObjectView generated end=== ….. private void myMethod() { // do something } //===ObjectView generated begin=== /** * Class method for retrieving all objects of this type based on a custom sql * it will try to instantiate all objects based on the result set comming for the sql sent * @objectview:method.id 26.2.retrieve * @showas hidden */ public static java.util.Vector retrieveAllUsingSQL ( JDBSession session, String sqlString ) throws SQLException, RollbackException, ObjectAccessException , MyException{ java.util.Vector collection = JDBPersistentObject.retrieveAllUsingSQL ( "com.objectview.examples.domain.B2bRelationship", session, sqlString ) ; // user.code.begin {1}.26.2.retrieve throw new MyException(“No worries”); // user.code.end {1}.26.2.retrieve return collection; } //===ObjectView generated end=== } Database Connection atabase connections are wrapped within the JDBSession class. The JDBSession class responsibilities are: opening and closing a java.sql.Connection, commit control, instance cacheing, connection pooling. There are 2 ways to create a database connection using JDBSession: D  Let ObjectViewPL obtain a java.sql.Connection.  Passing a java.sql.Connection object to JDBSession constructor.
  • 53. P R O G R A M M E R S ’ G U I D E Let ObjectView obtain a java.sql.Connection This is the default method and it uses the objectview.properties settings to obtain the database connection. The method used in this case is JDBSystem.acquireConnection() with no other parameters. There are mainly two ways of configuring ObjectViewPL properties to obtain a java.sql.Connection: 1. Obtain a connection using java.sql.DriverManager. The configured properties in this case are: • DB_CONNECTION_POOL_USE_EXTERNAL_POOL=false • JDB_JDBC_DRIVER • DB_CONNECTION_URL • DB_CONNECTION_USER_ID • DB_CONNECTION_PASSWORD 2. Obtain a connection from and external pool using datasource interfaces. In this case the necessary properties that needs to be configured are: • DB_CONNECTION_POOL_USE_EXTERNAL_POOL=true • INITIAL_CONTEXT_FACTORY • PROVIDER_URL • SECURITY_PRINCIPAL • SECURITY_CREDENTIALS • DATA_SOURCE_JNDI_NAME After properties are configured, the default method to acquire a session is JDBSystem.acquireConnection(), as the following code fragment illustrates: ….. JDBSession session = null; try { session = JDBSystem.acquireConnection(); Hashtable where = new Hashtable(3); where.put(Member.ATTR_loginString, "login1"); try { Vector v = Member.retrieveAll(session, where); for (Iterator iter = v.iterator(); iter.hasNext();) { Member element = (Member) iter.next(); } } catch (RollbackException e1) { e1.printStackTrace();
  • 54. P R O G R A M M E R S ’ G U I D E } catch (ObjectAccessException e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } catch (ObjectPoolException e) { e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } Passing a java.sql.Connection to ObjectViewPL This method is used to create a JDBSession object after we have obtained a java.sql.Connection object (wrap an existing java.sql.Connection). The connection can be obtained from an external datasource (i.e. owned by an EJB container) or using the jdbc API. This method of connecting ObjectViewPL is used to facilitate working with different data sources. For example read an Excell file and save its content in a RDBMS. The method used to connect using an existing java.sql.Connection is JDBSystem.acquireConnection(connection, isExternalMonitor). If isExternalMonitor parameter is true, this tells ObjectViewPL that transactions are managed externally and any calls to JDBSession.begin/commitTransaction() are ignored. External Transaction Monitor Integration User can configure ObjectviewPL to connect to an external data source and obtain database connections from and external connection pool or obtain such connections outside ObjectViewPL and let persistent mechanism know that transactions are managed outside. ObjectViewPL permits integration with and external transaction monitor thus allowing the user to embrace all the benefits from such integration. Important: if a connection is obtained from an external transaction monitor and managed externally, then user must let ObjectViewPL be aware of this fact by using JDBSession.acquireConnection(java.sql.Connection conn, boolean externalTransactionMonitor) method and setting the second parameter to true. public class ConnectionDemo { 
  • 55. P R O G R A M M E R S ’ G U I D E public static void main(String[] args) { JDBSession jdbSession = null; try { Connection conn = getConnectionFromExternalPool(); // obtain a JDBSession object from extrenal pool, let ObjectViewPL know // the connection was obatained from an external pool in order to let transactions // be managed by the application server's transaction monitor. jdbSession = JDBSystem.acquireConnection( conn, true); System.out.println(jdbSession); } catch (NamingException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } catch (ObjectPoolException e1) { e1.printStackTrace(); } finally { try { JDBSystem.releaseConnection(jdbSession); } catch (RollbackUncommitedSession e2) { e2.printStackTrace(); } catch (SQLException e2) { e2.printStackTrace(); } } } /** * This method show how to obtain a Connection from an external datasource. * I have used the weblogic server to configure a connection pool for my local oracle XE database * and set the datasource jndi name to <com.objectview.demoDataSource>. * * The connection factory, provider url and jndi name can be set in objectview.properties file * and if the DB_CONNECTION_POOL_USE_EXTERNAL_POOL property is set to true then the * java.sql.Connection will always be obtained from the external pool * when using the method JDBSystem.acquireConnection(). * * @return * @throws NamingException * @throws SQLException */ private static java.sql.Connection getConnectionFromExternalPool() throws NamingException, SQLException { Context ctx = null; Hashtable ht = new Hashtable(); ht.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); ht.put(javax.naming.Context.PROVIDER_URL, "t3://localhost:7001"); ctx = new javax.naming.InitialContext(ht); DataSource ds = (javax.sql.DataSource) ctx.lookup ("com.objectview.demoDataSource"); java.sql.Connection conn = ds.getConnection();
  • 56. P R O G R A M M E R S ’ G U I D E return conn; } } Retrieving and Persisting Objects bjectviewPL provides methods for storing, deleting and retrieving objects from persistent storage for all mapped types. Mappings are created using the OVPL mapping tool. See previous chapter for the mapping rules and tool usage screenshots and the section referring to ObjectView properties. From database point of view ObjectviewPL methods translate in four types of requests: selects (joins), inserts, updates and deletes. From object point of view there are two types of methods: save and retrieve. O Retrieving objects To retrieve persistent state ObjectView creates Java objects and populates them with database fields based on mapping configuration. Retrieving individual objects When primary keys are used, ObjectViewPL will instantiate one object based on primary key value. The generated methods to retrieve objects based on primary key value are:  retrieve(Object pkValue)  retrieve(Hastable pkValueDict)  findByPrimaryKey(Object pkValue1, Object pkValue2, …)  retrieveAll(Hashtable whereDict) if whereDict consists of primary keys. If primary keys consists of more than one key, only retrieve(Hastable pkValueDict) method will be generated and a Hashtable consisting of fieldName-objectValue pairs must be created and passed as parameter. However, if finders are generated (see mapping Workbench application guide) then a findByPrimaryKey() method will be generated having one parameter for each primary key. If a Hashtable is to be build and send as method parameter, then the keys represent the java attribute names and the values the corresponding attribute value. Retrieving object collections To retrieve object collections use the retrieveAll() methods. In its most generic form this method signature is :
  • 57. P R O G R A M M E R S ’ G U I D E  retrieveAll ( JDBSession session, Hashtable whereDict, String orderBy, String customWhereClause ).  retrieveAllUsingSQL ( JDBSession session, String sqlString ) The whereDict parameter is a Hashtable having the keys as the java attribute names and the values the corresponding values to be used in the where clause, orderBy parameter represents the order by clause and will be appended to the generated SQL statement, customWhereClause represents the additional where clause to be added to the generated one. It is recommended to use ANSI SQL format for any supply SQL fragment for portability among different databases. If the whole SQL is given then the objects are instantiated from result set matching attribute names. If objects represent a type-subtype mapping using different tables, then a join should be supplied to involve all tables. If helper tables where used in mapping the candidate java class, then the join should include any helper table mapped. To see some java code examples of retrieving objects look at the java examples supplied or included in this documentation bellow Saving Objects paragraph. Saving Objects The method used to change object’s persistent state or status is the save() method. Call this method on any persistent object (mapped with ObjectViewPL) and ObjectViewPL will translate the call to the right database operation. Insert To create a new objects use null or customized constructor, set the attributes to desired values and call save method against that object. If set so in mapping, autoincrementors and primary keys will be retrieved prior or after the save operation and will be set in the corresponding object’s attribute. Here is a code snippet to illustrate a database insert: public static void insertDemo() { JDBSession session = null; try { session = JDBSystem.acquireConnection(); // create a new person. Do no set incrementors or discriminators since they // are handled by ObjectViewPL. Person person = new Person(); person.setFirstName("Donald"); person.setLastName("Duck"); person.setGenderType("M"); person.setMaritalStatusType("M"); person.setSocialSecuritySnumber("1112222"); person.save(session);
  • 58. P R O G R A M M E R S ’ G U I D E testPersonId=person.getPersonBeId(); // Person is persisted and PK and discriminator values are set. System.out.println(person.toXml(false)); } catch (ObjectPoolException e) { e.printStackTrace(); } catch (RollbackException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ConcurrencyException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ObjectAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Do not set any autoincrementors or discriminators directly if a policy to obtain a value for such fields was defined in mapping. ObjectViewPL will retrieve and set these values. However if IDs are set they will be used (at user request) instead and ObjectViewPL will not try to obtain new ones. The special fields user does not need to care about setting their values are:  Primary keys  Autoincrementors: sequences, identity fields, GUIDs, etc.  Update controllers  Foreign keys  Type-subtype discriminators (type-subtype filtering)  Formulas and read-only fields. Update To update an object first you need to retrieve that object from database – so, for the next save operation to be an update request, object must be retrieved from database first. Then modify any persistent attributes and call the save method to make the changes persistent. 
  • 59. P R O G R A M M E R S ’ G U I D E public static void updateDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // retrieve a person from database. We will use a primary key to retrieve one // object and not a collection. Person person = (Person) Person.retrieve(session, testPersonId); person.setFirstName("Duffy"); person.setMemo("Donald Duck incognito"); person.save(session); System.out.println(person.toXml(false)); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Only objects that have been modified from last retrieve operation will be saved to database. ObjectViewPL keeps the last committed state of an objects and in order to minimize database I/O by issuing unnecessary statements will check current state against committed state. Delete Like update, to delete an object must first retrieve that object from database (only persistent objects can be deleted). There are two methods to do a delete: 1. Call the delete method 2. Mark the object for deletion an call the save method public static void deleteDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // retrieve a person from database. We will use a primary 
  • 60. P R O G R A M M E R S ’ G U I D E // key to retrieve one object and not a collection. Person person = (Person) Person.retrieve(session, testPersonId); person.delete(session); // person object is not persistent System.out.println("Persistent status:" + person.isPersistent()); System.out.println(person.toXml(false)); // the next save() operation against person object will be an insert. // to obtain a new id we must set null to the PersonBeId field, otherwise // the old Id will bereused. person.setPersonBeId(null); // !! if this not set, old id will be used. person.save(session); System.out.println("Persistent status:" + person.isPersistent()); System.out.println("Person Id:" + person.getPersonBeId()); // now mark object for deletion to be deleted by next save() operation person.markForDeletion(); person.save(session); System.out.println("Persistent status:" + person.isPersistent()); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Saving Object Graphs From database point of view saving an object graph consists of inserts, updates, deletes operations issued in one transaction for an entire object graph. From java point of view an object graph consists of all objects in VM memory that can be reached following mapped relationships starting from a given object. The method used for this operation is saveAll method from JDBPersistentObject class. This method saves an object and all its instantiated relationships to the database in the same db transaction. Only related objects that have been modified since the last retrieve operation will be saved to database. The order of the performed operations is:
  • 61. P R O G R A M M E R S ’ G U I D E  -Delete objects marked for deletion and cascade deletes (if configured so in mapping) dependents. Remove object references for deleted objects for the objects for which markForDeletionAndRemoveReferences() method was called before issuing saveAll().  -Insert new objects and modify existing ones.  -Export keys to children (dependents in relationships) after saving.  -Import keys from parents after saving. Recursive relationships are handled in the following way: If 2 classes have 2 relationships defined, on different keys, and each association have a different parent, then the one that will be saved first is the one configured as identifiable when association was mapped in ObjectView Workbench. The parent object will be saved twice, once to export its keys and second time with the imported keys from recursive relation. If you need to add more behaviour than the one described here to this method, then subclass saveAll( JDBSession session) method to add your custom code and then call super.saveAll( session) method to have all happening in one transaction. Just make sure all methods called inside saveAll(session) are called with the same session object to have all database operations handled in the same transaction context. To remove references of deleted objects in the context of an object graph, call the method markForDeletionAndRemoveReferences() and then call saveAll(); public static void saveAllDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // retrieve a person from database. Person person = (Person) Person.retrieve(session, new Integer(2)); // make some changes to this object person.setFirstName("Duffy"); person.setLastName("Duck"); // retrieve associated accounts for (Iterator iter = person.getAccountsSubType(session).iterator(); iter.hasNext();) { Account account = (Account) iter.next(); if (account.isExternalAccount()) { if ( ((ExternalAccount)account).isCreditCard()) { // this was added in a previous run of this method account.markForDeletionAndRemoveReferences(); } else { account.setAccountName("Duffy Duck"); } } } // add another account (the previous one we marked for deletion)
  • 62. P R O G R A M M E R S ’ G U I D E CreditCard cc = new CreditCard(); cc.setAccountName("Duffy's Mastercard"); cc.setHolderName("Duffy Duck"); cc.setCreditCardType(1); cc.setExpiryDate(new Date(System.currentTimeMillis())); cc.setBalanceAmt(100); person.addToAccounts(cc, session); // persist all changes (insert, update, delete) person.saveAll(session); // print graph in xml format, including relationships // We should find only 2 accounts. One was modified, one deleted, one added. System.out.println(person.toXml(true)); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } SaveAll with check Same as saveAll method but ObjectViewPL will check the persistent state against DB for each object to be saved. If object is found in database then an update will be issued, otherwise an insert. This method is useful for saving object graphs from one database to another one, or for XML imports, or in any case when object was not retrieved from the same database in which is to be saved but they might exist there. This method makes used of the checkPersistentStatus() method and calls it prior to saving the object graph. public static void importDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // retrieve a person from database. Person person = (Person) Person.retrieve(session, new Integer(2)); // make some changes to this object person.setFirstName("Donald"); person.setLastName("Duck");
  • 63. P R O G R A M M E R S ’ G U I D E person.setMemo("endagered species"); // this will go to the help table // retrieve associated accounts person.getAccountsSubType(session); // export to xml String xml = person.toXml(true); // convert xml back to objects Vector objs = Person.fromXml(xml); JDBPersistentObject importedObj = (JDBPersistentObject) objs.firstElement(); // now import this back to DB // use the saveWithCheck option to perform updates of existing objects importedObj.saveAllWithCheck(session); System.out.println(importedObj.toXml(true)); // now get another set of objects from the same xml String Vector objs2= Person.fromXml(xml); Person importedDuck2 = (Person) objs2.firstElement(); importedDuck2.setFirstName("Donald The Second"); importedDuck2.setLastName("Cloned Duck"); // if we save this object graph without the check option we get brand new // objects in database,because the next save operation // will results in inserts since they represent new objects that were // build in memory and not retrieved directly from database. // But first, we must make the PK's null because by default if PKs are set // by the user ObjectViewPL will not try to obtain new ones. // ObjectViewPL provides a method for this purpose only. // resetAutoincrementors(boolean includeRelations); importedDuck2.resetAutoincrementors(true); // now we can get the new object graph insert importedDuck2.saveAll(session); System.out.println(importedDuck2.toXml(true)); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } }
  • 64. P R O G R A M M E R S ’ G U I D E ObjectViewPL provides methods to handle object graphs. Object graphs combined with xml serialization can be used to in export- import operations. ObjectViewPL can handle recursive associations. All primary and foreign keys are handled internally and transparent for the user. Setting and Retrieving Relationships Relationships are set at the object level and are persisted calling the save or saveAll operations. At the object level relationships are set/reset using the provided (generated) setters and getters. When a relationship between to persistent objects is set the foreign keys are migrated automatically – if objects are new, they will migrate in the save operation. There is no need for user to manage object ids (primary and foreign keys).  To add an object to an existing set of related objects, use the addToxxx() generated methods. This method will not persist any changed made. To make the changed persistent user needs to call save() operation for each object that imported the value for its foreign key from a parent object. A simpler way is to call saveAll on parent graph.  To delete a related object use the deleteXxx() generated method on the parent object. This method will delete the related object from database and from object referenced roles collection.  To instantiate a relationships call the generated relationship getter.  To retrieve roles as individual collections (not set in any object context) use the finders generated methods. Relations can be obtain from database together with the parent object (in the same select/join statement) to speed up access and minimize I/O if configured so in the mapping process. public static void relationshipsDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // retrieve a person from database. Person person = (Person) Person.retrieve(session, new Integer(2)); // now add a new account CreditCard newCC = new CreditCard(); newCC.setCreditCardType(1); newCC.setExpiryDate(new Date(System.currentTimeMillis())); newCC.setHolderName(person.getFirstName()+" " + person.getLastName()); // retrieve existing accounts and add this new one to relationship collection 
  • 65. P R O G R A M M E R S ’ G U I D E // notice that because accounts relationship was mapped as to retrieve subtypes // each time, the accounts subtypes are retrieved in the accounts collection. person.addToAccounts(newCC,session); // persist changes. this will insert the new account in the database // and will set the foreign key ownerBeId person.saveAll(session); // if account would have been a persistent object already CreditCard newCC2 = new CreditCard(); newCC.setCreditCardType(2); newCC2.setExpiryDate(new Date(System.currentTimeMillis())); newCC2.setHolderName(person.getFirstName()+" " + person.getLastName() + " VISA"); // save account first newCC2.save(session); // set relationship person.addToAccounts(newCC2, session); // save account back in database to persist the relation //(store the ownerBeId foreign key) newCC2.save(session); // show person with the new added credit cards System.out.println(person.toXml(true)); // now delete the two credit cards added previously person.deleteAccount(newCC, session); person.deleteAccount(newCC2, session); // show person without the above credit cards System.out.println(person.toXml(true)); // call the relation getter with a custom where clause // Notice that because the where clause changed, // relation will be instantiated again person.getAccounts(session,null,Account.FLD_BALANCE_AMT+"=100" ); System.out.println(person.toXml(true)); // to force retrieving the roles from database again, reset the related roles to null person.setAccounts(null); person.getAccounts(session); // will retrieve accounts from db again. System.out.println(person.toXml(true)); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } }
  • 66. P R O G R A M M E R S ’ G U I D E } Aside of the where clause and order by clause set in mapping that has effect for all retrieve operations involving that particular relation, user can set (or add) a different where clause and order by clause to have effect on current retrieve operation using relationships getters like: person.getAccounts ( JDBSession aSession, String customOrderBy, String customWhere). Because relations are cached in the role instance variable, each time the relationship getter is called with a different where clause, ObjectViewPL will refresh the relation from database. Relationships can be retrieved using the generated finders (see Mapping Tool User Guide) case in which one findBy… method will be generated for each relationship. However, calling the finders will not instantiate the role attributes (relation will not be cached nor set at the object level) and object graphs will not be instantiated nor can they be used. User is free to choose which method is best to use (instantiated roles or finders) based on application constraints such as memory trace, serialization, and so on. Many to many relationships ObjectViewPL maps this type of association using an association class. The generated association class is treated like any other persistent class, except there are additional methods generated in the main classes to set and get the many-to-many relationships. The association class may have additional attributes to describe the business state of the association itself. In this case association class is a business class and the many-to- many relationship in discussion will be set and get through the association class explicitly. public static void manyToManyDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); Company company = (Company) Company.findByPrimaryKey(session, new Integer(7)); // we have defined a many-to-many relationship to the same class. This is // a special case of relationship, oftere referred as circular relationship. // We would like to show that saveAll handles correctly such object graph. // To make things even more complicated, many-to-many relationship is // defined at the supertype level. // The roles can be Companies or Persons, both subtypes of BusinessEntity BusinessEntity be = (BusinessEntity) company; // get the many to many relationships Vector relatedBes = be.getRelatedBusinesses(session); for (Iterator iter = relatedBes.iterator(); iter.hasNext();) {
  • 67. P R O G R A M M E R S ’ G U I D E BusinessEntity relatedBe = (BusinessEntity) iter.next(); } // add another related business Company newComp = new Company(); newComp.setCompanyName("ABC French Delicatessen"); newComp.setNotesString("catering"); relatedBes.add(newComp); be.setRelatedBusinesses(session,relatedBes); // must be called be.saveAll(session); System.out.println(company.toXml(true)); // now remove the just added company to the related businesses // this method will remove the b2b relationship from both // database and object graph be.deleteRelatedBusiness(newComp, session); System.out.println(company.toXml(true)); // also remove the new added company newComp.delete(session); // another way of setting a many to many realationships is // working directly with the association class // This method will be used if association class has // also a business meaning - i.e. has attributes to describe // the relationship. In our case such an attribute is relationshipType // lets create a new business entity, // lets say a Contract mediator person Person mediator = new Person(); mediator.setFirstName("Joe"); mediator.setLastName("Mediator"); mediator.setGenderType("M"); mediator.setMaritalStatusType("S"); // create a new association class B2bRelationship b2bRel = new B2bRelationship(); b2bRel.setRelatedBusiness((BusinessEntity)mediator); // set association attribute b2bRel.setRelationshipStype("mediator"); be.addToB2bRelationships(b2bRel, session); // of course objects can be saved individually, but saveAll is making // save operation easier. be.saveAll(session); System.out.println(company.toXml(true)); // now delete the just added person (mediator) relationship be.deleteRelatedBusiness(mediator, session); System.out.println(company.toXml(true)); // also delete the new added Person (mediator) mediator.delete(session); } catch (ObjectViewApplicationException e) { e.printStackTrace();
  • 68. P R O G R A M M E R S ’ G U I D E } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Types and Subtypes. Cast down policies. In the case objects involved in relationships represent hierarchies mapped as java inheritance, user has a choice of instantiating the supertype or the subtype for each such object. Why would you want to instantiate a superType and not the subtype? The answer relies on performance reasons. Lets say that in order to get to a business object C you need to pass object B in a relationship chain like A->B->C. Lets also say that B is a type-subtype hierarchy mapped to different tables. In this case it would not be necessary to retrieve the whole B type-subtype hierarchy just to retrieve the foreign key needing to retrieve C object. B in this case will only serve as a pas-by step and user might consider useful to avoid retrieving the B hierarchy tree. However if user chose to map the relationship as always retrieving subtype (see Workbench mapping application) then subtypes will always be retrieved. Once the user retrieved subtypes he can always retrieve the whole object subtype hierarchy is he/she wishes so by calling castDownToSubtype() methods. A subtype version of the association role getter is also generated for the case when related object is mapped as a type-subtype hierarchy. Retrieving relationships using customized join requests Another way of minimizing database i/o and improving performances in critical situations is to retrieve associations using a custom join. The method to use in this case is retrieveJoinedRoles ( JoinRequest[] joinRequests ) and calling the method will result in only one select statement issued and processed for all objects retrieved. The joinRequests parameter is a Vector with JoinRequest objects. (See the JoinRequest class comment for usage description). Because it uses only one Select statement consisting of multiple table join, this method has some limitations:
  • 69. P R O G R A M M E R S ’ G U I D E  Cannot have more than one one-to-many relationship in the request  Only first relation in the request is allowed to be a one-to-many relationship  Can only have one subtype castdown in the request. Examples of an accepted join request: A (*) B (1)C(1)D(subtypes) Example of a rejected join requests: A  (*) B (*)C -more that one one-to-many relations A  B (*)C D -one-to-many relation not the first one in request A  D(subtypes)  E(subtypes) -more than one subtype requested RetrieveJoinedRoles() method stores the retrieved associated objects in each parent object as relationship roles. This means that after this method completes, results are cached in role variables - so for example after executing this method for a join configuration: A --> (*) B -->(1)C --- (1)D(subtypes), A.getBs() will return the B objects without going to database, as well C.getDsSubtype(). Java code example: Company company2 = (Company) Company.findByPrimaryKey(session, new Integer(7)); BusinessEntity be2 = (BusinessEntity) company2; // JoinRequest( String roleName, // String customOrderBy, // String customWhereClause , // boolean castDown ) { JoinRequest[] jr2 = new com.objectview.jdb.JoinRequest[] { new JoinRequest("b2bRelationships", B2bRelationship.FLD_RELATIONSHIP_STYPE+ " desc",null, false ), new JoinRequest("relatedBusiness", null,null, true ), new JoinRequest("member", null,null, false ), new JoinRequest("defaultMemberAccount", null,null, false ), new JoinRequest("defaultPaymentAccount", null,null, false ) }; // retrieve all roles described above in one sql statement be2.retrieveJoinedRoles(jr2, session); // lets see what roles were retrieved System.out.println(company2.toXml(true)); The example above will produce the following SQL:
  • 70. P R O G R A M M E R S ’ G U I D E SELECT B2B_RELATIONSHIP1.BE_ID,B2B_RELATIONSHIP1.RELATED_BE_ID, B2B_RELATIONSHIP1.RELATIONSHIP_STYPE,BUSINESS_ENTITY2.BE_ID, BUSINESS_ENTITY2.BE_TYPE,BUSINESS_ENTITY2.NOTES_STRING, BUSINESS_ENTITY2.ROW_UPDATE_NUMBER, PERSON1.PERSON_BE_ID,PERSON1.AGE_TYPE,PERSON1.BIRTH_DATE,PERSON1.CHILDREN_NUMBER, PERSON1.FIRST_NAME,PERSON1.GENDER_TYPE,PERSON1.LAST_NAME, PERSON1.MARITAL_STATUS_TYPE,PERSON1.SOCIAL_SECURITY_SNUMBER, EX1_PERSON_MEMO1.PERSON_BE_ID,EX1_PERSON_MEMO1.MEMO, MEMBER1.MEMBER_ID,MEMBER1.BUSINESS_ENTITY_ID,MEMBER1.DEFAULT_MEMBER_ACCOUNT_ID, MEMBER1.LAST_VISIT_DATETIME,MEMBER1.LOGIN_PASSWORD,MEMBER1.LOGIN_STRING, BUSINESS_ENTITY3.BE_ID,BUSINESS_ENTITY3.BE_TYPE,BUSINESS_ENTITY3.NOTES_STRING, BUSINESS_ENTITY3.ROW_UPDATE_NUMBER,ACCOUNT1.ACCOUNT_ID,ACCOUNT1.ACCOUNT_NAME, ACCOUNT1.ACCOUNT_TYPE,ACCOUNT1.BALANCE_AMT, ACCOUNT1.LAST_UPDATE_DATETIME,ACCOUNT1.OWNER_BE_ID,ACCOUNT1.ROW_UPDATE_NUMBER, MEMBER_ACCOUNT1.MEMBER_ACCOUNT_ID,MEMBER_ACCOUNT1.DEFAULT_PAYMENT_ACCOUNT_ID, MEMBER_ACCOUNT1.MEMBER_ID,MEMBER_ACCOUNT1.PAPER_BILL_ADDRESS_ID, MEMBER_ACCOUNT1.STATEMENT_FREQUENCY_TYPE,ACCOUNT2.ACCOUNT_ID, ACCOUNT2.ACCOUNT_NAME,ACCOUNT2.ACCOUNT_TYPE,ACCOUNT2.BALANCE_AMT, ACCOUNT2.LAST_UPDATE_DATETIME,ACCOUNT2.OWNER_BE_ID,ACCOUNT2.ROW_UPDATE_NUMBER, EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_ID, EXTERNAL_ACCOUNT1.ACCOUNT_VALIDITY_CONFIRMED_B, EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_TYPE,EXTERNAL_ACCOUNT1.LAST_UPDATE_DATETIME, EXTERNAL_ACCOUNT1.ROW_UPDATE_NUMBER FROM BUSINESS_ENTITY BUSINESS_ENTITY1, COMPANY COMPANY1, B2B_RELATIONSHIP B2B_RELATIONSHIP1, BUSINESS_ENTITY BUSINESS_ENTITY2, PERSON PERSON1, EX1_PERSON_MEMO EX1_PERSON_MEMO1, MEMBER MEMBER1, BUSINESS_ENTITY BUSINESS_ENTITY3, ACCOUNT ACCOUNT1, MEMBER_ACCOUNT MEMBER_ACCOUNT1, ACCOUNT ACCOUNT2, EXTERNAL_ACCOUNT EXTERNAL_ACCOUNT1 WHERE COMPANY1.COMPANY_BE_ID=? AND COMPANY1.COMPANY_BE_ID=BUSINESS_ENTITY1.BE_ID AND BUSINESS_ENTITY1.BE_ID=B2B_RELATIONSHIP1.BE_ID AND PERSON1.PERSON_BE_ID=BUSINESS_ENTITY2.BE_ID AND PERSON1.PERSON_BE_ID=EX1_PERSON_MEMO1.PERSON_BE_ID AND B2B_RELATIONSHIP1.RELATED_BE_ID=BUSINESS_ENTITY2.BE_I AND BUSINESS_ENTITY2.BE_TYPE=? AND BUSINESS_ENTITY3.BE_ID=MEMBER1.BUSINESS_ENTITY_ID AND MEMBER1.BUSINESS_ENTITY_ID(+)=BUSINESS_ENTITY3.BE_ID AND MEMBER_ACCOUNT1.MEMBER_ACCOUNT_ID=ACCOUNT1.ACCOUNT_ID AND MEMBER1.DEFAULT_MEMBER_ACCOUNT_ID=MEMBER_ACCOUNT1.MEMBER_ACCOUNT_ID AND EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_ID=ACCOUNT2.ACCOUNT_ID AND MEMBER_ACCOUNT1.DEFAULT_PAYMENT_ACCOUNT_ID=EXTERNAL_ACCOUNT1.EXTERNAL_ACCOUNT_ID ORDER BY RELATIONSHIP_STYPE desc FOR THE PARAMETER VALUES :’P’ ,7 Object Rollback and Refresh. Dirty and Persistent Statuses. bjectviewPL provides methods for restoring the persisted state from memory or from database. To restore the persisted state ObjectViewPL stores in memory the current persistent state in an internal variable called commitDict. O
  • 71. P R O G R A M M E R S ’ G U I D E The last persisted object state can be retrieved calling JDBPersistentObject.getCommitDict(). Dirty status To avoid unnecessary database calls an object is stored in database only if it was modified since last database call. Dirty status is updated in each set method. To force the dirty status to the desired value call JDBPersistentObject.setDirty(boolean state); To check the ObjectViewPL internal computed dirty status call the method isModified(). Persistency Status If object was retrieved from database its persistent status becomes true and next save operation will result in a call to an update or a delete statement. User can change this flag (otherwise not recommended) only in cases when default behaviour has to be changed (imported objects,…) Persistency status can be checked and modified using isPersistent() and isPersistent(boolean status) methods. Persistent Object Cloning To create a copy in memory of an existing persisted object, use the JDBPersistentObject.newCopy() method. Primary keys, update controllers and autoincrementors will not be copied. After newCopy() the save() operation will result in an update statement. Transaction Management Transactions can be managed using ObjectViewPL API or can be managed by an external transaction monitor. For transactions internally managed, ObjectViewPL supports embedded transactions so user does not need to modify existing code to be able to wrap existing transactional units. The methods used for internal transaction management are:  JDBSession.beginTransaction() - begin an embedded transaction. If a transaction is already started, then ObjectViewPL will not start another one but will join the existing transaction. ObjectViewPL rolls back automatically in case of any error or in cases when a database connection id closed without explicitly calling commit or rollback.  JDBSession.commitTransaction() - Commits the open transaction. If transaction is embedded only commits if this call represents the most exterior level.  JDBSession.rollback() – Rollbacks exiting transaction. Rollback is always executed regardless of the level was called in case of embedded transactions.
  • 72. P R O G R A M M E R S ’ G U I D E Object vs. Database State synchronization If objects or database state is modified independently then the state synchronization should be performed as a separate step. State synchronization can be achieved using the following methods:  object.refresh() and object.refreshAll() – This method refresh the object/objectgraph persistent attributes from database.  object. checkPersistentStatus() – This method checks and updates persistent status, commitDict and dirtyStatus.  object. isPersistent ( boolean aBoolean ) – If object is in database the persistent flag is true.  child delete strategy in association mapping Database Triggers If database triggers are deleting or modifying rows, ObjectViewPL can be kept in synch using association mapping delete strategy policy, object refresh or checkPersistentStatus methods. For example if the delete trigger of a certain table is deleting the associated rows then ObjectViewPL should not issue any delete operations for associated roles but rely of the trigger to do the deletion while updating object status as deleted from database. Object persistent state rollback ObjectViewPL saves last successful database access operation fields to an internal dictionary that can be used to rollback persistent status. The internal variable used to save persistent state is called commitDict and can be retrieved using method JDBPersistentObject.getCommitDict(). The internal use for this variable is two fold: to prevent unnecessary updates if no fields were modified since last database read, and to restore object persistent state to the last database read. The method to be used for restoring persistent state is JDBPersistentObject.rollbackToLastPersistentState(). public static void objectRollbackPersistentState() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // get a BusinessEntity representing a Person. Person person = (Person) Person.findByPrimaryKey(session, new Integer(2)); person.setNotesString("Parking card declared lost"); person.setFirstName("Beautified"); person.setLastName("Changed Also"); System.out.println(person.toXml()); // put the last read values back person.rollbackToLastPersistentState(); System.out.println(person.toXml());
  • 73. P R O G R A M M E R S ’ G U I D E } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Mapping Functions, Stored Procedures, Views and Ad-hoc SQL bjectviewPL provides methods for managing stored procedures, open cursors queries and ad-hoc SQL. If Stored procedures returns result sets then they can be mapped as readOnly persistent classes.OFor stored procedures returning result sets (or open cursors) user has two options: to map the result set columns to a new persistent java class, or to use an existing domain class already mapped. For stored procedures returning rows from a temporary table separately mapped to a java persistent object, map database name is the (global) temporary table name and java attributes database names are the result set column names. In this case if returned result set metadata changes, mapping should change accordingly. When a stored procedure returns result sets that were already mapped to domain objects, then existing domain object mapping can be used to retrieve stored procedure result set data. Retrieving objects from stored procedures or functions returning open cursors The methods used for retrieving objects from an open cursor result set are retrieveAllUsingOpenCursor() static methods defined in JDBPersistentObject subclasses. The sequence is: execute storedProcString ( bind parameters ) retrieve the cursor and build objects by iterating the resultSet
  • 74. P R O G R A M M E R S ’ G U I D E close cursor ( that will free Oracle memory ) Bellow you find the code of an Oracle function returning an open cursor to be used as a sample. Attention: if a stored procedure is used instead of a function to return an open cursor, than first parameter must be an output parameter of cursor type and the actual procedure in parameters are staring from position number 2. In this case retrieveAllUsingOpenCursor must be called with isFunction boolean parameter false CREATE OR REPLACE PACKAGE objectview_pkg AS /****************************************************************************** NAME: objectview_pkg PURPOSE: Testing OPEN CURSOR PROCEDURE MAPPING AUTHOR: Adrian Faur To test the function use: DECLARE RetVal OBJECTVIEW_PKG.cursor_type; BE_TYPE_INPUT_CODE VARCHAR2(200); BEGIN BE_TYPE_INPUT_CODE := 'C'; RetVal := SYSTEM.OBJECTVIEW_PKG.BE_FOR_TYPE_FUNC ( BE_TYPE_INPUT_CODE ); COMMIT; END; ******************************************************************************/ TYPE cursor_type IS REF CURSOR; FUNCTION BE_FOR_TYPE_FUNC (BE_TYPE_INPUT_CODE IN VARCHAR2) RETURN cursor_type; PROCEDURE BE_FOR_TYPE_PROC (BE_TYPE_INPUT_CODE IN VARCHAR2, O_RESULT_SET OUT cursor_type); END objectview_pkg; / CREATE OR REPLACE PACKAGE BODY OBJECTVIEW_PKG AS FUNCTION BE_FOR_TYPE_FUNC ( BE_TYPE_INPUT_CODE IN VARCHAR2 ) RETURN cursor_type IS cur_result cursor_type; BEGIN OPEN cur_result FOR SELECT * FROM BUSINESS_ENTITY WHERE BUSINESS_ENTITY.BE_TYPE = BE_TYPE_INPUT_CODE; RETURN cur_result; END; /***** PROCEDURE ****************************************/ PROCEDURE BE_FOR_TYPE_PROC (BE_TYPE_INPUT_CODE IN VARCHAR2, O_RESULT_SET OUT CURSOR_TYPE) AS BEGIN OPEN O_RESULT_SET FOR SELECT * FROM BUSINESS_ENTITY WHERE BUSINESS_ENTITY.BE_TYPE = BE_TYPE_INPUT_CODE;
  • 75. P R O G R A M M E R S ’ G U I D E END; END OBJECTVIEW_PKG; / Here is the java code that uses this function to retrieve the objects: public static void storedProcMappingDemo() { JDBSession session = null; try { session = JDBSystem.acquireConnection(); Vector businessEntities=null; // Assumption: The objectview_pkg was created and compiled. Source file can be found // in config/OracleXE/StoredProcedureExamples.sql // call the open cursor function BE_FOR_TYPE_FUNC Vector param = new Vector(1); param.addElement("C"); // companies only // Attention! If function name not found, // grant permissions,create a public synonym or use fully qualified names. businessEntities = JDBPersistentObject.retrieveAllUsingOpenCursor ( BusinessEntity.class.getName(), session, "SYSTEM.OBJECTVIEW_PKG.BE_FOR_TYPE_FUNC" , param, true ); for (Iterator iter = businessEntities.iterator(); iter.hasNext();) { BusinessEntity be = (BusinessEntity) iter.next(); System.out.println(be.toXml(false)); } // Now call the stored procedure instead, that produces the same result param.removeAllElements(); param.addElement(null); // returned cursor param.addElement("C"); // companies only businessEntities = JDBPersistentObject.retrieveAllUsingOpenCursor( BusinessEntity.class.getName(), session, "SYSTEM.OBJECTVIEW_PKG.BE_FOR_TYPE_PROC" , param, false ); for (Iterator iter = businessEntities.iterator(); iter.hasNext();) { BusinessEntity be = (BusinessEntity) iter.next(); System.out.println(be.toXml(false)); } } catch (ObjectViewApplicationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) {
  • 76. P R O G R A M M E R S ’ G U I D E // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Retrieving objects from stored procedures returning result sets The method used to return java objects mapped to the stored procedure result set is JDBPesristentObject.retrieveAllUsingStoredProc(String className, JDBSession session, String procName , Vector parameters). In Sybase and SQLServer the last select statement issued in a stored procedure before returning control, generates the result set returned to caller. DB2 uses session scope temporary tables for storing result sets. This method can be used in all cases when a stored procedure returns a result set without any additional parameters for binding the result set. This method can be used in all cases where the code bellow can be used to call a stored procedure using jdbc: // Prepare the CallableStatement. CallableStatement cs = con.prepareCall ("{ call StoredProcName(param1,…)} "); // Call and Process the result set ResultSet rs = cs.executeQuery(); A separate case that needs discussion represents Oracle database stored procedures. In Oracle result sets can be returned from a stored procedure by using (global) temporary tables and associated constraint “ON COMMIT DELETE ROWS”. To implement this behaviour, JDBOracleObjectBroker must be used as the object broker for the corresponding domain object mapping. There is a bug in Oracle 8.? where commit does not always delete rows from temporary table defined with constraint “ON COMMIT DELETE ROWS”. So, to fix it, instead of "SELECT * FROM TEMP_TABLE" ObjectViewPL uses "SELECT * FROM TEMP_TABLE where session_id = ( select SID from v$session where audsid = userenv('SESSIONID'))"; 
  • 77. P R O G R A M M E R S ’ G U I D E Attention: To fix the bug described above, put a '#' in front of stored procedure name before supplying procName parameter to retrieveAllUsingStoredProc() method and map the class to use com.objectview.jdb.JDBOracleObjectBroker supplied class. Retrieving objects from ad-hoc SQL statements JDBPersistentObject. retrieveAllUsingSQL ( String className, JDBSession session, String sqlString ) method can be used to retrieve objects from any SQL returning a result set. All result set columns whose names that can be matched to a java attribute of the given object using mapping information will be retrieved and set into object context. Retrieving objects from database Views Views can be mapped to domain objects like any other tables, but in order to flag the objects as read-only (only SELECT statements accepted), user should set the “Is a database view or a stored procedure producing a result set” checkbox in mapping configuration (see Class Mapping Panel chapter of Mapping Tool Users’ Guide). In order to retrieve the objects use can call the retrieveAllUsingSQL() method and supply the “Select * from View_name” as the parameter representing the sqlString parameter. Retrieving objects from a given java.sql.ResultSet This is the most generic method for instantiating mapped java objects from a given result set. This method will try to build objects according to mapping information. The same method is used to instantiate objects for all other ObjectViewPL method calls, regardless of SQL form (joins, stored procedures, ad-hoc SQL, etc), as along as they produce a result set. This method will become very handy in cases when ObjectView does not cover specific requirements for constructing or issuing the SQL. The method to call in this case is JDBPersistentObject. buildObjects( ResultSet rs, JDBClassMap map, JDBSession session ). Lightweight Objects. Primary Key Objects. All JDBPersistentObjects generated by ObjectViewPL are “java.io.Serializable” objects. They can be serialized to storage media or sockets. When memory footprint or i/o is a particular concern, a new type of objects can be used as proxies to the real domain objects. These objects are instances of the class JDBPersistentObjectKey. A JDBPersistentObjectKey will always know how to retrieve its corresponding persistent object once it was created. To create JDBPersistentObjectKey one can use the two constructors provided or corresponding retrieve methods:  public JDBPersistentObjectKey( NullWrapperDictionary aKeyDict, String className ). className represents the domain object class name, aKeyDict is a special
  • 78. P R O G R A M M E R S ’ G U I D E java.util.Hashtable subclass that accepts null values for any given key. The keyDict entries are pairs of (key,value) where key is the javaAttributeName of the primary key (at:#pkJavaAttributeName put:pkValue).  JDBPersistentObjectKey( JDBPersistentObject po). This constructor is used when the persistent object is known.  retrieveAllKeys ( String className, JDBSession session, Hashtable whereDict, String orderBy, String customWhereClause, Vector persistentObjects ). Parameters: 1) className is the java full class name ( including package ) for the JDBPersistentObject(s) to be retrieved. 2) session database session 3) whereDict is a dictionary used to create the where clause for the select statement. Its keys represent java attribute names visibles in the className, and its values represent the values used in where clause. If whereDict is null or empty, a select all will take place. 4) orderBy is the order by string for the select clause. It is appended as it is provided. Do not Include ORDER BY text, but the comma separated database fields only. 5) customWhereClause is an extra string to be appended to the where clause 6) persistentObjects. Vector with persistent objects previously retrieved. In this case ,the objects are refreshed and returned. No new objects will be created. Please find a usage sample bellow: public static void objectKeyDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // create a JDBPersistentObjectKey to represents a known database Person object NullWrapperDictionary personKeyDict = new NullWrapperDictionary(1); personKeyDict.put(Person.ATTR_personBeId, new Integer(2)); JDBPersistentObjectKey pok = new JDBPersistentObjectKey(personKeyDict, Person.class.getName()); // retrieve the person object from database. Person person = (Person) pok.getPersistentObject(session); System.out.println(person.toXml(false));
  • 79. P R O G R A M M E R S ’ G U I D E // instead of retrieving all persons from database, retrieve only the primary keys objects. // we can then later retrieve the corresponding object behind each keyObject. Vector keys= JDBPersistentObject.retrieveAllKeys(Person.class.getName(), session); for (Iterator iter = keys.iterator(); iter.hasNext();) { JDBPersistentObjectKey objectKey = (JDBPersistentObjectKey) iter.next(); System.out.println(objectKey); Person p = (Person) objectKey.getPersistentObject(session); System.out.println(p.toXml(false)); } } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } XML alternative store bjectviewPL provides methods for writing and reading persistent object state to xml format. These methods are toXml() and fromXml() static methods from JDBPersistentObject class.OXML Logging If property LOG_TO_XML_IF_SAVE_ERROR was to true, then the xml representation of the domain object involved in an ObjectViewApplicationException will be written to a file named objectDump.xml. Here is a sample of such file: <?xml version="1.0" encoding="UTF-8" ?> <!-- Thread: Thread[AWT-EventQueue-0,6,main] @:2004-07-12 17:43:52.425 @:com.objectview.example2.Ex1Person {name=adrian3} INSERT INTO EX1_PERSON_EXTENSION ( NAME,MEMO ) VALUES ( ?,? )_VALUES_ :adrian3 , memories from Japan , ;rollback transaction --> <com.objectview.example2.Ex1Person> <name>adrian3</name> <memo>memories from Japan</memo> </com.objectview.example2.Ex1Person>
  • 80. P R O G R A M M E R S ’ G U I D E The content of this file should be correlated with the error file created by user upon catching the exception and that is why the SQL, thread and timestamp information are printed together with the object dump information. Iterators. Retrieve first and next object. hen objects need to be retrieved and processed one by one and in a certain order, then an iterator must be defined. ObjectViewPL has methods that helps creating an iterator to retrieve objects in the alphabetically order of the primary key values. W The methods to use are:  JDBPersistentObject.retrieveFirst ( String className, JDBSession session, String additionalWhereClause ). o className java.lang.String. The class name of the domain object to be retrieved o session com.objectview.jdb.JDBSession o additionalWhereClause SQL string where clause to be appended to default one issued by this method  JDBPersistentObject.retrieveNext ( String className, JDBSession session, Object key, String additionalWhereClause ) o className java.lang.String. The class name of the domain object to be retrieved o session com.objectview.jdb.JDBSession o key java.lang.Object. The primary key value o additionalWhereClause SQL string where clause to be appended to default one issued by this method Please find a usage example bellow: public static void iteratorDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // get first BusinessEntity representing a Person.
  • 81. P R O G R A M M E R S ’ G U I D E BusinessEntity be = (BusinessEntity) BusinessEntity.retrieveFirst( BusinessEntity.class.getName(), session, BusinessEntity.FLD_BE_TYPE+"='P'"); System.out.println(be.toXml()); // retrieve all next Business entities representing persons one by one while (be != null ) { be = (BusinessEntity) be.retrieveNext(BusinessEntity.FLD_BE_TYPE+"='P'"); if (be!=null) System.out.println(be.toXml()); } } catch (ObjectViewApplicationException e) { e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } } Locking policies ocking mechanisms for both optimistic and pessimistic approaches are covered in ObjectView by separate methods and/or mapping configurations.L Optimistic Locking It is implemented using update control fields of type Integer or Timestamp. To configure an update controller field see Attribute Mapping paragraph on Mapping Tool Users’ Guide. Optimistic locking is used to prevent dirty reads. Attention: Because update controller field is used in the update where clause, it must represent a real table column and not a composed or formula field. Also, if inheritance is mapped to different tables (vertical approach) then one update controller must be present for each particular table and defining just one at the super-type level will only shield for concurrent updates happening at super-type level and not for any fields saved to subtype tables(s). Here is a sample of how such field could be used:
  • 82. P R O G R A M M E R S ’ G U I D E public static void optimisticLockingDemo() { JDBSession session = null; try { // obtain a database connection based on objectview.properties settings session = JDBSystem.acquireConnection(); // get a BusinessEntity representing a Person. // Attention we only have defined an update controller at Busines_entity // table level - only updating fields from this table can trigger // a ConcurrencyException and no checking is made for updating fields // from Person or Company subtype tables. Person person1 = (Person) Person.findByPrimaryKey(session, new Integer(2)); // instantiate another object representing the same table row. Person person2 = (Person) Person.findByPrimaryKey(session, new Integer(2)); // modify both of them and try to save them back to database. Second // update should fail person1.setNotesString("Parking card lost"); person2.setNotesString("Reissued parking card"); person1.save(session); try { person2.save(session); } catch (ConcurrencyException e) { // re-read object from database System.out.println("ConcurrencyException catched"); person2.refresh(session); System.out.println("Curent Note is:" + person2.getNotesString()); person2.setNotesString("Reissued parking card"); person2.save(session); System.out.println(person2.toXml()); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ObjectViewApplicationException e) { e.printStackTrace(); } finally { try { JDBSystem.releaseConnection(session); } catch (RollbackUncommitedSession e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } } }
  • 83. P R O G R A M M E R S ’ G U I D E Pessimistic Locking This type of locking is obtained by issuing special SQL syntax specific to database engine. This SQL string will be appended to the select statement created internally by ObjectView for the particular object involved and its syntax is specified in the ObjectView property EXCLUSIVE_LOCKING_SQL. By default the "FOR UPDATE NOWAIT" value was specified in the property file. The NOWAIT option is recommended because it offers a better error message handling that can be used to avoid dead-locks. Dead-locks can occur especially for the objects that are persisted in more than one table and requires a join select. With NOWAIT option these locks can be avoided. User should catch the SQLException thrown by this method and interpret accordingly, eventually retrying a number of times. For example, the most common Oracle SQL exception thrown in this case is: java.sql.SQLException: ORA-00054: resource busy and acquire with NOWAIT specified Cacheing policies bjectviewPL caches objects using mapping preferences. See Class Mapping Panel in Mapping Tool Users’ Guide for different types of cacheing.O Hook methods ook methods are user written methods having certain name and syntax automatically called by ObjectViewPL in the object’s main lifecycle points. In order to be called, the hook method must be implemented by user in the particular domain class. Hook methods will be called for any instance of such class. These methods are: H  preSave(JDBSession session). Method is called before issuing any insert, update or delete.  preInsert(JDBSession session). Method is called before any insert.  preUpdate(JDBSession session). Method called before update operation.  preDelete(JDBSession session). Method called before delete operation.
  • 84. P R O G R A M M E R S ’ G U I D E  postInsert(JDBSession session). Method called after insert operation.  postUpade(JDBSession session). Method called after update operation.  postDelete(JDBSession session). Method called after delete operation.  postSave(JDBSession session). Method called after any insert, update or delete.  postRetrieve(JDBSession session). Method called after any retrieve operation.