http://www.apache.org/licenses/LICENSE-2.0
•
|
JDBC applications and Derby basics
Basic
details for using Derby, including loading the JDBC driver, specifying
a database URL, and starting Derby.
| |
•
|
After installing
Explains the installation layout.
| |
•
|
Deploying Derby applications
An overview of different deployment scenarios, and tips for getting the details
right when deploying applications.
| |
•
|
Controlling Derby application behavior
JDBC, cursors, locking and isolation levels, and multiple connections.
| |
•
|
Using Derby as a J2EE resource manager
Information for programmers developing back-end components in a J2EE system.
| |
•
|
Developing Tools and Using Derby with an IDE
Tips for tool designers.
| |
•
|
SQL tips
Insiders' tricks of the trade for using SQL.
| |
•
|
Localizing Derby
An
overview of database localization.
|
•
|
marks the database as upgraded to the current release (Version 10.1).
| |
•
|
allows use of new features such as SYNONYMS with the upgraded database.
|
1.
|
Back up your database to a safe location using Derby online/offline
backup procedures.
For more information on backup, see the
Derby Server and Administration Guide
.
If you do not
perform a soft upgrade, then once the database is upgraded, it cannot be reverted
back to the previous version.
|
1.
|
Use the upgrade=true database connection URL attribute,
as shown in the following example:
Once the upgrade is complete, you cannot connect to the database
with an older version of Derby.
|
Note that this is the version of Derby, not the version of the database. Sysinfo uses information found in the Derby jar files, so verify that only one version of Derby's jar files are in your class path when you run this tool.java org.apache.derby.tools.sysinfo
•
|
Synonym functionality
| |
•
|
Creating tables using the GENERATED BY DEFAULT option for identity columns
| |
•
|
Reclaiming unused space using the SYSCS_UTIL.SYSCS_INPLACE_COMPRESS_TABLE
procedure
|
1.
|
Simply connect to the database, as shown in the following example:
In this example, the sample database is a Version 10.0 database. |
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
•
|
you can specify the name of the database you want to connect to
| |
•
|
you can specify a number of attributes and values that allow you to accomplish
tasks. For more information about what you can specify with the Derby connection URL,
see "Examples". For detailed reference about attributes and values,
as well as syntax of the database connection URL, see the "Derby Database
Connection URL Syntax" in the
Derby Reference Manual
.
|
Connection conn=DriverManager.getConnection("jdbc:derby:sample");
2005-06-10 03:54:06.196 GMT: Booting Derby version Apache Derby - 10.0.0.1 - (29612): instance c013800d-00fd-0cb0-e736-ffffd1025a25 on database directory sample
DriverManager.getConnection("jdbc:derby:;shutdown=true");
Sat Jan 10 14:31:54 PDT 2005: Shutting down instance 80000001-00d0-8bdf-d115-000a0a0b2d00
ERROR XJ040: Failed to start database 'sample', see the next exception for details. ERROR XSDB6: Another instance of Derby might have already booted the databaseC:\databases\sample.
WARNING: Derby (instance 80000000-00d2-3265-de92-000a0a0a0200) is attempting to boot the database /export/home/sky/wombat even though Derby (instance 80000000-00d2-3265-8abf-000a0a0a0200) might still be active. Only one instance of Derby should boot a database at a time. Severe and non-recoverable corruption can result and might have already occurred.
Sat Aug 14 09:42:51 PDT 2005: Booting Derby version Apache Derby - 10.0.0.1 - (29612): instance 80000000-00d2-1c87-7586-000a0a0b1300 on database at directory C:\tutorial_system\sample ------------------------------------------------------------ Sat Aug 14 09:42:59 PDT 2005: Booting Derby version Apache Derby - 10.0.0.1 - (29612): instance 80000000-00d2-1c87-9143-000a0a0b1300 on database at directory C:\tutorial_system\HelloWorldDB
•
|
All databases exist within a system.
| |
•
|
System-wide properties affect the entire system, and persistent system-wide
properties live in the system directory.
| |
•
|
You can boot all the databases in the system, and the boot-up times of
all databases affect the performance of the system.
| |
•
|
You can preboot databases only if they are within the system. (Databases
do not necessarily have to live inside the system directory, but keeping your databases there is the recommended practice.)
| |
•
|
Once you connect to a database, it is part of the current system and thus
inherits all system-wide properties.
| |
•
|
Only one instance of Derby can run in a JVM at a single time, and
only one instance of Derby should boot a database at one time. Keeping
databases in the system directory makes it less likely that you would use
more than one instance of Derby.
| |
•
|
The error log is located inside the system directory.
|
•
|
log directory
Contains files that make up the database transaction
log, used internally for data recovery (not the same thing as the error log).
| |
•
|
seg0 directory
Contains one file for each user table, system
table, and index (known as conglomerates).
| |
•
|
service.properties file
A text file with internal configuration
information.
| |
•
|
tmp directory
(might not exist.) A temporary directory used
by Derby for large sorts
and deferred updates and deletes. Sorts are used by a variety of SQL statements.
For databases on read-only media, you might need to set a property to change
the location of this directory. See "Creating Derby Databases
for Read-Only Use".
| |
•
|
jar directory
(might not exist.) A directory in which jar
files are stored when you use database class loading.
|
Type of Object
|
Limit
|
tables per database
|
java.lang.Long.MAX_VALUE
Some operating systems
impose a limit to the number of files allowed in a single directory.
|
indexes per table
|
32,767 or storage
|
columns per table
|
1,012
|
number of columns on an index key
|
16
|
rows per table
|
no limit
|
size of table
|
no limit Some operating systems impose a limit on the size
of a single file.
|
size of row
|
no limit--rows can span pages. Rows cannot span tables
so some operating systems impose a limit on the size of a single file, and
therefore limit the size of a table and size of a row in that table.
|
•
|
Indexes are not supported for columns defined on CLOB,
BLOB, and LONG VARCHAR data types.
If the length of the key columns
in an index is larger than half the page size of the index, creating an index
on those key columns for the table fails. For existing indexes, an insert
of new rows for which the key columns are larger than half of the index page
size causes the insert to fail.
It is generally not recommended to create
indexes on long columns. It is best to create indexes on small columns that
provide a quick look-up to larger, unwieldy data in the row. You might not
see performance improvements if you index long columns. For information about
indexes, see
Tuning Derby
.
| |
•
|
The system shuts down if the database log cannot allocate
more disk space.
A "LogFull" error or some sort of
IOException
will occur in the derby.log if the system runs out of space. If the system has no more
disk space to append to the derby.log, you might not
see the error messages.
|
jdbc:derby:myDB
Connection conn =DriverManager.getConnection("jdbc:derby:myDB");
jdbc:derby:../otherDirectory/myDB jdbc:derby:c:/otherDirectory/myDB
•
|
refer to a previously created Derby database
| |
•
|
specify the create=true attribute
|
jdbc:derby:directory:myDB
jdbc:derby:/sample
jdbc:derby:/demo/databases/sample
jdbc:derby:/jarDB1
jdbc:derby:jar:(c:/derby/lib/jar2.jar)jarDB2
•
|
jdbc:derby:db1
Open a connection to the database db1. db1 is a directory located
in the system directory.
| |
•
|
jdbc:derby:london/sales
Open a connection to
the database london/sales. london is a subdirectory of the system directory, and sales is a subdirectory of the directory london.
| |
•
|
jdbc:derby:/reference/phrases/french
Open a
connection to the database /reference/phrases/french.
On a UNIX system, this would be the path of the directory. On a Windows
system, the path would be C:\reference\phrases\french if
the current drive were C. If a jar file storing databases
were in the user's classpath, this could also be a path within the jar
file.
| |
•
|
jdbc:derby:a:/demo/sample
Open a connection
to the database stored in the directory \demo\sample on
drive A (usually the floppy drive) on a Windows system.
| |
•
|
jdbc:derby:c:/databases/salesdb jdbc:derby:salesdb
These two connection URLs connect to the same database, salesdb, on a Windows platform if the system directory of the Derby system
is C:\databases.
| |
•
|
jdbc:derby:support/bugsdb;create=true
Create
the database support/bugsdb in the system directory,
automatically creating the intermediate directory support if it does not exist.
| |
•
|
jdbc:derby:sample;shutdown=true
Shut down the sample database.
| |
•
|
jdbc:derby:/myDB
Access myDB (which is directly in a directory in the classpath) as a read-only
database.
| |
•
|
jdbc:derby:classpath:/myDB
Access myDB (which is directly in a directory in the classpath) as a read-only
database. The reason for using the subsubprotocol is that it might have the
same path as a database in the directory structure.
| |
•
|
jdbc:derby:jar:(C:/dbs.jar)products/boiledfood
Access the read-only database boiledfood in the products directory from the jar file C:/dbs.jar.
| |
•
|
jdbc:derby:directory:myDB
Access myDB, which is in the system directory. The reason for using the
directory:
subsubprotocol is that it might happen
to have the same path as a database in the classpath.
|
•
|
bootPassword=key
| |
•
|
create=true
| |
•
|
databaseName=nameofDatabase
| |
•
|
dataEncryption=true
| |
•
|
encryptionProvider=providerName
| |
•
|
encryptionAlgorithm=algorithm
| |
•
|
territory=ll_CC
| |
•
|
logDevice=logDirectoryPath
| |
•
|
createFrom=BackupPath
| |
•
|
restoreFrom=BackupPath
| |
•
|
rollForwardrecoveryFrom=BackupPath
| |
•
|
password=userPassword
| |
•
|
shutdown=true
| |
•
|
user=userName
|
jdbc:derby:;shutdown=true
// shutting down a database from your application DriverManager.getConnection( "jdbc:derby:sample;shutdown=true");
jdbc:derby:databaseName;create=true
jdbc:derby:sample;user=jill;password=toFetchAPail
jdbc:derby:encryptedDB;create=true;dataEncryption=true; bootPassword=DBpassword
jdbc:derby:encryptedDB;bootPassword=DBpassword
Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); Properties p = new Properties(); p.put("user", "sa"); p.put("password", "manager"); Connection conn = DriverManager.getConnection( "jdbc:derby:mynewDB", p);
C:>echo %DERBY_INSTALL% C:\DERBY_INSTALL
•
|
index.html in the top-level directory is the top
page for the on-line documentation.
| |||||||
•
|
release_notes.html, in the top-level Derby base
directory, contains important last-minute information. Read it first.
| |||||||
•
|
/demo contains some sample applications, useful
scripts, and prebuilt databases.
| |||||||
•
|
/doc contains the on-line documentation (including
this document).
| |||||||
•
|
/frameworks contains utilities and scripts for
running Derby.
| |||||||
•
|
/javadoc contains the documented APIs for the
public classes and interfaces. Typically, you use the JDBC interface to interact
with Derby; however, you can use some of these additional classes in
certain situations.
| |||||||
•
|
/lib contains the Derby libraries.
|
•
|
directory The default. Specify this explicitly
only to distinguish a database that might be ambiguous with one on the class
path.
| |
•
|
classpath Databases are treated as read-only databases,
and all databaseNames must begin with at least a slash,
because you specify them "relative" to the classpath directory.
| |
•
|
jar Databases are treated as read-only databases. DatabaseNames might require a leading slash, because you
specify them "relative" to the jar file.
|
jdbc:default:connection
•
|
Specify the jdbc.drivers system property, which
allows users to customize the JDBC drivers used by their applications. For
example:
|
•
|
Load the class directly from Java code using the static method Class.forName. For example:
|
Connection conn = DriverManager.getConnection("jdbc:derby:sample");
•
|
the Derby library (derby.jar)
| |
•
|
the application's libraries
You have the option of storing these
libraries in the database. (See
Loading classes from a database
.)
| |
•
|
the database or databases used by the application, in the context of their
system directory (see
Embedded systems and properties
)
Figure1. Deploying an application, embedded Derby software,
and the database. Storing the application in the database and setting properties
as database-wide properties simplify deployment.
![]() |
•
|
If you are setting any system-wide properties, see if they can be set
as database-wide properties instead.
| |
•
|
Are any properties being set in the derby.properties file? Some
properties can only be set on a system-wide basis. If so, deploy the entire
system directory along with the properties file. Deploy only those databases
that you wish to include. Setting properties programmatically can simplify
this step- you will not have to worry about deploying the system directory/properties
file.
|
1.
|
Create and populate the database on read-write media.
| |
2.
|
Commit all transactions and shut down Derby in
the prescribed manner (see
Shutting down Derby or an individual database
).
If you do not shut down Derby in
the prescribed manner, Derby will
need to perform recovery the next time the system boots. Derby cannot
perform recovery on read-only media.
| |
3.
|
Delete the tmp directory if one was created within your
database directory. If you include this directory, Derby will
attempt to delete it and will return errors when attempting to boot a database
on read-only media.
| |
4.
|
For the read-only database, set the property derby.storage.tempDirectory to
a writable location.
Derby needs
to write to temporary files for large sorts required by such SQL statements
as ORDER BY, UNION, DISTINCT, and GROUP BY. For more information about this
property, see
Tuning Derby
.
| |
5.
|
Configure the database to send error messages to a writable file
or to an output stream.
For information, see
Tuning Derby
.
|
1.
|
Follow the instructions for creating a database for use on read-only media.
See
Creating and preparing the database for read-only use
.
| |
2.
|
From the directory that contains the database folder, archive the database
directory and its contents. For example, for the database sales that lives in the system directory C:\london, issue the command from london. Do not issue
the command from inside the database directory itself.
|
cd C:\london jar cMf C:\dbs.jar sales
cd C:\london jar cMf C:\dbs.jar sales products\boiledfood
jdbc:derby:jar:(pathToArchive)databasePathWithinArchive
jdbc:derby:jar:(C:/dbs.jar)products/boiledfood jdbc:derby:jar:(C:/dbs.jar)sales
jdbc:derby:jar:(C:/dbs.jar)/products/boiledfood
1.
|
Set the classpath to include the jar or zip file before starting
up Derby:
| |
2.
|
Connect to a database within the jar or zip file with one of the
following connection URLs:
|
jdbc:derby:classpath:/products/boiledfood
jdbc:derby:directory:databasePathInFileSystem
jdbc:derby:directory:/products/boiledfood
1.
| ||
2.
| ||
3.
| ||
4.
|
•
|
the standard Java packages (java.*,
javax.*
)
Derby does not prevent you from storing such
a jar file in the database, but these classes are never
loaded from the jar file.
| |
•
|
those supplied with your Java environment (for example, sun.*)
|
jar cf travelagent.jar travelagent/*.class.
•
|
Extract the required third-party classes from their
jar file and include only those in your jar file.
Best if you need
only a small subset of the classes in the third-party jar file.
| |
•
|
Store the third-party jar file in the database.
Best if you need most or all of the classes in the third-party jar file, since
your application and third-party logic can be upgraded separately.
| |
•
|
Deploy the third-party jar file in the user's class
path.
Best if the classes are often already installed on a user's
machine (for example, Objectspace's JGL classes).
|
•
|
Separate jar files with a colon (:).
| |
•
|
Use two-part names for the jar files (schema name and jar name). Set the
property as a database-level property for the database. The first time you set the property, you must reboot to load the classes.
|
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.database.classpath', 'APP.ToursLogic:APP.ACCOUNTINGLOGIC')
•
|
Indirectly referencing them in the code
| |
•
|
Directly using java.lang.Class.forName
|
•
|
You originally configured database-level class
loading for the database correctly. Turning on the database-level class loading
property requires setting the
derby.database.classpath
property with valid two-part names, then rebooting.
| |
•
|
If changes to the derby.database.classpath property
are needed to reflect new jar files, you change the property to a valid value.
|
•
|
to avoid blocking and deadlocks
| |
•
|
to ensure that any updates done from within the method are atomic with
the outer transaction
|
Connection conn = DriverManager.getConnection( "jdbc:default:connection");
•
|
cannot issue a commit or rollback, unless called within a CALL statement.
| |
•
|
cannot change connection attributes such as auto-commit.
| |
•
|
cannot modify the data in a table used by the parent statement that called
the procedure, using INSERT, UPDATE, or DELETE. For example, if a SELECT statement
using the T table calls the
changeTables
procedure,
changeTables
cannot
modify data in the
T table.
| |
•
|
cannot drop a table used by the statement that called the procedure.
| |
•
|
cannot be in a class whose static initializer executes DDL statements.
|
CALL MYPROC()
try { preparedStatement.execute(); } catch (SQLException se ) { String SQLState = se.getSQLState(); if ( SQLState.equals( "23505" ) ) { correctDuplicateKey(); } else if ( SQLState.equals( "22003" ) ) { correctArithmeticOverflow(); } else { throw se; } }
•
|
The exception is an SQLException
| |
•
|
The range of the SQLState is 38001-38999
|
CREATE TRIGGER . . . DELETE FROM flightavailability WHERE flight_id IN (SELECT flight_id FROM flightavailability WHERE YEAR(flight_date) < 2005);)
•
|
the "before" values of the rows being changed (their values before
the database event that caused the trigger to fire)
| |
•
|
the "after" values of the rows being changed (the values to which
the database event is setting them)
|
CREATE TRIGGER trig1 AFTER UPDATE ON flights REFERENCING OLD AS UPDATEDROW FOR EACH ROW MODE DB2SQL INSERT INTO flights_history VALUES (UPDATEDROW.FLIGHT_ID, UPDATEDROW.SEGMENT_NUMBER, UPDATEDROW.ORIG_AIRPORT, UPDATEDROW.DEPART_TIME, UPDATED ROW.DEST_AIRPORT, UPDATEDROW.ARRIVE_TIME, UPDATEDROW.MEAL, UPDATEDROW.FLYING_TIME, UPDATEDROW.MILES, UPDATEDROW.AIRCRAFT,'INSERTED FROM trig1');
Connection conn = DriverManager.getConnection( "jdbc:derby:sample"); System.out.println("Connected to database sample"); conn.setAutoCommit(false); Connection conn2 = DriverManager.getConnection( "jdbc:derby:newDB;create=true"); System.out.println("Created AND connected to newDB"); conn2.setAutoCommit(false); Connection conn3 = DriverManager.getConnection( "jdbc:derby:newDB"); System.out.println("Got second connection to newDB"); conn3.setAutoCommit(false);
•
|
Cursors
You cannot use auto-commit if you do any positioned
updates or deletes (that is, an update or delete statement with a "WHERE CURRENT
OF" clause) on cursors which have the close cursors on commit option
set.
Auto-commit automatically closes cursors, which are explicitly
opened with the close on commit option, when you do any in-place updates
or deletes. For more information about cursors, see
SQL and JDBC ResultSet/Cursor mechanisms
.
A
cursor declared to be held across commit can execute updates and issue multiple
commits before closing the cursor, but the cursor must be repositioned before
any statement following the commit. If this is attempted with auto-commit
on, an error is generated.
| |||||||||||||||||||
•
|
Database-side JDBC Procedures (procedures using nested connections)
You cannot execute procedures within SQL statements if those procedures
perform a commit or rollback on the current connection. Since in the auto-commit
mode all SQL statements are implicitly committed, Derby turns
off auto-commit during execution of database-side procedures and turns it
back on when the method completes.
Procedures that use nested connections
are not permitted to turn auto-commit on or off or to commit or roll back.
| |||||||||||||||||||
•
|
Table-level locking and the SERIALIZABLE isolation level
When
an application uses table-level locking and the SERIALIZABLE isolation level,
all statements that access tables hold at least shared table locks. Shared
locks prevent other transactions that update data from accessing the table.
A transaction holds a lock on a table until the transaction commits. So
even a SELECT statement holds a shared lock on a table until its connection
commits and a new transaction begins.
Table1. Summary of Application Behavior with Auto-Commit On or Off
|
Connection conn = DriverManager.getConnection( "jdbc:derby:sample"); Statement s = conn.createStatement(); s.execute("set schema 'SAMP'"); //note that autocommit is on--it is on by default in JDBC ResultSet rs = s.executeQuery( "SELECT empno, firstnme, lastname, salary, bonus, comm " + "FROM samp.employee"); /** a standard JDBC ResultSet. It maintains a * cursor that points to the current row of data. The cursor * moves down one row each time the method next() is called. * You can scroll one way only--forward--with the next() * method. When auto-commit is on, after you reach the * last row the statement is considered completed * and the transaction is committed. */ System.out.println( "last name" + "," + "first name" + ": earnings"); /* here we are scrolling through the result set with the next() method.*/ while (rs.next()) { // processing the rows String firstnme = rs.getString("FIRSTNME"); String lastName = rs.getString("LASTNAME"); BigDecimal salary = rs.getBigDecimal("SALARY"); BigDecimal bonus = rs.getBigDecimal("BONUS"); BigDecimal comm = rs.getBigDecimal("COMM"); System.out.println( lastName + ", " + firstnme + ": " + (salary.add(bonus.add(comm)))); } rs.close(); // once we've iterated through the last row, // the transaction commits automatically and releases //shared locks s.close();
Statement s3 = conn.createStatement(); // name the statement so we can reference the result set // it generates s3.setCursorName("UPDATABLESTATEMENT"); // we will be able to use the following statement later // to access the current row of the cursor // a result set needs to be obtained prior to using the // WHERE CURRENT syntax ResultSet rs = s3.executeQuery("select * from FlightBookings FOR UPDATE of number_seats"); PreparedStatement ps2 = conn.prepareStatement( "UPDATE FlightBookings SET number_seats = ? " + "WHERE CURRENT OF UPDATABLESTATEMENT");
PreparedStatement ps2 = conn.prepareStatement( "UPDATE employee SET bonus = ? WHERE CURRENT OF "+ Updatable.getCursorName());
String URL = "jdbc:derby:sample"; // autocommit must be turned off for updatable cursors conn.setAutoCommit(false); Statement s3 = conn.createStatement(); // name the statement so we can reference the result set // it generates s3.setCursorName("UPDATABLESTATEMENT"); // Updatable statements have some requirements // for example, select must be on a single table ResultSet Updatable = s3.executeQuery( "SELECT firstnme, lastname, workdept, bonus" + "FROM employee FOR UPDATE of bonus"); // we need a separate statement to do the // update PreparedStatement PreparedStatement ps2 = conn.prepareStatement("UPDATE employee " + // we could use the cursor name known by the system, // as the following line shows //"SET bonus = ? WHERE CURRENT OF " + Updatable.getCursorName()); // but we already know the cursor name "SET bonus = ? WHERE CURRENT OF UPDATABLESTATEMENT"); String theDept="E21"; while (Updatable.next()) { String firstnme = Updatable.getString("FIRSTNME"); String lastName = Updatable.getString("LASTNAME"); String workDept = Updatable.getString("WORKDEPT"); BigDecimal bonus = Updatable.getBigDecimal("BONUS"); if (workDept.equals(theDept)) { // if the current row meets our criteria, // update the updatable column in the row ps2.setBigDecimal(1, bonus.add(new BigDecimal(250))); ps2.executeUpdate(); System.out.println("Updating bonus in employee" + " table for employee " + firstnme + ", department " + theDept ); } } Updatable.close(); s3.close(); ps2.close(); conn.commit();
//autocommit does not have to be off because even if //we accidentally scroll past the last row, the implicit commit //on the the statement will not close the result set because result sets //are held over commit by default conn.setAutoCommit(false); Statement s4 = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); s4.execute("set schema 'SAMP'"); ResultSet scroller=s4.executeQuery( "SELECT sales_person, region, sales FROM sales " + "WHERE sales > 8 ORDER BY sales DESC"); if (scroller.first()) System.out.println("The sales rep who sold the highest number of sales is " + scroller.getString("SALES_PERSON")); else System.out.println("There are no rows."); scroller.beforeFirst(); scroller.afterLast(); scroller.absolute(3); if (!scroller.isAfterLast()) System.out.println("The employee with the third highest number of sales is " + scroller.getString("SALES_PERSON") + ", with " + scroller.getInt("SALES") + " sales"); if (scroller.isLast()) System.out.println("There are only three rows."); if (scroller.last()) System.out.println("The least highest number of sales of the top three sales is: " + scroller.getInt("SALES")); scroller.close(); s4.close(); conn.commit() conn.close(); System.out.println("Closed connection");
•
|
CLOSE_CURSORS_AT_COMMIT
Cursors are closed when an
implicit or explicit commit is performed.
| |
•
|
HOLD_CURSORS_OVER_COMMIT
Cursors are held open when
a commit is performed, implicitly or explicitly. This is the default behavior.
|
•
|
Open ResultSets remain open. The cursor is positioned before the
next logical row of the result set.
| |||||||
•
|
When the session is terminated, the ResultSet is closed and destroyed.
| |||||||
•
|
All locks are released, except locks protecting the current cursor position
of open cursors specified to stay open after commits.
| |||||||
•
|
Immediately following a commit, the only valid operations that can be
performed on the ResultSet are:
|
Isolation levels for JDBC
|
Isolation levels for SQL
|
Connection.TRANSACTION_READ_ UNCOMMITTED (ANSI level
0)
|
UR, DIRTY READ, READ UNCOMMITTED
|
Connection.TRANSACTION_READ_COMMITTED (ANSI level
1)
|
CS, CURSOR STABILITY, READ COMMITTED
|
Connection.TRANSACTION_REPEATABLE_READ (ANSI level
2)
|
RS
|
Connection.TRANSACTION_SERIALIZABLE (ANSI level
3)
|
RR, REPEATABLE READ, SERIALIZABLE
|
Anomaly
|
Example
|
Dirty Reads
A dirty read happens when a transaction
reads data that is being modified by another transaction that has not yet
committed.
|
Transaction A begins.
Transaction B begins. (Transaction B sees data updated by transaction A. Those updates have not yet been committed.) |
Non-Repeatable Reads
Non-repeatable reads happen when
a query returns data that would be different if the query were repeated within
the same transaction. Non-repeatable reads can occur when other transactions
are modifying data that a transaction is reading.
|
Transaction A begins.
Transaction B begins. (Transaction B updates rows viewed by transaction A before transaction A commits.) If Transaction A issues the same SELECT statement, the results will be different. |
Phantom Reads
Records that appear in a set being read
by another transaction. Phantom reads can occur when other transactions insert
rows that would satisfy the WHERE clause of another transaction's statement.
|
Transaction A begins.
Transaction B begins. Transaction B inserts a row that would satisfy the query in Transaction A if it were issued again. |
Isolation Level
|
Table-Level Locking
|
Row-Level Locking
|
TRANSACTION_READ_UNCOMMITTED
|
Dirty reads, nonrepeatable reads, and phantom reads possible
|
Dirty reads, nonrepeatable reads, and phantom reads possible
|
TRANSACTION_READ_COMMITTED
|
Nonrepeatable reads and phantom reads possible
|
Nonrepeatable reads and phantom reads possible
|
TRANSACTION_REPEATABLE_READ
|
Phantom reads not possible because entire table is locked
|
Phantom reads possible
|
TRANSACTION_SERIALIZABLE
|
None
|
None
|
•
|
TRANSACTION_SERIALIZABLE
RR, SERIALIZABLE,
or REPEATABLE READ from SQL.
TRANSACTION_SERIALIZABLE means
that Derby treats the transactions
as if they occurred serially (one after the other) instead of concurrently. Derby issues locks to prevent
all the transaction anomalies listed in
Transaction Anomalies
from
occurring. The type of lock it issues is sometimes called a range lock.
For more information about range locks, see
Scope of locks
.
| |||||||
•
|
TRANSACTION_REPEATABLE_READ
RS from
SQL.
TRANSACTION_REPEATABLE_READ means that Derby issues
locks to prevent only dirty reads and non-repeatable reads, but not phantoms.
It does not issue range locks for selects.
| |||||||
•
|
TRANSACTION_READ_COMMITTED
CS or CURSOR
STABILITY from SQL.
TRANSACTION_READ_COMMITTED means
that Derby issues locks
to prevent only dirty reads, not all the transaction anomalies listed in
Transaction Anomalies
.
TRANSACTION_READ_COMMITTED is
the default isolation level for transactions.
| |||||||
•
|
TRANSACTION_READ_UNCOMMITTED
UR, DIRTY
READ, or READ UNCOMMITTED from SQL.
For a
SELECT INTO, FETCH with a read-only cursor, full select used in an INSERT,
full select/subquery in an UPDATE/DELETE, or scalar full select (wherever
used), READ UNCOMMITTED allows:
For other operations, the rules that apply to READ COMMITTED also
apply to READ UNCOMMITTED.
|
'
|
Shared
|
Update
|
Exclusive
|
Shared
|
+
|
+
|
-
|
Update
|
+
|
-
|
-
|
Exclusive
|
-
|
-
|
-
|
•
|
table locks
A statement can lock the entire table.
Table-level locking systems always lock entire tables.
Row-level locking systems can lock entire tables if the WHERE clause
of a statement cannot use an index. For example, UPDATES that cannot use an
index lock the entire table.
Row-level locking systems can lock entire
tables if a high number of single-row locks would be less efficient than a
single table-level lock. Choosing table-level locking instead of row-level
locking for performance reasons is called lock escalation. (For more information about this topic, see "About the System's
Selection of Lock Granularity" and "Transaction-Based Lock Escalation"
in
Tuning Derby
.)
| ||||||||||||||||
•
|
single-row locks
A statement can lock only a single row at a time.
This section applies only
to row-level locking systems.
For TRANSACTION_READ_COMMITTED or TRANSACTION_REPEATABLE_READ
isolation, Derby treats rows as cursors for SELECT statements. It locks
rows only as the application steps through the rows in the result. The current
row is locked. The row lock is released when the application goes to the next
row. (For TRANSACTION_SERIALIZABLE isolation, however, Derby locks the
whole set before the application begins stepping through.) For TRANSACTION_READ_UNCOMMITTED,
no row locks are requested.
Derby locks single rows for INSERT
statements, holding each row until the transaction is committed. (If there
is an index associated with the table, the previous key is also locked.)
| ||||||||||||||||
•
|
range locks
A statement can lock a range of rows (range lock).
This section applies only to row-level
locking systems.
For any isolation level, Derby locks all the rows in the result plus an entire range of rows
for updates or deletes.
For the TRANSACTION_SERIALIZABLE isolation level, Derby locks
all the rows in the result plus an entire range of rows in the table for SELECTs
to prevent nonrepeatable reads and phantoms.
For example, if a SELECT
statement specifies rows in the Employee table where
the salary is BETWEEN two values, the system can lock
more than just the actual rows it returns in the result. It also must lock
the entire range of rows between those two values
to prevent another transaction from inserting, deleting, or updating a row
within that range.
An index must be available for a range lock. If one
is not available, Derby locks the entire table.
Table1. Possible Types and Scopes of Locking
|
ERROR 40001: A lock could not be obtained due to a deadlock, cycle of locks & waiters is: Lock : ROW, DEPARTMENT, (1,14) Waiting XID : {752, X} , APP, update department set location='Boise' where deptno='E21' Granted XID : {758, X} Lock : ROW, EMPLOYEE, (2,8) Waiting XID : {758, U} , APP, update employee set bonus=150 where salary=23840 Granted XID : {752, X} The selected victim is XID : 752
/// if this code might encounter a deadlock, // put the whole thing in a try/catch block // then try again if the deadlock victim exception // was thrown try { s6.executeUpdate( "UPDATE employee " + "SET bonus = 625 " "WHERE empno='000150'"); s6.executeUpdate("UPDATE project " + "SET respemp = '000150' " + "WHERE projno='IF1000'"); } // note: do not catch such exceptions in database-side methods; // catch such exceptions only at the outermost level of // application code. // See Database-side JDBC procedures and SQLExceptions . catch (SQLException se) { if (se.getSQLState().equals("40001")) { // it was chosen as a victim of a deadlock. // try again at least once at this point. System.out.println( "Will try the transaction again."); s6.executeUpdate("UPDATE employee " + "SET bonus = 625 " + "WHERE empno='000150'"); s6.executeUpdate("UPDATE project " + "SET respemp = 000150 " + "WHERE projno='IF1000'"); } else throw se; }
•
|
Multiple applications access a single database (possible only when Derby is running inside a server
framework).
| |||||||||||||
•
|
A single application has more than one Connection to the same database.
The way you deploy Derby affects
the ways applications can use multi-threading and connections, as shown in
Threading and Connection Modes
.
Table1. Threading and Connection Modes
|
•
|
Use the TRANSACTION_READ_COMMITTED isolation level
and turn on row-level locking (the defaults).
| |
•
|
Beware of deadlocks caused by using more than one Connection in a single thread (the most obvious case). For example, if
the thread tries to update the same table from two different
Connections
, a deadlock can occur.
| |
•
|
Assign Connections to threads that handle discrete
tasks. For example, do not have two threads update the Hotels table. Have one thread update the Hotels table
and a different one update the Groups table.
| |
•
|
If threads access the same tables, commit transactions often.
| |
•
|
Multi-threaded Java applications have the ability to self-deadlock without
even accessing a database, so beware of that too.
| |
•
|
Use nested connections to share the same lock space.
|
•
|
Committing or rolling back a transaction closes all open ResultSet objects and currently executing Statements, unless you are using held cursors.
If one thread commits, it closes
the Statements and ResultSets of
all other threads using the same connection.
| |
•
|
Executing a Statement automatically closes any
existing open ResultSet generated by an earlier execution
of that Statement.
If threads share Statements, one thread could close another's ResultSet.
|
•
|
Avoid sharing Statements (and their
ResultSets
) among threads.
| |
•
|
Each time a thread executes a Statement, it should
process the results before relinquishing the
Connection
.
| |
•
|
Each time a thread accesses the Connection, it
should consistently commit or not, depending on application protocol.
| |
•
|
Have one thread be the "managing" database Connection thread that should handle the higher-level tasks, such as
establishing the
Connection
, committing,
rolling back, changing
Connection
properties
such as auto-commit, closing the
Connection
,
shutting down the database (in an embedded environment), and so on.
| |
•
|
Close ResultSets and
Statements
that are no longer needed in order to release resources.
|
•
|
Use row-level locking.
| |
•
|
Use the TRANSACTION_READ_COMMITTED isolation level.
| |
•
|
Avoid queries that cannot use indexes; they require locking of all the
rows in the table (if only very briefly) and might block an update.
|
PreparedStatement ps = conn.prepareStatement( "UPDATE account SET balance = balance + ? WHERE id = ?"); /* now assume two threads T1,T2 are given this java.sql.PreparedStatement object and that the following events happen in the order shown (pseudojava code)*/ T1 - ps.setBigDecimal(1, 100.00); T1 - ps.setLong(2, 1234); T2 - ps.setBigDecimal(1, -500.00); // *** At this point the prepared statement has the parameters // -500.00 and 1234 // T1 thinks it is adding 100.00 to account 1234 but actually // it is subtracting 500.00 T1 - ps.executeUpdate(); T2 - ps.setLong(2, 5678); // T2 executes the correct update T2 - ps.executeUpdate(); /* Also, the auto-commit mode of the connection can lead to some strange behavior.*/
catch (Throwable e) { System.out.println("exception thrown:"); errorPrint(e); } static void errorPrint(Throwable e) { if (e instanceof SQLException) SQLExceptionPrint((SQLException)e); else System.out.println("A non-SQL error: " + e.toString()); } static void SQLExceptionPrint(SQLException sqle) { while (sqle != null) { System.out.println("\n---SQLException Caught---\n"); System.out.println("SQLState: " + (sqle).getSQLState()); System.out.println("Severity: " + (sqle).getErrorCode()); System.out.println("Message: " + (sqle).getMessage()); sqle.printStackTrace(); sqle = sqle.getNextException(); } }
•
|
org.apache.derby.jdbc.EmbeddedDataSource
Implements javax.sql.DataSource interface, which a
JNDI server can reference. Typically this is the object that you work with
as a
DataSource
.
| |
•
|
org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource
Implements javax.sql.ConnectionPoolDataSource. A factory for
PooledConnection
objects.
| |
•
|
org.apache.derby.jdbc.EmbeddedXADataSource
Derby's implementation of a javax.sql.XADataSource.
|
import org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource; import org.apache.derby.jdbc.EmbeddedDataSource; import org.apache.derby.jdbc.EmbeddedXADataSource; javax.sql.ConnectionPoolDataSource cpds = new EmbeddedConnectionPoolDataSource(); javax.sql.DataSource ds = new EmbeddedDataSource(); javax.sql.XADataSource xads = new EmbeddedXADataSource();
•
|
DatabaseName
This mandatory property must
be set. It identifies which database to access. If a database named wombat
located at /local1/db/wombat is to be accessed, then one should call setDatabaseName("/local1/db/wombat") on the data source object.
| |
•
|
CreateDatabase
Optional. Sets a property to
create a database the next time the XADataSource.getXAConection() method is called. The string createString is
always "create" (or possibly null). (Use the method
setDatabaseName()
to define the name of the database.)
| |
•
|
ShutdownDatabase
Optional. Sets a property
to shut down a database. The string shutDownString is
always "shutdown" (or possibly null). Shuts down the database the
next time
XADataSource.getXAConnection().getConnection()
method is called.
| |
•
|
DataSourceName
Optional. Name for ConnectionPooledDataSource
or XADataSource. Not used by the data source object. Used for informational
purpose only.
| |
•
|
Description
Optional. Description of the data
source. Not used by the data source object. Used for informational purpose
only.
| |
•
|
connectionAttributes
Optional. Connection
attributes specific to Derby. See the
Derby Reference Manual
for a more
information about the attributes.
|
javax.sql.XADataSource xads = makeXADataSource(mydb, true); // example of setting property directory using // Derby 's XADataSource object import org.apache.derby.jdbc.EmbeddedXADataSource; import javax.sql.XADataSource; // dbname is the database name // if create is true, create the database if not already created XADataSource makeXADataSource (String dbname, boolean create) { EmbeddedXADataSource xads = new EmbeddedXADataSource(); // use Derby 's setDatabaseName call xads.setDatabaseName(dbname); if (create) xads.setCreateDatabase("create"); return xads; }
•
|
User authentication
Derby verifies
user names and passwords before permitting them access to the Derby system.
See
Working with user authentication
.
| |
•
|
User authorization
A means of granting specific users permission
to read a database or to write to a database. See
User authorization
.
| |
•
|
Disk encryption
A means of encrypting Derby data
stored on disk. See
Encrypting databases on disk
.
| |
•
|
Validation of Certificate for Signed Jar Files
In a Java 2
environment, Derby validates
certificates for classes loaded from signed jar files. See
Signed jar files
.
Figure1. Some of the Derby security
mechanisms at work in a client/server environment
![]()
Figure1. Another Derby security
mechanism, disk encryption, protects data when the recipient might not know
how to protect data. It is useful for databases deployed in an embedded environment.
![]() |
1.
|
When first working with security, work with system-level properties only
so that you can easily override them if you make a mistake.
| |
2.
|
Be sure to create at least one valid user, and grant that user full (read-write)
access. For example, you might always want to create a user called sa with the password
derby
while
you are developing.
| |
3.
|
Test the authentication system while it is still configured at the system
level. Be absolutely certain that you have configured the system correctly
before setting the properties as database-level properties.
| |
4.
|
Before disabling system-level properties (by setting derby.database.propertiesOnly to true), test that at least one database-level read-write user (such
as sa) is valid. If you do not have at least one valid
user that the system can authenticate, you will not be able to access your
database.
|
1.
|
Configure security features as system properties. See
Tuning Derby
.
| |
2.
|
Provide administrative-level protection for the derby.properties file and Derby databases. For example, you can protect these files
and directories with operating system permissions and firewalls.
| |
3.
|
Turn on user authentication for your system. All users must provide valid
user IDs and passwords to access the Derby system. See
Working with user authentication
for information. If you are using Derby's built-in
users, configure users for the system in the derby.properties file. Provide the protection for this file.
| |
4.
|
Configure user authorization for sensitive databases in your system.
Only designated users will be able to access sensitive databases. You typically
configure user authorization with database-level properties. See
User authorization
for information. It is also possible to configure user authorization
with system-level properties. This is useful when you are developing systems
or when all databases have the same level of sensitivity.
|
1.
|
Encrypt the database when you create it.
| |
2.
|
Configure all security features as database-level properties. These properties
are stored in the database (which is encrypted). See
Tuning Derby
.
| |
3.
|
Turn on protection for database-level properties so that they cannot be
overridden by system properties by setting the derby.database.propertiesOnly property to TRUE.
| |
4.
|
To prevent unauthorized users from accessing databases once they are booted,
turn on user authentication for the database and configure user authorization
for the database. See
Working with user authentication
and
User authorization
for more information.
| |
5.
|
If you are using Derby's built-in users, configure each user
as a database-level property so that user names and passwords can be encrypted.
|
•
|
External directory service
:
LDAP directory service
. This includes Windows NT domain user authentication through
the Netscape NT Synchronization Service.
| |
•
| ||
•
|
•
|
Netscape Directory Server
Netscape Directory Server is an LDAP directory
server. In addition, the Netscape Directory Synchronization Service synchronizes
entries in a Windows NT directory with the entries in Netscape's Directory
Server. It allows you to use the Windows NT directory as a repository for Derby users.
| |
•
|
UMich slapd (freeware for the UNIX platform from the University of Michigan)
| |
•
|
AE SLAPD for Windows NT, from AEInc
|
•
|
derby.authentication.server
Set the property derby.authentication.server to the location and port number
of the LDAP server. For example:
|
cn=mary,ou=People,o=FlyTours.com uid=mary,ou=People,o=FlyTours.com
•
|
You have set derby.authentication.ldap.searchFilter to derby.user.
| |
•
|
A user DN has been cached locally for the specific user with the derby.user.UserName property.
|
•
|
derby.authentication.ldap.searchAuthDN (optional)
Specifies the DN with which to bind (authenticate) to the server when searching
for user DNs. This parameter is optional if anonymous access is supported
by your server. If specified, this value must be a DN recognized by the directory
service, and it must also have the authority to search for the entries.
If not set, it defaults to an anonymous search using the root DN specified
by the derby.authentication.ldap.searchBase property.
For example:
| |
•
|
derby.authentication.ldap.searchAuthPW (optional)
Specifies the password to use for the guest user configured above to bind
to the directory service when looking up the DN. If not set, it defaults to
an anonymous search using the root DN specified by the derby.authentication.ldap.searchBase property.
| |
•
|
derby.authentication.ldap.searchBase (optional)
Specifies the root DN of the point in your hierarchy from which to begin a
guest search for the user's DN. For example:
When using Netscape Directory Server, set this property to the root
DN, the special entry to which access control does not apply (optional).
|
•
|
derby.authentication.ldap.searchFilter (optional)
Set derby.authentication.ldap.searchFilter to a logical
expression that specifies what constitutes a user for your LDAP directory
service. The default value of this property is
objectClass=inetOrgPerson
. For example:
|
import org.apache.derby.authentication.UserAuthenticator; import java.io.FileInputStream; import java.util.Properties; import java.sql.SQLException; /** * A simple example of a specialized Authentication scheme. * The system property 'derby.connection.requireAuthentication' * must be set * to true and 'derby.connection.specificAuthentication' must * contain the full class name of the overriden authentication * scheme, i.e., the name of this class. * * @see org.apache.derby.authentication.UserAuthenticator */ public class MyAuthenticationSchemeImpl implements UserAuthenticator { private static final String USERS_CONFIG_FILE = "myUsers.cfg"; private static Properties usersConfig; // Constructor // We get passed some Users properties if the //authentication service could not set them as //part of System properties. // public MyAuthenticationSchemeImpl() { } /* static block where we load the users definition from a users configuration file.*/ static { /* load users config file as Java properties File must be in the same directory where Derby gets started. (otherwise full path must be specified) */ FileInputStream in = null; usersConfig = new Properties(); try { in = new FileInputStream(USERS_CONFIG_FILE); usersConfig.load(in); in.close(); } catch (java.io.IOException ie) { // No Config file. Raise error message System.err.println( "WARNING: Error during Users Config file retrieval"); System.err.println("Exception: " + ie); } } /** * Authenticate the passed-in user's credentials. * A more complex class could make calls * to any external users directory. * * @param userName The user's name * @param userPassword The user's password * @param databaseName The database * @param infoAdditional jdbc connection info. * @exception SQLException on failure */ public boolean authenticateUser(String userName, String userPassword, String databaseName, Properties info) throws SQLException { /* Specific Authentication scheme logic. If user has been authenticated, then simply return. If user name and/or password are invalid, then raise the appropriate exception. This example allows only users defined in the users config properties object. Check if the passed-in user has been defined for the system. We expect to find and match the property corresponding to the credentials passed in. */ if (userName == null) // We do not tolerate 'guest' user for now. return false; // // Check if user exists in our users config (file) // properties set. // If we did not find the user in the users config set, then // try to find if the user is defined as a System property. // String actualUserPassword; actualUserPassword = usersConfig.getProperty(userName); if (actualUserPassword == null) actualUserPassword = System.getProperty(userName); if (actualUserPassword == null) // no such passed-in user found return false; // check if the password matches if (!actualUserPassword.equals(userPassword)) return false; // Now, check if the user is a valid user of the database if (databaseName != null) { /* if database users restriction lists present, then check if there is one for this database and if so, check if the user is a valid one of that database. For this example, the only user we authorize in database DarkSide is user 'DarthVader'. This is the only database users restriction list we have for this example. We authorize any valid (login) user to access the OTHER databases in the system. Note that database users ACLs could be set in the same properties file or a separate one and implemented as you wish. */ // if (databaseName.equals("DarkSide")) { // check if user is a valid one. if (!userName.equals("DarthVader")) // This user is not a valid one of the passed-in return false; } } // The user is a valid one in this database return true; } }
derby.authentication.provider=BUILTIN
derby.user."FRed"=java
-- adding the user sa with password 'derbypass' CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.user.sa', 'derbypass') -- adding the user mary with password 'little7xylamb' CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.user.mary', 'little7xylamb') -- removing mary by setting password to null CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.user.mary', null)
# Users definition # derby.user.sa=derbypass derby.user.mary=little7xylamb
Property Name
|
Use
|
derby.connection.requireAuthentication
|
Turns on user authentication.
|
derby.authentication.provider
|
Specifies the kind of user authentication to use.
|
derby.authentication.server
|
For LDAP user authentication, specifies the location of
the server.
|
derby.authentication.ldap.searchAuthDN, derby.authentication.ldap.searchAuthPW, Derby.authentication.ldap.searchFilter, and
Derby.authentication. ldap.searchBase
|
Configures the way DN searches are performed.
|
derby.user.UserName
|
Creates a user name and password for Derby's
built-in user repository.
|
javax.naming.*
|
JNDI properties
|
•
|
Separately as arguments to the following signature of the method: getConnection(String url, String user, String password)
| |
•
|
As attributes to the database connection URL
| |
•
|
By setting the user and password properties in a Properties object as
with other connection URL attributes
|
•
|
Within the user authentication system, Fred is known as FRed. Your external user authorization service is case-sensitive, so
Fred must always type his name that way.
| |
•
|
Within the Derby user authorization system, Fred becomes a case-insensitive
authorization identifier. Fred is known as FRED.
| |
•
|
When specifying which users are authorized to access the accounting database,
you must list Fred's authorization identifier, FRED (which you can type as FRED, FREd, or fred, since the system automatically
converts it to all-uppercase).
|
•
|
Within the user authentication system, Fred is known as Fred!. You must now put double quotes around the name, because it is
not a valid
SQL92Identifier
. (Derby knows
to remove the double quotes when passing the name to the external authentication
system.)
| |
•
|
Within the Derby user authorization system, Fred becomes a case-sensitive authorization identifier. Fred is known
as Fred!.
| |
•
|
When specifying which users are authorized to access the accounting database,
you must list Fred's authorization identifier, "Fred!" (which you must always delimit with double quotation marks).
|
•
|
noAccess
| |
•
|
readOnlyAccess
| |
•
|
fullAccess (the default)
|
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.database.fullAccessUsers', 'sa,mary')
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.database.readOnlyAccessUsers', 'guest,"Fred!"')
Action
|
Read-Only Users
|
Full-Access Users
|
Executing SELECT statements
|
X
|
X
|
Reading database properties
|
X
|
X
|
Loading database classes from jar files
|
X
|
X
|
Executing INSERT, UPDATE, or DELETE statements
|
'
|
X
|
Executing DDL statements
|
'
|
X
|
Adding or replacing jar files
|
'
|
X
|
Setting database properties
|
'
|
X
|
•
|
Full access for a single user named "sa"
| |
•
|
Read-only access for anyone else who connects to the database
|
•
|
An implementation of the Java Cryptographic Extension (JCE) package version
1.2.1 or higher.
Derby does not support earlier, non-exportable, versions
of JCE (such as JCE 1.2). More information on JCE 1.2.1, including a product
download, can be found at:
http://java.sun.com/products/jce/index.html
.
Any
attempt to create or access an encrypted database without the libraries for
an implementation of JCE of the proper version, or without Java
2 Platform, Standard Edition, v 1.2 (J2SE) or higher, raises an exception;
you will not be able to create or boot the database.
Note: The JCE installation
documentation describes configuring (registering) the JCE software. You do
not need to do this; Derby registers JCE dynamically.
| |
•
|
The encryption provider
An encryption provider implements the Java
cryptography concepts. The JRE for J2SE 1.4 or J2EE 1.4 includes JCE and one
or more default encryption providers.
|
•
|
For J2SE/J2EE 1.4 or higher, the JRE's provider is the default.
| |
•
|
For an IBM Corp J2SE/J2EE 1.3 JRE, the default provider is com.ibm.crypto.provider.
| |
•
|
For a Sun Microsystem J2SE/J2EE 1.3 JRE, the default provider is com.sun.crypto.provider.SunJCE.
| |
•
|
For any other J2SE/J2EE 1.3 JRE, a provider must be specified.
|
•
|
AES (128, 192, and 256 bits)
| |
•
|
DES (the default) (56 bits)
| |
•
|
DESede (168 bits)
| |
•
|
All other algorithms (128 bits)
|
jdbc:derby:encryptionDB1;create=true;dataEncryption=true; bootPassword=clo760uds2caPe
-- using the the provider library jce_jdk13-10b4.zip| -- available from www.bouncycastle.org jdbc:derby:encryptedDB3;create=true;dataEncryption=true; bootPassword=clo760uds2caPe; encryptionProvider=org.bouncycastle.jce.provider.BouncyCastleProvider; encryptionAlgorithm=DES/CBC/NoPadding -- using a provider -- available from -- http://jcewww.iaik.tu-graz.ac.at/download.html jdbc:derby:encryptedDB3;create=true;dataEncryption=true; bootPassword=clo760uds2caPe; encryptionProvider=iaik.security.provider.IAIK;encryptionAlgorithm= DES/CBC/NoPadding
•
|
DES (the default)
| |||||||||||||||||||
•
|
DESede (also known as triple DES)
| |||||||||||||||||||
•
|
Any encryption algorithm that fulfills the following requirements:
For example, the algorithm Blowfish implemented
in the Sun JCE package fulfills these requirements.
|
algorithmName/feedbackMode/padding
•
|
CBC
| |
•
|
CFB
| |
•
|
ECB
| |
•
|
OFB
|
jdbc:derby:wombat;bootPassword=clo760uds2caPe
•
|
The first connection to the database in the JVM session
| |
•
|
The first connection to the database after the database has been explicitly
shut down
| |
•
|
The first connection to the database after the system has been shut down
and then rebooted
|
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'bootPassword', 'oldbpw , newbpw');
•
|
If the class is signed, Derby will:
|
•
|
JVM subversion, running the application under a home-grown JVM.
| |
•
|
Trolling for objects
| |
•
|
Class substitution, locating a class that has access to sensitive data
and replacing it with one that passes on information
|
# turn on user authentication derby.connection.requireAuthentication=true # set the authentication provider to an external LDAP server derby.authentication.provider=LDAP # the host name and port number of the LDAP server derby.authentication.server=godfrey:389 # the search base for user names derby.authentication.ldap.searchBase=o=oakland.mycompany.com # explicitly show the access mode for databases (this is default) derby.database.defaultAccessMode=fullAccess
CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.connection.requireAuthentication', 'true') CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.authentication.provider', 'BUILTIN') CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.user.enduser', 'red29PlaNe') CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY( 'derby.database.propertiesOnly', true')
/** * Turn on built-in user authentication and user authorization. * * @param conn a connection to the database. */ public static void turnOnBuiltInUsers(Connection conn) throws SQLException { System.out.println("Turning on authentication."); Statement s = conn.createStatement(); // Setting and Confirming requireAuthentication s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.connection.requireAuthentication', 'true')"); ResultSet rs = s.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.connection.requireAuthentication')"); rs.next(); System.out.println(rs.getString(1)); // Setting authentication scheme to Derby s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.authentication.provider', 'BUILTIN')"); // Creating some sample users s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.user.sa', 'ajaxj3x9')"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.user.guest', 'java5w6x')"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.user.mary', 'little7xylamb')"); // Setting default connection mode to no access // (user authorization) s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.defaultConnectionMode', 'noAccess')"); // Confirming default connection mode rs = s.executeQuery ( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.database.defaultConnectionMode')"); rs.next(); System.out.println(rs.getString(1)); // Defining read-write users s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.fullAccessUsers', 'sa,mary')"); // Defining read-only users s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.readOnlyAccessUsers', 'guest')"); // Confirming full-access users rs = s.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.database.fullAccessUsers')"); rs.next(); System.out.println(rs.getString(1)); // Confirming read-only users rs = s.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.database.readOnlyAccessUsers')"); rs.next(); System.out.println(rs.getString(1)); //we would set the following property to TRUE only //when we were ready to deploy. s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.propertiesOnly', 'false')"); s.close(); }
/** * Turn off built-in user authentication and user authorization. * * @param conn a connection to the database. */ public static void turnOffBuiltInUsers(Connection conn) throws SQLException { Statement s = conn.createStatement(); System.out.println("Turning off authentication."); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.connection.requireAuthentication', 'false')"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.authentication.provider', null)"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.user.sa', null)"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.user.guest', null)"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.user.mary', null)"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.defaultConnectionMode', 'fullAccess')"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.fullAccessUsers', null)"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.readOnlyAccessUsers', null)"); s.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" + "'derby.database.propertiesOnly', 'false')"); // Confirming requireAuthentication ResultSet rs = s.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.connection.requireAuthentication')"); rs.next(); System.out.println(rs.getString(1)); // Confirming default connection mode rs = s.executeQuery( "VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY(" + "'derby.database.defaultConnectionMode')"); rs.next(); System.out.println(rs.getString(1)); System.out.println("Turned off all the user-related properties."); s.close(); } }
This allows the Derby engine complete access to the system directory and any databases contained in the system directory.permission java.io.FilePermission "${derby.system.home}/-", "read,write,delete"
/* Grants permission to run Derby and access all */ /* databases under the Derby system home */ /* when it is specified by the system property */ /* Derby.system.home */ /* Note Derby.system.home must be an absolute pathname */ grant codeBase "file://f:/derby/lib/derby.jar" { permission java.lang.RuntimePermission "createClassLoader"; permission java.util.PropertyPermission "derby.*", "read"; permission.java.io.FilePermission "${derby.system.home}","read"; permission java.io.FilePermission "${derby.system.home}${/} -", "read,write,delete"; };
/* Grants permission to run Derby and access all */ /* databases under the Derby system home */ /* when it defaults to the current directory */ grant codeBase "file://f:/derby/lib/derby.jar" { permission java.lang.RuntimePermission "createClassLoader"; permission java.util.PropertyPermission "derby.*", "read"; permission java.util.PropertyPermission "user.dir", "read"; permission java.io.FilePermission "${derby.system.home}","read"; permission java.io.FilePermission "${user.dir}${/}-", "read,write,delete"; };
/* Grants permission to run Derby and access a single */ /* database (salesdb) under the Derby system home */ /* Note Derby.system.home must be an absolute pathname */ grant codeBase "file://f:/derby/lib/derby.jar" { permission java.lang.RuntimePermission "createClassLoader"; permission java.util.PropertyPermission "derby.*", "read"; permission java.io.FilePermission "${derby.system.home}","read"; permission java.io.FilePermission "${derby.system.home}${/}*", "read,write,delete"; permission java.io.FilePermission "${derby.system.home}${/} salesdb${/} -", "read,write,delete"; };
java.sql.DriverManager.getDriver( "jdbc:derby:").getPropertyInfo(URL, Prop)
•
|
name of the attribute
| |
•
|
description
| |
•
|
current value
If an attribute has a default
value, this is set in the value field of DriverPropertyInfo, even if the attribute has not been set in the connection URL or the
Properties
object. If the attribute does not have
a default value and it is not set in the URL or the
Properties
object, its value will be null.
| |
•
|
list of choices
| |
•
|
whether required for a connection request
|
import java.sql.*; import java.util.Properties; // start with the least amount of information // to see the full list of choices // we could also enter with a URL and Properties // provided by a user. String url = "jdbc:derby:"; Properties info = new Properties(); Driver cDriver = DriverManager.getDriver(url); for (;;) { DriverPropertyInfo[] attributes = cDriver.getPropertyInfo( url, info); // zero length means a connection attempt can be made if (attributes.length == 0) break; // insert code here to process the array, e.g., // display all options in a GUI and allow the user to // pick and then set the attributes in info or URL. } // try the connection Connection conn = DriverManager.getConnection(url, info);
•
|
You test an individual query or database connection and then try to run
an application that uses the same database as the tested feature.
The
database connection established by testing the connection or query stays open,
and prevents the application from establishing a connection to the same database.
| |
•
|
You run an application, and before it completes (for example, while it
waits for user input), you attempt to run a second application or to test
a connection or query that uses the same database as the first application.
|
/* in java */ String myURL = conn.getMetaData().getURL();
SELECT phonebook.* FROM phonebook, (VALUES (CAST(? AS INT), CAST(? AS VARCHAR(255)))) AS Choice(choice, search_string) WHERE search_string = (case when choice = 1 then firstnme when choice=2 then lastname when choice=3 then phonenumber end);
CREATE TABLE MAPS ( MAP_ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), MAP_NAME VARCHAR(24) NOT NULL, REGION VARCHAR(26), AREA DECIMAL(8,4) NOT NULL, PHOTO_FORMAT VARCHAR(26) NOT NULL, PICTURE BLOB(102400), UNIQUE (MAP_ID, MAP_NAME) )
INSERT INTO OneColumnTable VALUES 1,2,3,4,5,6,7,8 INSERT INTO TwoColumnTable VALUES (1, 'first row'), (2, 'second row'), (3, 'third row')
-- send 5 rows at a time: PREPARE p1 AS 'INSERT INTO ThreeColumnTable VALUES (?,?,?), (?,?,?), (?,?,?), (?,?,?), (?,?,?) EXECUTE p1 USING 'VALUES (''1st'',1,1,''2nd'',2,2''3rd'', 3,3,''4th'',4,4,''5th'',5,5)'
-- get the names of all departments in Ohio SELECT DeptName FROM Depts, (VALUES (1, 'Shoe'), (2, 'Laces'), (4, 'Polish')) AS DeptMap(DeptCode,DeptDesc) WHERE Depts.DeptCode = DeptMap.DeptCode AND Depts.DeptLocn LIKE '%Ohio%'
SELECT * FROM (VALUES ('',1,"TRUE")) AS ProcedureInfo(ProcedureName,NumParameters, ProcedureValid) WHERE 1=0
•
|
Database error messages are in the language of the locale, if support
is explicitly provided for that locale with a special library.
For example, Derby explicitly supports Spanish-language
error messages. If a database's locale is set to one of the Spanish-language
locales, Derby returns
error messages in the Spanish language.
| |
•
|
The Derby tools. In
the case of the tools, locale support includes locale-specific interface and
error messages and localized data display.
For more information about
localization of the Derby tools,
see the
Derby Tools and Utilities Guide
.
|
•
|
You must have the locale-specific Derby jar file. Derby provides
such jars for only some locales. You will find the locale jar files in the
/lib directory in your Derby installation.
| |
•
|
The locale-specific Derby jar file must be in the classpath.
|
•
|
derbyLocale_de_DE.jar German
| |
•
|
derbyLocale_es.jar - Spanish
| |
•
|
derbyLocale_fr.jar - French
| |
•
|
derbyLocale_it.jar - Italian
| |
•
|
derbyLocale_ja_JP.jar - Japanese
| |
•
|
derbyLocale_ko_KR.jar - Korean
| |
•
|
derbyLocale_pt_BR.jar - Brazilian Portuguese
| |
•
|
derbyLocale_zh_CN.jar - Simplified Chinese
| |
•
|
derbyLocale_zh_TW.jar - Traditional Chinese
|
•
|
GROUP BY clauses
| |
•
|
ORDER BY clauses
| |
•
|
JOIN operations
| |
•
|
PRIMARY KEY constraints
| |
•
|
Foreign KEY constraints
| |
•
|
UNIQUE key constraints
| |
•
|
MIN aggregate function
| |
•
|
MAX aggregate function
| |
•
|
[NOT] IN predicate
| |
•
|
UNION, INTERSECT, and EXCEPT operators
|