Day 3 - Kuali Wiki

Download Report

Transcript Day 3 - Kuali Wiki

Training - Day 3
OJB
What is OR Mapping?
• OR Mapping is the mapping of relational
database tables to objects (Java Objects in
our case)
• Many OR Mapping tools available
– Hibernate
– iBatis
– OJB
• UIS supports Apache OJB
– Current version: 1.0.4
Apache OJB
• Open source project sponsored by the
Apache Project
• Makes working with a database feel like
working with an Java object model
• SQL is seldom used
– OJB generates the SQL
– Criteria objects
Some of the features…
•
•
•
•
•
•
•
•
•
•
•
•
•
Store and retrieve Java objects to/from any JDBC compliant RDMS
No special interfaces needed for your OJB objects – transparent
persistence
Object graphs can be persisted by persisting the root object
Mapping support for 1:1, 1:n, and m:n associations
OR Mappings defined in an XML repository
Can use multiple databases
Lazy loading via proxies (JDK or CGLIB)
Support for polymorphism and extents
Multiple sequence manager implementations
Connection pooling and reuse of prepared statements
JTA and JCA integration
Optimistic (via number or timestamp) and pessimistic locking supported
Support for object caching
Supported APIs
• Persistence Broker (PB)
– Low level kernel API
– Foundation of the others below
• ODMG
– Object Data Management Group Persistence 3.0
– Full support
• JDO
– Java Data Objects
– Partial support
• OTM
– Object Transaction Manager
– API or tool to build other tools on
– Specific to OJB
Persistence Broker
• Kuali supported API
• Low level API compared to OTM,
ODMG or JDO, but still very easy to use
• Store, update, delete, and retrieve
objects or collections of objects
• More on the PB after we learn how to
configure OJB and map relationships
OJB.properties
• Usually found on the root of the project
classpath
• When upgrading OJB from any version,
this file should be replaced and updated
• Key points
– Location of the repository.xml file
– How to obtain database connections
– How to obtain proxies
– How to manage transactions
Example
• Let’s take a look at a real
OJB.properties file
The Repository Mapping
• repository.xml usually on the root of the
project classpath
• A DTD is also needed
• Good idea to break up the contents of
repository.xml for easy reuse (testing)
– repository_user.xml : OR Mappings
– repository_database.xml : Database config
repository.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE descriptor-repository PUBLIC
"-//Apache Software Foundation//DTD OJB Repository//EN"
"repository.dtd"
[
<!ENTITY database SYSTEM "repository_database.xml">
<!ENTITY user SYSTEM "repository_user.xml">
]>
<descriptor-repository version="1.0"
isolation-level="read-uncommitted"
proxy-prefetching-limit="50">
<!-- include all used database connections -->
&database;
<!-- include user defined mappings here -->
&user;
</descriptor-repository>
repository_database.xml
<!-- Datasource example -->
<jdbc-connection-descriptor
jcd-alias="MYDB"
default-connection="true"
platform="Oracle9i"
jdbc-level="3.0"
batch-mode="false"
useAutoCommit="1"
ignoreAutoCommitExceptions="false"
testOnBorrow="true"
testWhileIdle="true"
testOnReturn="true"
validationQuery="select 1 from dual">
<object-cache class="org.apache.ojb.broker.cache.ObjectCachePerBrokerImpl">
</object-cache>
<sequence-manager
className="org.apache.ojb.broker.util.sequence.SequenceManagerNextValImpl">
</sequence-manager>
</jdbc-connection-descriptor>
<class-descriptor>
• Where you define your table to object
mapping
<class-descriptor
class="edu.iu.uis.train.domain.User"
table="TRN_USR_T">
<field-descriptor>
• A database column, or object property
<field-descriptor
name=”username"
column=”usr_nm"
jdbc-type="VARCHAR" />
A few special fields
• Primary keys
– primarykey=“true”
• Auto-incrementing PK
– autoincrement=“true”
– Will use the Sequence Manager that you have configured
– If using Oracle sequences, you can set the sequence name:
sequence-name=“some seq”
• Locking field (we use optimistic locking – fast, data
integrity only checked on an update)
– locking=“true”
– Need to store a hidden locking field on JSP pages
– Long – incremented each time the column is updated
• Long is recommended because of Oracle
• Other possibilities are Integer and Timestamp
JDBC Types
JDBC Type
Java Type
CHAR
VARCHAR
LONGVARCHAR
NUMERIC
DECIMAL
BIT
BOOLEAN
TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT
DOUBLE
BINARY
VARBINARY
LONGVARBINARY
DATE
TIME
TIMESTAMP
CLOB
BLOB
ARRAY
DISTINCT
STRUCT
REF
DATALINK
JAVA_OBJECT
String
String
String
java.math.BigDecimal
java.math.BigDecimal
boolean / Boolean
boolean / Boolean
Byte / byte
Short / short
Integer / int
Long / long
Float / float
Double / double
Double / double
byte[]
byte[]
byte[]
java.sql.Date
java.sql.Time
java.sql.Timestamp
Clob
Blob
Array
mapping of underlying type
Struct
Ref
java.net.URL
underlying Java class
<reference-descriptor>
• 1:1 Relationship
<reference-descriptor
name=”movie"
class-ref="edu.iu.uis.train.domain.Movie"
auto-retrieve="true"
auto-update="false"
auto-delete="false" >
<foreignkey field-ref=”movieId"
target-field-ref="movieId"/>
</reference-descriptor>
<collection-descriptor>
• 1:n Relationship or m:n Relationship
<collection-descriptor
name=”userCollection"
element-class-ref="edu.iu.uis.train.domain.User"
auto-retrieve="true"
auto-update="true"
auto-delete="true"
proxy="false">
<inverse-foreignkey field-ref=”userId"
target-field-ref=”userId"/>
</collection-descriptor>
repository_user.xml
• Let’s take a looks at this file in the
exercises project
Exercise: Time to map your
business objects
• Open repository_user.xml and complete
the TODO items
– Need DDL for columns and types
– Need domain objects for attribute names
(which are mapped to the columns)
Getting back to the PB API
• You can use the PB to:
– Query
– Insert and update
– Delete
• It can also tap into database
transactions, which you should probably
do just about all, if not all, the time
Saving an object
public static void storeProduct(Product product) {
PersistenceBroker broker = null;
try {
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.beginTransaction();
broker.store(product);
broker.commitTransaction();
}catch(PersistenceBrokerException e) {
if(broker != null) broker.abortTransaction();
// do more exception handling
}finally {
if (broker != null) broker.close();
}
}
Saving multiple objects
public static void storeProducts(List products) {
PersistenceBroker broker = null;
try {
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.beginTransaction();
for (Object productObj : products) {
Project product = (Product) productObj;
broker.store(product);
}
broker.commitTransaction();
} catch(PersistenceBrokerException e) {
if(broker != null) broker.abortTransaction();
// do more exception handling
} finally {
if (broker != null) broker.close();
}
}
Deleting an object
public static void storeProduct(Product product) {
PersistenceBroker broker = null;
try {
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
broker.beginTransaction();
broker.delete(product);
broker.commitTransaction();
}catch(PersistenceBrokerException e){
if(broker != null) broker.abortTransaction();
// do more exception handling
}finally {
if (broker != null) broker.close();
}
}
Querying in OJB
• You can build up a template object and query
• You can use raw sql if you need to bypass OJB
• You can use a Criteria object
– Recommended way
– This is the only way I will demonstrate for now, but there’s
great docs on the OJB website if you want to try something
else
A simple query
public static Collection getExpensiveLowStockProducts() {
PersistenceBroker broker = null;
Collection results = null;
try {
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
Criteria criteria = new Criteria();
criteria.addLessOrEqualThan("stock", new Integer(20));
criteria.addGreaterOrEqualThan("price", new Double(100000.0));
QueryByCriteria query = new QueryByCriteria(Product.class, criteria);
results = broker.getCollectionByQuery(query);
} finally {
if (broker != null) broker.close();
}
return results;
}
More about the Criteria
• You can add just about any kind of
“criteria” to build up an SQL statement
• Let’s take a look at the API
http://db.apache.org/ojb/api/org/apache/ojb/broker/query/Criteria.html
Updating an object
public static boolean sellOneProduct(Integer stock) {
PersistenceBroker broker = null;
boolean isSold = false;
try {
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
Criteria criteria = new Criteria();
criteria.addLessOrEqualThan("stock", stock);
criteria.addGreaterOrEqualThan("price", new Double(100000.0));
QueryByCriteria query = new QueryByCriteria(Product.class, criteria);
Product result = (Product) broker.getObjectByQuery(query);
if (result != null) {
broker.beginTransaction();
result.setStock(new Integer(result.getStock().intValue() - 1));
broker.store(result);
broker.commitTransaction();
isSold = true;
}
} catch(PersistenceBrokerException e) {
if(broker != null) broker.abortTransaction();
// do more exception handling
} finally {
if (broker != null) broker.close();
}
return isSold;
}
Exercise: The MovieDAOImpl
• It’s time to write your first DAO
• You shouldn’t need to extend any files,
just implement the MovieDAO interface
– Use eclipse to do this when you create the
class and it will create all of the methods
for you
– Let’s do this part together
A better way to do all this
• Now that you’ve seen how the PB API
works, there’s a much better way to
work with OJB
• We will see more of this when we talk
about Spring
References
• Object Relational Bridge
– http://db.apache.org/ojb/
• OJB Tutorials
– http://db.apache.org/ojb/docu/tutorials/sum
mary.html