Guia Oficial Matisse Java
Guia Oficial Matisse Java
Guia Oficial Matisse Java
Programmers Guide
May 2013
Contents
1
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Scope of This Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Before Reading This Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Before Running the Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Contents
12 Handling Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Connection with Factory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Creating your Object Factory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Contents
Contents
1 Introduction
Scope of This Document
This document is intended to help Java programmers learn the aspects of Matisse design and
programming that are unique to the Matisse Java binding.
Aspects of Matisse programming that the Java binding shares with other interfaces, such as basic
concepts and schema design, are covered in Getting Started with Matisse.
Future releases of this document will add more advanced topics. If there is anything you would like to see
added, or if you have any questions about or corrections to this document, please send e-mail to
support@matisse.com.
Install the Java Development Kit version 7 or later for your operating system (a free download from
java.com or oracle.com).
Or use the preinstalled Java version on your MacOS machine.
Set the MATISSE_HOME and JAVA_HOME environment variables to the top-level directories of the
Matisse and JDK installations. On MS Windows, you can set environment variables in Control Panel
-> System.
Download and extract the Java sample code from the Matisse Web site:
http://www.matisse.com/developers/documentation/
The sample code files are grouped in subdirectories by chapter number. For example, the code
snippets from the following chapter are in the chap_2 directory.
Create and initialize a database. You can simply start the Matisse Enterprise Manager, select the
database example and right click on Re-Initialize.
Introduction
From a Unix shell prompt or on MS Windows from a Command Prompt window, change to the
chap_x subdirectory in the directory where you installed the examples.
If applicable, load the ODL file into the database. From the Enterprise Manager, select the database
example and right click on Schema->Import ODL Schema. For example you may import
chap_3/objects.odl for the Chapter 3 demo.
For the examples that include an ODL file, you may optionally create a subdirectory named docs,
then generate the API reference for your application schema (single command, all on one line). For
instance:
javadoc -public -classpath .;%MATISSE_HOME%\lib\matisse.jar -d docs Person.java
Employee.java
Introduction
2.
3.
Read-Only Access
The following code connects to a database in read-only mode, suitable for reports:
try
{
MtDatabase db = new MtDatabase(args[0], args[1]);
db.open();
db.startVersionAccess();
System.out.println("Connection and read-only access to "
+ db.toString());
// version connect (=>read-only access)
db.endVersionAccess();
db.close();
}
catch (MtException mte)
{
System.out.println("MtException : " + mte.getMessage());
}
Version Access
The following code illustrates methods of accessing various versions of a database.
try
{
MtDatabase db = new MtDatabase(args[0], args[1]);
db.open();
db.startTransaction();
System.out.println("Version list before regular commit:");
listVersions(db);
// read/write access
db.commit();
db.startTransaction();
System.out.println("Version list after regular commit:");
listVersions(db);
// another read/write access
String verName = db.commit("test");
System.out.println("Commit to version named: " + verName);
db.startVersionAccess();
System.out.println("Version list after named commit:");
listVersions(db);
// read-only access on the latest version.
db.endVersionAccess();
db.startVersionAccess(verName);
System.out.println("Sucessful access within version: " + verName);
// read-only access on a named version. It's not possible to
JDBC Connection
The following code accesses a Matisse database using JDBC two ways: first using pure JDBC, then using
a mix of JDBC and Matisse methods.
public static void main(String[] args) {
if (args.length < 2)
{
System.out.println("Need to specify <HOST> <DATABASE>");
System.exit(-1);
}
String hostname = args[0];
String dbname = args[1];
// Build a JDBC connection
connectFromJDBC(hostname, dbname);
// Build a JDBC connection from a MtDatabase connection
connectFromMtDatabase(hostname, dbname);
}
/**
* Create a JDBC connection. (Does not require com.matisse.* import.
*/
public static void connectFromJDBC(String host, String dbname) {
System.out.println("=========== connectFromJDBC ==========\n");
try {
Class.forName("com.matisse.sql.MtDriver");
String url = "jdbc:mt://" + host + "/" + dbname;
System.out.println("Query class names from the JDBC connection: " + url);
Connection jcon = DriverManager.getConnection(url);
10
Specific Options
This example shows how to enable the local client-server memory transport and to set or read various
connection options and states.
11
class AdvancedConnect {
static MtDatabase db;
public static void main(String[] args) {
if (args.length < 2)
{
System.out.println("Need to specify <HOST> <DATABASE>");
System.exit(-1);
}
try
{
db = new MtDatabase(args[0],args[1]);
if (System.getProperty("MT_MEM_TRANS") != null)
db.setOption(MtDatabase.MEMORY_TRANSPORT, MtDatabase.ON);
if (System.getProperty("MT_DATA_ACCESS") != null)
{
db.setOption(MtDatabase.DATA_ACCESS_MODE,
Integer.parseInt(System.getProperty("MT_DATA_ACCESS")));
}
db.open(System.getProperty("dbuser"),
System.getProperty("dbpasswd"));
start(isReadOnly());
printState();
end();
db.close();
}
catch (MtException mte)
{
System.out.println("MtException : " + mte.getMessage());
}
}
static void start(boolean readonly) {
if (readonly)
db.startVersionAccess();
else
db.startTransaction();
}
static void end() {
if (db.isVersionAccessInProgress())
db.endVersionAccess();
else if (db.isTransactionInProgress())
db.commit();
else
System.out.println("No transaction/version access in progress");
}
static boolean isMemoryTransportOn() {
return db.getOption(MtDatabase.TRANSPORT_TYPE) == MtDatabase.MEM_TRANSPORT;
}
12
13
Running ObjectsExample
This sample program creates objects from 2 classes ( Person and Employee), lists all Person objects
(which includes both objects, since Employee is a subclass of Person), deletes objects, then lists all
Person objects again to show the deletion. Note that because FirstName and LastName are not nullable,
they must be set when creating an object.
1.
2.
3.
Load objects.odl into the database. From the Enterprise Manager, select the database example
and right click on Schema->Import ODL Schema, then select chap_3/objects.odl for this demo.
4.
5.
6.
Creating Objects
This section illustrates the creation of objects. The stubclass provides a default constructor which is the
base constructor for creating persistent objects.
public Person(com.matisse.MtDatabase db) {
14
super(getClass(db));
}
// Create a new Person object (instance of class Person)
Person p = new Person(db);
p.setFirstName("John");
p.setLastName("Smith");
p.setAge(42);
PostalAddress a = new PostalAddress(db);
a.setCity("Portland");
a.setPostalCode("97201");
p.setAddress(a);
// Create a new Employee object
Employee e = new Employee(db);
e.setFirstName("Jane");
e.setLastName("Jones");
// Age is nullable we can leave it unset
e.setHireDate(new GregorianCalendar());
e.setSalary(new BigDecimal(85000.00));
If your application need to create a large number of objects all at once, we recommend that you use the
preallocate() method defined on MtDatabase which provide a substantial performance optimization.
db.startTransaction();
// Optimize the objects loading
// Preallocate OIDs so objects can be created in the client workspace
// without requesting any further information from the server
db.preallocate(DEFAULT_ALLOCATOR_CNT);
for (int i = 1; i <= 100; i++) {
// Create a new Employee object
Employee e = new Employee(db);
String fname = fNameSample[sampleSeq.nextInt(MAX_SAMPLES)];
String lname = lNameSample[sampleSeq.nextInt(MAX_SAMPLES)];
e.setFirstName(fname);
e.setLastName(lname);
e.setHireDate(new GregorianCalendar());
e.setSalary(new BigDecimal(salarySample[sampleSeq.nextInt(MAX_SAMPLES)]));
PostalAddress a = new PostalAddress(db);
int addrIdx = sampleSeq.nextInt(MAX_SAMPLES);
a.setCity(addressSample[addrIdx][0]);
a.setPostalCode(addressSample[addrIdx][1]);
e.setAddress(a);
System.out.println("Employee "+i+ " " + fname + " " + lname + " created.");
if (i % OBJECT_PER_TRAN_CNT == 0) {
db.commit();
db.startTransaction();
}
// check the remaining number of preallocated objects.
if (db.numPreallocated() < 2) {
db.preallocate(DEFAULT_ALLOCATOR_CNT);
}
}
if (db.isTransactionInProgress())
db.commit();
15
Listing Objects
This section illustrates the enumeration of objects from a class. The instanceIterator() static method
defined on a generated stubclass allows you to enumerate the instances of this class and its subclasses.
The getInstanceNumber() method returns the number of instances of this class.
// List all Person objects
System.out.println("\n" + Person.getInstanceNumber(db) +
Person(s) in the database.");
Iterator<Person> iter = Person.instanceIterator(db);
while (iter.hasNext()) {
Person x = iter.next();
System.out.println("\t" + x.getFirstName() + " " + x.getLastName() +
" from " + (x.getAddress() != null ? x.getAddress().getCity() : "???") +
" is a " + x.getMtClass().getMtName());
}
The ownInstanceIterator() static method allows you to enumerate the own instances of a class
(excluding its subclasses). The getOwnInstanceNumber() method returns the number of instances of a
class (excluding its subclasses).
// List all Person objects (excluding Employee sub-class)
System.out.println("\n" + Person.getOwnInstanceNumber(db) +
" Person(s) (excluding subclasses) in the database.");
MtObjectIterator<Person> iter = Person.<Person>ownInstanceIterator(db);
while (iter.hasNext()) {
Person x = iter.next();
System.out.println("\t" + x.getFirstName() + " " + x.getLastName() +
" from " + (x.getAddress() != null ? x.getAddress().getCity() : "???") +
" is a " + x.getMtClass().getMtName());
}
iter.close();
Deleting Objects
This section illustrates the removal of objects. The remove() method delete an object.
// Remove created objects
Person p;
...
// NOTE: does not remove the object sub-parts
p.remove();
To remove an object and its sub-parts, you need to override the deepRemove() method in the stubclass to
meet your application needs. For example the implementation of deepRemove() in the Person class that
contains a reference to a PostalAddress object is as follows:
public void deepRemove() {
PostalAddress pAddr = getAddress();
if (pAddr != null)
pAddr.deepRemove();
super.deepRemove();
16
Person p;
...
p.deepRemove();
The removeAllInstances() method defined on MtClass delete all the instances of a class.
Person.getClass(db).removeAllInstances();
Comparing Objects
This section illustrates how to compare objects. Persistent objects must be compared with the equal()
method. You cant compare persistent object with the == operator.
Person p1;
Person p2;
...
if(p1.equals(p2))
System.out.println("Same objects");
Running ValuesExample
This example shows how to get and set values for various Matisse data types including Null values, and
how to check if a property of an object is a Null value or not.
This example uses the database created for ObjectsExample. It creates objects, then manipulates its
values in various ways.
To launch the application:
Windows:
java -classpath .;%MATISSE_HOME%\lib\matisse.jar ObjectsExample host database
UNIX:
java -classpath .;$MATISSE_HOME/lib/matisse.jar ValuesExample host database
17
Removing Values
This section illustrates the removal of object property values. Removing the value of an attribute will
return the attribute to its default value.
Employee e;
// Removing value returns attribute to default
e.removeAge();
if (!e.isAgeNull())
System.out.println("\t" + e.getAge() + " years old");
else
System.out.println("\tAge: null" +
(e.isDefaultValue(Employee.getAgeAttribute(db)) ? " (default value)" : ""));
Streaming Values
This section illustrates the streaming of blob-type values (MT_BYTES, MT_AUDIO, MT_IMAGE,
stubclass provides streaming methods (setPhotoElements(), getPhotoElements()) for
each blob-type property defined in the class. It also provides a method (getPhotoSize()) to retrieve the
blob size without reading it.
MT_VIDEO). The
// Setting blobs
// set to 512 for demo purpose
// a few Mega-bytes would be more appropriate
// for real multimedia objects (audio, video, high-resolution photos)
int bufSize = 512;
int num, total;
byte buffer[] = new byte[bufSize];
try {
InputStream is = new FileInputStream("matisse.gif");
// reset the stream
e.setPhotoElements(buffer, MtType.BEGIN_OFFSET, 0, true);
do {
num = is.read(buffer, 0, bufSize);
if (num > 0) {
e.setPhotoElements(buffer, MtType.CURRENT_OFFSET, num,
false);
}
} while (num == bufSize);
18
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("Image of " + e.getPhotoSize() + " bytes stored.");
19
Running RelationshipsExample
This example creates several objects, then manipulates the relationships among them in various ways.
1.
2.
3.
Load examples.odl into the database. From the Enterprise Manager, select the database example
and right click on Schema->Import ODL Schema, then select chaps_4_5_6/examples.odl for this
demo.
4.
5.
6.
20
m1.setReportsTo(m1);
Employee e = new Employee(db);
...
// Set a relationship
e.setReportsTo(m1);
Person c1 = new Person(db);
...
Person c2 = new Person(db);
...
// Set successors
m2.setChildren(new Person[] {c1, c2});
...
// Get all successors
Person[] c = m2.getChildren();
21
22
Running IndexExample
This example uses the database created for RelationshipsExample. Using the PersonName index, it
checks whether the database contains an entry for a person matching the specified name. Run it using the
following command:
Windows:
java -classpath .;examples\java_examples\chaps_4_5_6;%MATISSE_HOME%\lib\matisse.jar
IndexExample host database firstName lastName
UNIX:
java -classpath .:examples/java_examples/chaps_4_5_6:$MATISSE_HOME/lib/matisse.jar
IndexExample host database firstName lastName
The application will list the names in the database, indicate whether the specified name was found, and
return results within a sample range (defined in the source) using an iterator.
Index Lookup
This section illustrates retrieving objects from an index. The stubclass provides a lookup and a iterator
method for each index defined on the class.
// the lookup function returns null to represent no match
Person found = Person.lookupPersonName(db, lastName, firstName);
// open an iterator for a specific range
String fromFirstName = "Fred";
String toFirstName = "John";
String fromLastName = "Jones";
String toLastName = "Murray";
System.out.println("\nLookup from \"" +
fromFirstName + " " + fromLastName + "\" to \"" +
toFirstName + " " + toLastName + "\"");
MtObjectIterator<Person> ppIter = Person.<Person>personNameIterator(db, fromLastName,
fromFirstName,
toLastName,
toFirstName);
while (ppIter.hasNext()) {
Person p = ppIter.next();
System.out.println(" " + p.getFirstName() + " " + p.getLastName());
}
ppIter.close();
23
24
Running EPDictExample
This example uses the database created for RelationshipsExample. Using the commentDict entry-point
dictionary, the example retrieves the Person objects in the database with Comments fields containing a
specified character string. To run it, use the following syntax:
Windows:
java -classpath .;examples\java_examples\chaps_4_5_6;%MATISSE_HOME%\lib\matisse.jar
EPDictExample host database search_string
UNIX:
java -classpath .:examples/java_examples/chaps_4_5_6:$MATISSE_HOME/lib/matisse.jar
EPDictExample host database search_string
25
To modify an object, use the set command specifying the id value of the object.
set id attribute_name value
To list all versions, objects, and values, use the dump command:
dump
Building VersionExample
1.
2.
Create and initialize a database as described in Getting Started with Matisse. If you wish, you may
re-initialize the database you created in the last chapter.
3.
26
4.
Load versions.odl into the database. From the Enterprise Manager, select the database example
and right click on Schema->Import ODL Schema, then select chap_7/versions.odl for this demo.
5.
6.
Running VersionExample
1.
This creates an object with id=1, FirstName=John, and LastName unset, and command-line output
similar to the following (your version name may vary):
New Version VerEx00000005 created
Which will produce output similar to the following (your version name may vary):
Version VEREX00000005
1: John (unset)
2.
27
This creates a second version of the object, with LastName= Smith. You can see this by repeating the
dump command shown in step 1:
Version VerEx00000005
1: John (unset)
Version VEREX100000007
1: John Smith
3.
This creates a third version of the object, with FirstName= Jack. You can see this by repeating the
dump command:
Version VEREX00000005
1: John (unset)
Version VEREX00000007
1: John Smith
Version VEREX00000009
1: Jack Smith
4.
5.
6.
Run the dump command again and you will see that there are now four versions of the database,
one for each modification you made:
Version VEREX00000005
1: John (unset)
Version VEREX00000007
1: John Smith
28
Version VEREX00000009
1: Jack Smith
Version VEREX0000000B
2: Jane (unset)
1: Jack Smith
Version VEREX0000000D
2: Jane Jones
1: Jack Smith
You can also view a list of these versions in Matisse Enterprise Manager, by selecting the Database
Snapshots node under Data.
Creating a Version
This example shows how to create a historical version (database snapshot). Versions are created at
commit time. You need to provide a version prefix name to the commit() method.
db.startTransaction();
Person p = new Person(db);
p.setId(1);
p.setFirstName("John");
p.setLastName("Doe");
String vname = db.commit("VerEx");
System.out.println("Version " + vname);
Accessing a Version
This example shows how to access a historical version (database snapshot). You need to provide the
version name (or version prefix if unique) to the startVersionAccess() method.
db.startVersionAccess("VerEx");
Person p = Person.lookupPersonId(db, id);
System.out.println(p.getFirstName());
System.out.println(p.getLastName());
db.endVersionAccess();
Listing Versions
This example shows how to list historical versions (database snapshots). The MtVersionIterator
iterator allows you to enumerate the versions.
db.startVersionAccess();
MtVersionIterator it = db.versionIterator();
while (it.hasNext()) {
System.out.println("Version " + it.next());
}
it.close();
db.endVersionAccess();
29
2.
3.
Load examples.odl into the database. From the Enterprise Manager, select the database example
and right click on Schema->Import ODL Schema, then select JDBC/examples.odl for this demo.
4.
5.
6.
Connecting to a Database
The following code shows how to open a JDBC connection from a Matisse connection.
MtDatabase dbcon = new MtDatabase(hostname, dbname);
// Open a connection to the database
dbcon.open();
dbcon.startTransaction();
Connection jdbcon = dbcon.getJDBCConnection();
30
- It is specifically used for the SQL statements where you don't need to pass any value as
a parameter
PreparedStatement
CallableStatement-
Statement
- It is a subclass of the statement class. The main difference is that, unlike the
statement class, prepared statement is complied and optimized once and can be used multiple times
by setting different parameter values.
It provides a way to call a stored procedure on the server from a Java
program. Callable statements also need to be prepared first, and then their parameters are set using
the set methods.
Retrieving Values
You use the ResultSet object, which is returned by the executeQuery method, to retrieve values or
objects from the database. Use the next method combined with the appropriate getString, getInt, etc.
methods to access each row in the result.
The following code demonstrates how to retrieve string and integer values from a ResultSet object after
executing a SELECT statement.
MtDatabase dbcon = new MtDatabase(hostname, dbname);
// Open a connection to the database
dbcon.open();
try {
// Set the SQL CURRENT_NAMESPACE to 'examples.java_examples.jdbc' so there is
// no need to use the full qualified names to acces the schema objects
//dbcon.setSqlCurrentNamespace("examples.java_examples.jdbc");
Connection jdbcon = dbcon.getJDBCConnection();
// Create an instance of PreparedStatement
String commandText = "SELECT FirstName, LastName, Spouse.FirstName AS Spouse, Age
FROM examples.java_examples.jdbc.Person WHERE LastName = ? LIMIT 10;";
PreparedStatement pstmt = jdbcon.prepareStatement(commandText);
pstmt.setEscapeProcessing(false);
// Set parameters
pstmt.setString(1, "Watson");
31
32
To retrieve objects, use REF in the select-list of the query statement and the getObject method returns
an object. The following code example shows how to retrieve Person objects from a ResultSet object.
// Set the SQL CURRENT_NAMESPACE to 'examples.java_examples.jdbc' so there is
// no need to use the full qualified names to acces the schema objects
//dbcon.setSqlCurrentNamespace("examples.java_examples.jdbc");
// Create an instance of Statement
Statement stmt = dbcon.createStatement();
// Set the SELECT statement. Note that we use REF() in the select-list
// to get the Java objects directly (rather than values)
String commandText = "SELECT REF(p) FROM examples.java_examples.jdbc.Person p WHERE
LastName = 'Watson';";
// Execute the SELECT statement and get a DataReader
ResultSet rset = stmt.executeQuery(commandText);
Person p;
// Read rows one by one
while (rset.next()) {
// Get the Person object
p = (Person)rset.getObject(1);
// Print the current object with spouse's name
// Note that spouse is directly accessed from the Person object 'p'
System.out.println("Person: " +
String.format("%16s",p.getFirstName()) +
String.format("%16s",p.getLastName()) +
" Spouse: " +
String.format("%16s", p.getSpouse().getFirstName()));
}
// Clean up and close the database connection
rset.close();
stmt.close();
33
Creating a Class
You can create schema objects using the executeUpdate Method as long as the transaction is started in
the DATA DEFINITION mode.
MtDatabase db = new MtDatabase(hostname, dbname);
// In order to execute DDL statements, the transaction needs to be
// started in the "Data Definition" mode
db.setOption (MtDatabase.DATA_ACCESS_MODE, MtDatabase.DATA_DEFINITION);
db.startTransaction();
// Execute the DDL statement
stmt = db.createStatement ();
stmt.executeUpdate ("CREATE CLASS Manager UNDER Employee (bonus INTEGER)");
db.commit();
db.close();
34
35
36
2.
3.
Load SqlMethods.odl into the database. From the Enterprise Manager, select the database
example and right click on Schema->Import ODL Schema, then select
sqlmethods/SqlMethods.odl for this demo.
4.
Generate Java class files with the -psm options so Java methods mapping the SQL Methods
defined on the class are generated as well:
mt_sdl stubgen --lang java --psm -f SqlMethods.odl
5.
6.
37
BEGIN
DECLARE fullName STRING;
SET fullName = CONCAT(SELF.FirstName, ' ');
IF SELF.MiddleName IS NOT NULL THEN
SET fullName = CONCAT(fullName, SELF.MiddleName);
SET fullName = CONCAT(fullName, ' ');
END IF;
SET fullName = CONCAT(fullName, SELF.LastName);
RETURN fullName;
END;"
38
Running ReflectionExample
This example creates several objects, then manipulates them to illustrate Matisse Reflection mechanism.
1.
2.
3.
Load examples.odl into the database. From the Enterprise Manager, select the database example
and right click on Schema->Import ODL Schema, then select reflection/examples.odl for this
demo.
4.
5.
Creating Objects
This example shows how to create persistent objects without the corresponding Java stubclass. The static
method get() defined on all Matisse Meta-Schema classes (i.e. MtClass, MtAttribute, etc.) allows you
to access to the schema descriptor necessary to create objects. Each object is an instance of the MtObject
base class. The MtObject class holds all the methods to update the object properties (attribute and
relationships (i.e. setString(), setSuccessors(), etc.).
MtDatabase db = new MtDatabase(hostname, dbname, new MtCoreObjectFactory());
db.open();
db.startTransaction();
System.out.println("Creating one Person...");
// Create a Person object
MtClass pClass = MtClass.get(db,
"examples.java_examples.reflection.Person");
39
Listing Objects
This example shows how to list persistent objects without the corresponding Java stubclass. The
instanceIterator() method defined on the MtClass object allows you to access all instances defined
on the class.
MtClass pClass = MtClass.get(db, "examples.java_examples.reflection.Person");
MtAttribute fnAtt = MtAttribute.get(db, "FirstName", pClass);
MtAttribute lnAtt = MtAttribute.get(db, "LastName", pClass);
MtAttribute cgAtt = MtAttribute.get(db, "collegeGrad", pClass);
// List all objects
System.out.println("\n" + pClass.getInstanceNumber() +
" Person(s) in the database.");
// Retrieve the object from the previous transaction
MtObjectIterator<MtObject> iter = pClass.<MtObject>instanceIterator();
while (iter.hasNext()) {
MtObject p = iter.next();
40
41
42
Adding Classes
This example shows how to add a new class to the database schema. The connection needs to be open in
the DDL (MtDatabase.DATA_DEFINITION) mode. Then you need to create instances of MtClass,
MtAttribute and MtRelationship and connect them together.
43
MtClass paClass = new MtClass(db, "PostalAddress", ns, new MtAttribute[] { cAtt, pcAtt },
null);
MtRelationship adRshp = new MtRelationship(db, "Address", paClass, new int[]{0, 1} );
pClass.addMtRelationship(adRshp);
Deleting Objects
This example shows how to delete persistent objects.The MtObject class holds remove() and
deepRemove(). Note that on MtObject deepRemove() does not execute any cascading delete but only
calls remove().
MtClass pClass = MtClass.get(db,
"examples.java_examples.reflection.Person");
MtObjectIterator iter = pClass.instanceIterator();
while (iter.hasNext()) {
MtObject p = iter.next();
p.deepRemove();
}
iter.close();
44
Removing Classes
This example shows how to remove a class for the database schema. The deepRemove() method defined
on MtClass will delete the class and its properties and indexes. The connection needs to be open in
MtDatabase.DATA_DEFINITION mode.
MtDatabase db = new MtDatabase(hostname, dbname, new MtCoreObjectFactory());
// open connection in DDL mode
db.setOption(MtDatabase.DATA_ACCESS_MODE, MtDatabase.DATA_DEFINITION);
db.open();
db.startTransaction();
MtClass paClass = MtClass.get(db,
"examples.java_examples.reflection.PostalAddress");
System.out.println("Removing " + paClass.getMtClass().getMtName() +
" " + paClass.getMtName() +
" (#" + paClass.getMtOid() + ")...");
paClass.deepRemove();
db.commit();
db.close();
45
Running EventsExample
This example creates several events, then manipulates them to illustrate the Event Notification
mechanism.
1.
2.
3.
4.
Events Subscription
This section illustrates event registration and event handling. Matisse provides the MtEvent class to
manage database events. You can subscribe up to 32 events (MtEvent.EVENT1 to MtEvent.EVENT32)
and then wait for the events to be triggered.
static
static
static
static
int
int
int
int
TEMPERATURE_CHANGES_EVT = MtEvent.EVENT1;
RAINFALL_CHANGES_EVT = MtEvent.EVENT2;
HIMIDITY_CHANGES_EVT = MtEvent.EVENT3;
WINDSPEED_CHANGES_EVT = MtEvent.EVENT4;
46
: "No ")
"No ") +
"No ") +
"No ") +
Events Notification
This section illustrates event selection and notification.
static
static
static
static
int
int
int
int
TEMPERATURE_CHANGES_EVT = MtEvent.EVENT1;
RAINFALL_CHANGES_EVT = MtEvent.EVENT2;
HIMIDITY_CHANGES_EVT = MtEvent.EVENT3;
WINDSPEED_CHANGES_EVT = MtEvent.EVENT4;
47
48
12 Handling Packages
The mt_sdl utility with the stubgen command allows you to generate Java source code for the schema
classes defined in the ODL file. The --sn <namespace> and --ln <namespace> options define the
mapping between the schema class namespace and the Java class package. When your persistent classes
are defined in a specific package, you need to give this information to the Connection object so that it
can find these classes when returning objects.
For example, to generate the Java classes in the root package from the schema classes in defined in the
java_examples.chap_3 namespace.
mt_sdl stubgen --lang java --sn java_examples.chap_3 -f examples.odl
To generate the Java classes in the com.corp.myapp package from the schema classes in defined in the
root namespace.
mt_sdl stubgen --lang java --ln com.corp.myapp -f example.odl
To generate the Java classes in the com.corp.myapp package from the schema classes in defined in the
Examples.Sample03 namespace.
mt_sdl stubgen --lang java --sn Examples.Sample03 --ln com.corp.myapp -f example.odl
To generate the Java classes in the com.corp.myapp package from the schema classes in defined in the
com.corp.myapp namespace.
mt_sdl stubgen --lang java -f example.odl
To generate the Java classes in the root package from the schema classes in defined in the root
namespace.
mt_sdl stubgen --lang java -f example.odl
Now assuming that the schema classes are defined in the company.project.module.db01 namespace:
MtDatabase db = new MtDatabase("host", "db", new
MtPackageObjectFactory("com.company.project.module",
"company.project.module.db01"));
Now assuming that the schema classes are defined in the com.company.project.module namespace,
which matches the Java package name, you can use the default factory:
Handling Packages
49
If the persistent classes are in the multiple Java packages, you pass HashMap to the
MtPackageObjectFactory constructor,
HashMap<String,String> pkgNsMap = new HashMap<String,String> ();
pkgNsMap.put("com.company.project.module1", "company.project.module.submoduleA");
pkgNsMap.put("com.company.project.module2", "company.project.module.submoduleB");
new MtPackageObjectFactory(pkgNsMap)
Using MtExplicitObjectFactory
The class is an alternative the class. The mt_sdl utility with the stubgen command generates the
<dbName>SchemaMap.txt file that defines a direct class mapping between the Java classes and the
schema classes.
MtDatabase db = new MtDatabase("host", "db", new
MtExplicitObjectFactory("examplesSchemaMap.txt"));
Using MtCoreObjectFactory
This factory is the basic MtObject-based object factory. This factory is the most appropriate for
application which does use generated stubs. This factory is faster than the default Object Factory used by
MtDatabase since it doesn't use reflection to build objects.
MtDatabase db = new MtDatabase("host", "db", new MtCoreObjectFactory());
Handling Packages
50
res = jClsName.substring(NS_REFLECT.length());
}
return res;
}
}
Handling Packages
51
Running MtDatabasePoolManagerExample
This example creates a MtDatabase pool manager, then use it a multi-threaded application to illustrate
Matisse Connection pooling mechanism.
1.
2.
3.
4.
52
Running JdbcConnectionPoolManagerExample
This example creates a JDBC Connection pool manager, then use it a multi-threaded application to
illustrate Matisse Connection pooling mechanism.
1.
2.
3.
4.
53
54
2.
matisseJAVA library contains the Java Native Interface (JNI) layer that links the binding to the
matisse library.
Matisse Lite
Matisse Lite is the embedded version of Matisse DBMS. Matisse Lite is a compact library that
implements the server-less version of Matisse. The Java binding also includes a Lite version of the
binding. The Matisse Lite Java binding is comprised of in 2 files:
1.
2.
matisseliteJAVA library contains the Java Native Interface (JNI) layer that links the binding to the
matisselite library.
The Matisse Java API documentation included in the delivery provides a detailed description of all the
classes and methods.
NOTE:
The Java binding API for Matisse Client Server and for Matisse Lite are
totally identical making your application working with either one without
any code changes.
55
2.
A .java file will be created for each class defined in the database. If you need to define these
persistent classes in a specific namespace, use -n option. The following command generates classes
under the namespace com.company.project:
mt_sdl stubgen --lang java --ln com.company.project -f myschema.odl
When you update your database schema later, load the updated schema into the database. Then, execute
the mt_sdl utility in the directory where you first generated the class files, to update the files. Your own
program codes added to these stub class files will be preserved.
Matisse Lite
Windows:
javac -classpath .;%MATISSE_HOME%\lib\matisselite.jar *.java
UNIX:
javac -classpath .;$MATISSE_HOME/lib/matisselite.jar *.java
56
UNIX:
java -classpath .;$MATISSE_HOME/lib/matisse.jar MyApp host database
Matisse Lite
Windows:
java -classpath .;%MATISSE_HOME%\lib\matisselite.jar MyApp host database
UNIX:
java -classpath .;$MATISSE_HOME/lib/matisselite.jar MyApp host database
57
getInstanceNumber(com.matisse.MtDatabase db)
getOwnInstanceNumber(com.matisse.MtDatabase db)
Open an iterator
instanceIterator(com.matisse.MtDatabase db)
ownInstanceIterator(com.matisse.MtDatabase db)
Sample
constructor
Sample toString
Get descriptor
Person(com.matisse.MtDatabase db)
toString()
getClass(com.matisse.MtDatabase db)
getFirstName()
Set value
setFirstName(java.lang.String val)
Remove value
removeFirstName()
isFirstNameNull()
Check Default
value
isFirstNameDefault()
Get descriptor
getFirstNameAttribute(com.matisse.MtDatabase db)
58
Set elements
Count elements
getPhotoSize()
clearSpouse()
getSpouseRelationship(com.matisse.MtDatabase db)
Employee getAssistant()
Set successor
setAssistant(Employee succ)
Person[] getTeam()
Open an iterator
teamIterator()
Count successors
getteamSize()
Set successors
Add successors
setTeam(Employee[] succs)
Remove
successors
removeTeam(Employee succ)
59
removeTeam(Employee[] succs)
For indexes
The following methods are created for every index defined for a database. These examples are for the
only index defined in the example, Person.personName.
Lookup
Open an iterator
Get descriptor
Open an iterator
Get descriptor
getCommentDictDictionary(com.matisse.MtDatabase db)
60
NetBeans IDE
Goal: mount a JAR filesystem for the matisse.jar file.
1.
2.
3.
Click browse.
4.
5.
Click OK.
Eclipse IDE
Goal: import the matisse.jar file.
1.
2.
3.
4.
5.
6.
Click Next.
7.
Click Browse.
8.
9.
Click Finish.
61
This example is a prototype for a real-world manufacturing application. The schema, as diagrammed
above, reflects a motherboard with two chip components, each of which has several parameters.
Relationships defined in the Revisable superclass track major (dot-zero) branches and minor (.x, .x.x,
etc.) revisions of the motherboard.
62
2.1
2.2
2.2.1
2.3
This applications overloaded methods reduce disk requirements by storing only the modified attributes
for each object, and searching up the revision/branch hierarchy to find values for the other attributes.
To build and run this sample application:
1.
2.
Create and initialize a database as described in Getting Started with Matisse. If you wish, you may
re-initialize a database created for another example.
3.
4.
Load Revision.odl into the database. From the Enterprise Manager, select the database example
and right click on Schema->Import ODL Schema, then select revision/Revision.odl for this
demo.
5.
6.
7.
Windows:
java -classpath .;examples\java_examples\revision;%MATISSE_HOME%\lib\matisse.jar
Revision database@host [set|dump] parameters
UNIX:
java -classpath .:examples/java_examples/revision:$MATISSE_HOME/lib/matisse.jar
Revision database@host [set|dump] parameters
63
For example:
...
...
...
...
...
...
...
...
Notes on set:
If no nextRevision successor exists for the specified revision, Revision creates one. For example, if
you specify revision 2 and there is no 3, the new object will be 3; if you specify 2.1 and there is no
2.2, the new object will be 2.2.
If a nextRevision successor already exists, Revision creates a new branch. For example, if you
specify 2 and there is already a 3, the new object will be 2.1; if you specify 2.1 and there is already a
2.2, the new object will be 2.2.1.
Notes on dump:
The dump command lists all objects that are revision or branch successors to the specified revision. For
example, if the revisions were as shown in the diagram on the previous page, dump 2.2 would include
2.2, 2.2.1, and 2.3; dump 2 would include 2, 2.1, 2.2, 2.2.1, 2.3, and 3.
64
This JSP-based application is a generic Matisse database browser that you can use to explore or query
any running Matisse database. When used with the included sample database (schema shown above), it
also demonstrates how to build a Web-browser-based front end for a Matisse using JSP.
You can download the code from:
http://www.matisse.com/developers/documentation/
See the included readme.txt file for installation and operation instructions.
65