blob: a8e4f976f98506d09c2586792043db70ddb7dced [file] [log] [blame]
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _`Javadoc`: /javadoc/model/
.. _`DynaBeans`: http://jakarta.apache.org/commons/beanutils/apidocs/index.html?org/apache/commons/beanutils/DynaBean.html
Java API
========
The model
---------
At the core of DdlUtils lies the database model in package
``org.apache.ddlutils.model``. It consists of classes that
represent the database schema:
.. image:: images/model.png
:alt: UML diagram of the database model
Using the appropriate methods on these classes, you can build the
database model manually, or you read it from XML or from the database
(see the next paragraphs for details). More info about the classes
can be found in the `Javadoc`_.
Reading from XML
----------------
Most of the time you have a schema in an XML file, and you want to
read it into memory in order to do something with it. This is quite easily
accomplished with a few lines of code::
import org.apache.ddlutils.io.DatabaseIO;
import org.apache.ddlutils.model.Database;
...
public Database readDatabaseFromXML(String fileName)
{
return new DatabaseIO().read(fileName);
}
Writing to XML
--------------
Writing a model to XML is just as easy as reading from XML::
import org.apache.ddlutils.io.DatabaseIO;
import org.apache.ddlutils.model.Database;
...
public void writeDatabaseToXML(Database db, String fileName)
{
new DatabaseIO().write(db, fileName);
}
Reading the model from a live database
--------------------------------------
Reading the database model from a live database is only slightly more involved
because we first need to create a platform instance via the data source pointing
to the database::
import javax.sql.DataSource;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformFactory;
import org.apache.ddlutils.model.Database;
...
public Database readDatabase(DataSource dataSource)
{
Platform platform = PlatformFactory.createNewPlatformInstance(dataSource);
return platform.readModelFromDatabase("model");
}
Changing a database
-------------------
Changing a database essentially means one of two things: resetting a database to the
schema defined by the model, or altering the database to have the same model. The key
difference is that with the latter, data in the database is retained as much as
possible. Only major changes to the table structure or type-incompatible alterations of
columns will result in loss of data, most changes will simply retain the data.
.. note:: Whether a change of e.g. a column type affects the data contained in the table, depends
on the database that you use. Most databases are able to convert between different
datatypes and will apply these conversions when the column type is changed.
Both types of modification differ only in how the SQL is created, the general procedure
is the same: create the sql and execute it::
import javax.sql.DataSource;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformFactory;
import org.apache.ddlutils.model.Database;
...
public void changeDatabase(DataSource dataSource,
Database targetModel,
boolean alterDb)
{
Platform platform = PlatformFactory.createNewPlatformInstance(dataSource);
if (alterDb)
{
platform.alterTables(targetModel, false);
}
else
{
platform.createTables(targetModel, true, false);
}
}
.. note:: Databases like Oracle allow for more than one separate schema in one database. To cater
for these databases, there are variants of these methods where you can specify the
catalog and schema.
Inserting data into a database
------------------------------
DdlUtils provides a simple way to insert data into the database. For this it uses
`DynaBeans`_ which are essentially dynamically created beans with variable properties.
For each table defined by the database model, a so-called dyna class is created that
represents the table with its columns. Of this dyna class, instances - the dyna beans -
are then created which can be inserted by DdlUtils into the database::
import javax.sql.DataSource;
import org.apache.commons.beanutils.DynaBean;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformFactory;
import org.apache.ddlutils.model.Database;
...
public void insertData(DataSource dataSource,
Database database)
{
Platform platform = PlatformFactory.createNewPlatformInstance(dataSource);
// "author" is a table of the model
DynaBean author = database.createDynaBeanFor("author", false);
// "name" and "whatever" are columns of table "author"
author.set("name", "James");
author.set("whatever", new Integer(1234));
platform.insert(database, author);
}
Getting data from a database
----------------------------
In the same way as inserting data into a database, DdlUtils uses dyna beans
for retrieving data from the database. You issue a SQL select against the
database and get dyna beans back. This means that the table that the select
goes against, has to be part of the database model used by DdlUtils.
In the following sample, the titles of all books in the database are printed
to stdout::
import java.util.ArrayList;
import java.util.Iterator;
import javax.sql.DataSource;
import org.apache.commons.beanutils.DynaBean;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformFactory;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.Table;
...
public void dumpBooks(DataSource dataSource,
Database database)
{
Platform platform = PlatformFactory.createNewPlatformInstance(dataSource);
ArrayList params = new ArrayList();
params.add("Some title");
Iterator it = platform.query(database,
"select * from book where title = ?",
params,
new Table[] { database.findTable("book") });
while (it.hasNext())
{
DynaBean book = (DynaBean)it.next();
System.out.println(book.get("title"));
}
}
There are two things to note in this sample code:
First, we specified so-called query hints in the call to the ``query``. Query hints
are an array of tables whose columns are used by the query statement. The reason why they
should be used is that not all databases provide sufficient information in the JDBC result set
object to determine the table to which a column belongs to. Since this info is need by
DdlUtils to properly extract the value and convert it to the corresponding Java type, it is
safer to specify these hints. What DdlUtils does in this case, is to search for a column
of that name within the specified tables and use the mapping for this column. This of course
can fail if you use aliases in the query statement (and the JDBC driver handles them in
a strange way), or if more than one table has a column of this name. But in most cases you'll
get the expected results.
The other thing to note is that DdlUtils does not parse the query statement. This means that
if you use delimited identifier mode (i.e. identifiers can contain whitespaces, non-alphanumeric
characters etc., but they also need to be enclosed in double quotes), then you'll have to
specify the query statement accordingly - DdlUtils won't do that for you. If you'd like to be
on the safe side, then you could write the above statement like this::
import java.util.ArrayList;
import java.util.Iterator;
import javax.sql.DataSource;
import org.apache.commons.beanutils.DynaBean;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformFactory;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.Table;
...
public void dumpBooks(DataSource dataSource,
Database database)
{
Platform platform = PlatformFactory.createNewPlatformInstance(dataSource);
ArrayList params = new ArrayList();
String sql;
params.add("Some title");
if (platform.isDelimitedIdentifierModeOn())
{
sql = "select * from \"book\" where \"title\" = ?";
}
else
{
sql = "select * from book where title = ?";
}
Iterator it = platform.query(database,
sql,
params,
new Table[] { database.findTable("book") });
while (it.hasNext())
{
DynaBean book = (DynaBean)it.next();
System.out.println(book.get("title"));
}
}