Castor JDO code samples
Documentation Author(s): Werner Guttmann
Introduction Java class files DDL Object Mappings
Read-only fields
Transient fields Relations
1:1 relation
1:M relation
M:N relation Extend relation & polymorphism OQL samples
Introduction
This document provides object mapping examples and the corresponding
Java objects and DDL for the database table.
Java class files
The following fragment shows the Java class declaration for the
Product class:
package myapp;
public class Product {
private int _id;
private String _name;
private float _price;
private ProductGroup _group;
public int getId() { ... }
public void setId( int anId ) { ... }
public String getName() { ... }
public void setName( String aName ) { ... }
public float getPrice() { ... }
public void setPrice( float aPrice ) { ... }
public ProductGroup getProductGroup() { ... }
public void setProductGroup( ProductGroup aProductGroup ) { ... }
} |
|
The following fragment shows the Java class declaration for the
ProductGroup class:
public class ProductGroup {
private int _id;
private String _name;
public int getId() { ... }
public void setId( int id ) { ... }
public String getName() { ... }
public void setName( String name ) { ... }
} |
|
DDL
The following sections show the DDL for the relational database
tables PROD, PROD_GROUP, and PROD_DETAIL:
PROD:
create table prod (
id int not null,
name varchar(200) not null,
price numeric(18,2) not null,
group_id int not null
); |
|
PROD_GROUP:
create table prod_group (
id int not null,
name varchar(200) not null
); |
|
PROD_DETAIL:
create table prod_detail (
id int not null,
prod_id int not null,
name varchar(200) not null
); |
|
Object Mappings
The following code fragment shows the object mapping for the
ProductGroup class:
<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Object Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="myapp.ProductGroup" identity="id">
<description>Product group</description>
<map-to table="prod_group" xml="group" />
<field name="id" type="integer" >
<sql name="id" type="integer"/>
</field>
<field name="name" type="string">
<sql name="name" type="char" />
</field>
</class>
</mapping> |
|
As a result of that declaration, Castor JDO will create the following
SQL statements for creating, deleting, loading and updating instances
of ProductGroup:
create: INSERT INTO prod_group (id, name) VALUES (?,?)
delete: DELETE FROM prod_group WHERE id=?
load: SELECT prod_group.id, prod_group.name FROM prod_group WHERE prod_group.id=?;
update: UPDATE prod_group SET name=? WHERE id=?
|
|
Read-only fields
To declare the name field read-only, the field
definition above for the field name needs to be changed to:
<class name="myapp.ProductGroup" identity="id">
...
<field name="name" type="string">
<sql name="name" type="char" read-only="true" />
</field>
</class> |
|
As a result of that declaration, Castor JDO creates the following
SQL statements for creating, deleting, loading and updating
instances of ProductGroup:
create: INSERT INTO prod_group (id) VALUES (?)
delete: DELETE FROM prod_group WHERE id=?
load: SELECT prod_group.id, prod_group.name FROM prod_group WHERE prod_group.id=?;
update: no statement will be generated |
|
Transient fields
To declare the name field transient with regards to
persistence, above field definition for the field name needs
to be changed to:
<class name="myapp.ProductGroup" identity="id">
...
<field name="name" type="string" >
<sql name="name" type="char" transient="true" />
</field>
</class> |
|
Relations
1:1 relation
The following code fragment shows the mapping file for the Product
class. Apart from the simple field declarations, this includes a
simple 1:1 relation between Product and
ProductGroup, where every product instance is associated
with a ProductGroup:
<class name="myapp.Product" identity="id">
<map-to table="prod" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="name" type="string">
<sql name="name" type="char" />
</field>
<field name="price" type="float">
<sql name="price" type="numeric" />
</field>
<field name="group" type="myapp.ProductGroup" >
<sql name="group_id" />
</field>
<field name="details" type="myapp.ProductDetail"
collection="vector">
<sql many-key="prod_id"/>
</field>
<field name="categories" type="myapp.Category" collection="vector">
<sql name="category_id"
many-table="category_prod" many-key="prod_id" />
</field>
</class> |
|
1:M relation
The following code fragment shows (again) the mapping file for
the Product class. The field definition highlighted
shows how to declare a 1:M relation between Product and
ProductDetail, where every product instance is made up
of many ProductDetails:
<class name="myapp.Product" identity="id">
<map-to table="prod" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="name" type="string">
<sql name="name" type="char" />
</field>
<field name="price" type="float">
<sql name="price" type="numeric" />
</field>
<field name="group" type="myapp.ProductGroup" >
<sql name="group_id" />
</field>
<field name="details" type="myapp.ProductDetail" collection="vector">
<sql many-key="prod_id"/>
</field>
<field name="categories" type="myapp.Category" collection="vector">
<sql name="category_id"
many-table="category_prod" many-key="prod_id" />
</field>
</class> |
|
The following code fragment shows the corresponding mapping
entry for the ProductDetail class that defines the
second leg of the 1:M relation between Product and
ProductDetail.
<class name="myapp.ProductDetail" identity="id" depends="myapp.Product" >
<description>Product detail</description>
<map-to table="prod_detail" xml="detail" />
<field name="id" type="integer">
<sql name="id" type="integer"/>
</field>
<field name="name" type="string">
<sql name="name" type="char"/>
</field>
<field name="product" type="myapp.Product">
<sql name="prod_id" />
</field>
%lt;/class> |
|
M:N relation
The following code fragment shows (again) the mapping file for
the Product class. The field definition highlighted
shows how to declare a M:N relation between Product and
ProductCategory, where many products can be mapped to
many product categories:
<class name="myapp.Product" identity="id">
<map-to table="prod" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="name" type="string">
<sql name="name" type="char" />
</field>
<field name="price" type="float">
<sql name="price" type="numeric" />
</field>
<field name="group" type="myapp.ProductGroup" >
<sql name="group_id" />
</field>
<field name="details" type="myapp.ProductDetail" collection="vector">
<sql many-key="prod_id">/>
</field>
<field name="categories" type="myapp.Category" collection="vector">
<sql name="category_id"
many-table="category_prod" many-key="prod_id" />
</field>
</class> |
|
The following code fragment shows the corresponding mapping
entry for the ProductCategory class that defines the
second leg of the M:N relation between Product and
Category.
<class name="myapp.Category" identity="id">
<description>
A product category, any number of products can belong to
the same category, a product can belong to any number of
categories.
</description>
<map-to table="category" xml="category" />
<field name="id" type="integer">
<sql name="id" type="integer"/>
</field>
<field name="name" type="string">
<sql name="name" type="char"/>
</field>
<field name="products" type="myapp.Product" collection="vector">
<sql name="prod_id"
many-table="category_prod" many-key="category_id" />
</field>
</class> |
|
Extend relation & polymorphism
As of release 0.9.9, Castor supports polymorphic queries on extend
hierarchies. (That is, hierarchies where some entities "extend"
other entities.) To highlight this new feature, let's add two new
classes to what we have currently.
package myapp;
public class Computer extends Product {
private int _id;
private String _make;
public int getId() { ... }
public void setId( int anId ) { ... }
public String getmake() { ... }
public void setMake( String aMake ) { ... }
}
public class Car extends Product {
private int _id;
private Date _registeredIn;
public int getId() { ... }
public void setId( int anId ) { ... }
public Date getRegisteredIn() { ... }
public void setRegisteredIn( Date aRegisteredIn ) { ... }
} |
|
The corresponding DDL statements for the relational database tables
COMP and CAR would look as follows:
COMP:
create table comp (
id int not null,
make varchar(200) not null
); |
|
CAR:
create table car (
id int not null,
regIn int not null
); |
|
Based upon the mapping defined for the Product class as
shown above, the following code fragment shows the mapping for
the Computer and Car classes.
<class name="myapp.Computer" extends="myapp.Product" identity="id">
<map-to table="COMP" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="make" type="string">
<sql name="make" type="char" />
</field>
</class>
<class name="myapp.Car" extends="myapp.Product" identity="id">
<map-to table="CAR" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="registeredIn" type="date">
<sql name="regIn" type="long" />
</field>
</class> |
|
Based upon this mapping, it is possible to execute the following OQL
queries against this class model:
OQLQuery query = d.getOQLQuery("SELECT c FROM myapp.Computer c");
|
|
To return all computers:
OQLQuery query = d.getOQLQuery("SELECT c FROM myapp.Computer c WHERE c.make = $");
|
|
To return all computers of a particular make:
OQLQuery query = d.getOQLQuery("SELECT p FROM myapp.Product p");
|
|
To return all products (where Castor will return the actual object
instances, i.e. a Computer instance if the object returned
by the query is of type Computer or a Car instance
if the object returned by the query is of type Car):
OQLQuery query = d.getOQLQuery("SELECT p FROM myapp.Product p WHERE p.group.name = $");
|
|
To return all products that belong to the specified product group
(where Castor will return the actual object instances, i.e. a
Computer instance if the object returned by the query is of
type Computer or a Car instance if the object
returned by the query is of type Car):
OQL samples
Based upon above definitions, here are a few OQL sample queries that
highlight various artifacts of the OQL support of Castor JDO.
To Be Written
|