Revamped JORA to avoid keeping connection objects around which is not thread
safe and particularly not so in the webapp where one thread might come slip a read-only connection into the session before an update was about to happen. This ends up being a giant refactor, but it's much cleaner this way (to pass a connection into the Table whenever it is doing anything), so I've taken the pain. Fortuanately, code that uses the convenience methods doesn't need to change, so as a part of this refactor I've taken the opportunity to switch a bunch of old stuff to the new, concise, future proof hotness. git-svn-id: https://samskivert.googlecode.com/svn/trunk@1830 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -30,7 +30,7 @@ import com.samskivert.jdbc.jora.*;
|
|||||||
* The JORA repository simplifies the process of building persistence
|
* The JORA repository simplifies the process of building persistence
|
||||||
* services that make use of the JORA object relational mapping package.
|
* services that make use of the JORA object relational mapping package.
|
||||||
*
|
*
|
||||||
* @see com.samskivert.jdbc.jora.Session
|
* @see com.samskivert.jdbc.jora.Table
|
||||||
*/
|
*/
|
||||||
public abstract class JORARepository extends SimpleRepository
|
public abstract class JORARepository extends SimpleRepository
|
||||||
{
|
{
|
||||||
@@ -47,17 +47,12 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
{
|
{
|
||||||
super(provider, dbident);
|
super(provider, dbident);
|
||||||
|
|
||||||
// our parent class will have already obtained a database connection
|
|
||||||
// and therefore ended up calling getConnection() which will create our
|
|
||||||
// session, so we can make use of it straight away
|
|
||||||
|
|
||||||
// create our tables
|
// create our tables
|
||||||
createTables(_session);
|
createTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts the supplied object into the specified table. The table must be
|
* Inserts the supplied object into the specified table.
|
||||||
* configured to store items of the supplied type.
|
|
||||||
*
|
*
|
||||||
* @return a call to {@link DatabaseLiaison#lastInsertedId} made
|
* @return a call to {@link DatabaseLiaison#lastInsertedId} made
|
||||||
* immediately following the insert.
|
* immediately following the insert.
|
||||||
@@ -69,15 +64,14 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
table.insert(object);
|
table.insert(conn, object);
|
||||||
return liaison.lastInsertedId(conn);
|
return liaison.lastInsertedId(conn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the supplied object in the specified table. The table must
|
* Updates the supplied object in the specified table.
|
||||||
* be configured to store items of the supplied type.
|
|
||||||
*
|
*
|
||||||
* @return the number of rows modified by the update.
|
* @return the number of rows modified by the update.
|
||||||
*/
|
*/
|
||||||
@@ -88,7 +82,26 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.update(object);
|
return table.update(conn, object);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates fields specified by the supplied field mask in the supplied
|
||||||
|
* object in the specified table.
|
||||||
|
*
|
||||||
|
* @return the number of rows modified by the update.
|
||||||
|
*/
|
||||||
|
protected <T> int update (final Table<T> table, final T object,
|
||||||
|
final FieldMask mask)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return executeUpdate(new Operation<Integer>() {
|
||||||
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.update(conn, object, mask);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -106,7 +119,7 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
Connection conn, DatabaseLiaison liaison)
|
Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.select(query).toArrayList();
|
return table.select(conn, query).toArrayList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -124,7 +137,43 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
Connection conn, DatabaseLiaison liaison)
|
Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.select(auxtable, query).toArrayList();
|
return table.select(conn, auxtable, query).toArrayList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all objects from the specified table that match the supplied
|
||||||
|
* example.
|
||||||
|
*/
|
||||||
|
protected <T> ArrayList<T> loadAllByExample (
|
||||||
|
final Table<T> table, final T example)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
|
public ArrayList<T> invoke (
|
||||||
|
Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.queryByExample(conn, example).toArrayList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all objects from the specified table that match the supplied
|
||||||
|
* example.
|
||||||
|
*/
|
||||||
|
protected <T> ArrayList<T> loadAllByExample (
|
||||||
|
final Table<T> table, final T example, final FieldMask mask)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return execute(new Operation<ArrayList<T>>() {
|
||||||
|
public ArrayList<T> invoke (
|
||||||
|
Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.queryByExample(conn, example, mask).toArrayList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -141,7 +190,25 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public T invoke (Connection conn, DatabaseLiaison liaison)
|
public T invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.select(query).get();
|
return table.select(conn, query).get();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a single object from the specified table that matches the supplied
|
||||||
|
* query, joining with the supplied auxiliary table(s). <em>Note:</em> the
|
||||||
|
* query should match one or zero records, not more.
|
||||||
|
*/
|
||||||
|
protected <T> T load (
|
||||||
|
final Table<T> table, final String auxtable, final String query)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
return execute(new Operation<T>() {
|
||||||
|
public T invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
|
throws SQLException, PersistenceException
|
||||||
|
{
|
||||||
|
return table.select(conn, auxtable, query).get();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -158,7 +225,7 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public T invoke (Connection conn, DatabaseLiaison liaison)
|
public T invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.queryByExample(example).get();
|
return table.queryByExample(conn, example).get();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -169,14 +236,14 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
* records, not more.
|
* records, not more.
|
||||||
*/
|
*/
|
||||||
protected <T> T loadByExample (
|
protected <T> T loadByExample (
|
||||||
final Table<T> table, final FieldMask mask, final T example)
|
final Table<T> table, final T example, final FieldMask mask)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<T>() {
|
return execute(new Operation<T>() {
|
||||||
public T invoke (Connection conn, DatabaseLiaison liaison)
|
public T invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.queryByExample(example, mask).get();
|
return table.queryByExample(conn, example, mask).get();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -196,8 +263,8 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
if (table.update(object) == 0) {
|
if (table.update(conn, object) == 0) {
|
||||||
table.insert(object);
|
table.insert(conn, object);
|
||||||
return liaison.lastInsertedId(conn);
|
return liaison.lastInsertedId(conn);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -221,7 +288,7 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.update(object, mask);
|
return table.update(conn, object, mask);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -244,7 +311,7 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.update(object, mask);
|
return table.update(conn, object, mask);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -261,30 +328,14 @@ public abstract class JORARepository extends SimpleRepository
|
|||||||
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
public Integer invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws SQLException, PersistenceException
|
throws SQLException, PersistenceException
|
||||||
{
|
{
|
||||||
return table.delete(object);
|
return table.delete(conn, object);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After the database session is begun, this function will be called
|
* During construction, this function will be called to give the repository
|
||||||
* to give the repository implementation the opportunity to create its
|
* implementation the opportunity to create its table objects.
|
||||||
* table objects.
|
|
||||||
*
|
|
||||||
* @param session the session instance to use when creating your table
|
|
||||||
* instances.
|
|
||||||
*/
|
*/
|
||||||
protected abstract void createTables (Session session);
|
protected abstract void createTables ();
|
||||||
|
|
||||||
protected void gotConnection (Connection conn)
|
|
||||||
{
|
|
||||||
// create or update our JORA session
|
|
||||||
if (_session == null) {
|
|
||||||
_session = new Session(conn);
|
|
||||||
} else {
|
|
||||||
_session.setConnection(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Session _session;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class MySQLLiaison implements DatabaseLiaison
|
|||||||
String msg = sqe.getMessage();
|
String msg = sqe.getMessage();
|
||||||
return (msg != null &&
|
return (msg != null &&
|
||||||
(msg.indexOf("Lost connection") != -1 ||
|
(msg.indexOf("Lost connection") != -1 ||
|
||||||
msg.indexOf("Communication link failure") != -1 ||
|
msg.indexOf("link failure") != -1 ||
|
||||||
msg.indexOf("Broken pipe") != -1));
|
msg.indexOf("Broken pipe") != -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
//-< Cursor.java >---------------------------------------------------*--------*
|
//
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
// $Id$
|
||||||
// (Java Object Relational Adapter) * /\| *
|
//
|
||||||
// * / \ *
|
// samskivert library - useful routines for java programs
|
||||||
// Created: 10-Jun-98 K.A. Knizhnik * / [] \ *
|
// Copyright (C) 2001-6 Konstantin Knizhnik, Michael Bayne
|
||||||
// Last update: 20-Jun-98 K.A. Knizhnik * GARRET *
|
//
|
||||||
//-------------------------------------------------------------------*--------*
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
// Cursor for navigation thru result of SELECT statement
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
//-------------------------------------------------------------------*--------*
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
package com.samskivert.jdbc.jora;
|
||||||
|
|
||||||
@@ -15,81 +25,67 @@ import java.sql.*;
|
|||||||
|
|
||||||
import com.samskivert.Log;
|
import com.samskivert.Log;
|
||||||
|
|
||||||
/** Cursor is used for successive access to records fetched by SELECT
|
/**
|
||||||
* statement. As far as records can be retrived from several derived tables
|
* Cursor is used for successive access to records fetched by SELECT statement.
|
||||||
* (polymorphic form of select), this class can issue several requests
|
* As far as records can be retrived from several derived tables (polymorphic
|
||||||
* to database. Cursor also provides methods for updating/deleting current
|
* form of select), this class can issue several requests to database. Cursor
|
||||||
* record.
|
* also provides methods for updating/deleting current record.
|
||||||
*/
|
*/
|
||||||
public class Cursor<V>
|
public class Cursor<V>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* A cursor is initially positioned before its first row; the
|
* A cursor is initially positioned before its first row; the first call to
|
||||||
* first call to next makes the first row the current row; the
|
* next makes the first row the current row; the second call makes the
|
||||||
* second call makes the second row the current row, etc.
|
* second row the current row, etc.
|
||||||
*
|
*
|
||||||
* <P>If an input stream from the previous row is open, it is
|
* <P> If an input stream from the previous row is open, it is implicitly
|
||||||
* implicitly closed. The ResultSet's warning chain is cleared
|
* closed. The ResultSet's warning chain is cleared when a new row is read.
|
||||||
* when a new row is read.
|
|
||||||
*
|
*
|
||||||
* @return object constructed from fetched record or null if there
|
* @return object constructed from fetched record or null if there are no
|
||||||
* are no more rows
|
* more rows
|
||||||
*/
|
*/
|
||||||
public V next ()
|
public V next ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
// // if we closed everything up after the last call to next(),
|
// if we closed everything up after the last call to next(),
|
||||||
// // table will be null here and we should bail immediately
|
// table will be null here and we should bail immediately
|
||||||
if (table == null) {
|
if (_table == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// if (nTables == 0) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// do {
|
if (_result == null) {
|
||||||
if (result == null) {
|
if (_qbeObject != null) {
|
||||||
// if (table.isAbstract) {
|
PreparedStatement qbeStmt;
|
||||||
// table = table.derived;
|
synchronized (_table.preparedStmtHash) {
|
||||||
// continue;
|
qbeStmt = _table.preparedStmtHash.get(_query);
|
||||||
// }
|
if (qbeStmt == null) {
|
||||||
if (qbeObject != null) {
|
qbeStmt = _conn.prepareStatement(_query);
|
||||||
PreparedStatement qbeStmt;
|
_table.preparedStmtHash.put(_query, qbeStmt);
|
||||||
synchronized(session.preparedStmtHash) {
|
|
||||||
Object s = session.preparedStmtHash.get(query);
|
|
||||||
if (s == null) {
|
|
||||||
qbeStmt=
|
|
||||||
session.connection.prepareStatement(query);
|
|
||||||
session.preparedStmtHash.put(query, qbeStmt);
|
|
||||||
} else {
|
|
||||||
qbeStmt = (PreparedStatement)s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
synchronized(qbeStmt) {
|
}
|
||||||
table.bindQueryVariables(
|
synchronized (qbeStmt) {
|
||||||
qbeStmt, qbeObject, qbeMask);
|
_table.bindQueryVariables(qbeStmt, _qbeObject, _qbeMask);
|
||||||
result = qbeStmt.executeQuery();
|
_result = qbeStmt.executeQuery();
|
||||||
qbeStmt.clearParameters();
|
qbeStmt.clearParameters();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (stmt == null) {
|
if (_stmt == null) {
|
||||||
stmt = session.connection.createStatement();
|
_stmt = _conn.createStatement();
|
||||||
}
|
}
|
||||||
result = stmt.executeQuery(query);
|
_result = _stmt.executeQuery(_query);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (result.next()) {
|
}
|
||||||
return currObject = table.load(result);
|
if (_result.next()) {
|
||||||
}
|
return _currObject = _table.load(_result);
|
||||||
result.close();
|
}
|
||||||
result = null;
|
|
||||||
currObject = null;
|
|
||||||
table = null;
|
|
||||||
// table = table.derived;
|
|
||||||
// } while (--nTables != 0);
|
|
||||||
|
|
||||||
if (stmt != null) {
|
_result.close();
|
||||||
stmt.close();
|
_result = null;
|
||||||
|
_currObject = null;
|
||||||
|
_table = null;
|
||||||
|
|
||||||
|
if (_stmt != null) {
|
||||||
|
_stmt.close();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -111,77 +107,81 @@ public class Cursor<V>
|
|||||||
if (spurious > 0) {
|
if (spurious > 0) {
|
||||||
Log.warning("Cursor.get() quietly tossed " + spurious +
|
Log.warning("Cursor.get() quietly tossed " + spurious +
|
||||||
" spurious additional records. " +
|
" spurious additional records. " +
|
||||||
"[query=" + query + "].");
|
"[query=" + _query + "].");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update current record pointed by cursor. This method can be called
|
/**
|
||||||
* only after next() method, which returns non-null object. This objects
|
* Update current record pointed by cursor. This method can be called only
|
||||||
* is used to update current record fields.<P>
|
* after next() method, which returns non-null object. This objects is used
|
||||||
|
* to update current record fields.
|
||||||
*
|
*
|
||||||
* If you are going to update or delete selected records, you should add
|
* <P> If you are going to update or delete selected records, you should
|
||||||
* "for update" clause to select statement. So parameter of
|
* add "for update" clause to select statement. So parameter of
|
||||||
* <CODE>jora.Table.select()</CODE> statement should contain "for update"
|
* <CODE>jora.Table.select()</CODE> statement should contain "for update"
|
||||||
* clause:
|
* clause: <CODE>record.table.Select("where name='xyz' for
|
||||||
* <CODE>record.table.Select("where name='xyz' for update");</CODE><P>
|
* update");</CODE><P>
|
||||||
*
|
*
|
||||||
* <I><B>Attention!</I></B>
|
* <I><B>Attention!</I></B> Not all database drivers support update
|
||||||
* Not all database drivers support update operation with
|
* operation with cursor. This method will not work with such database
|
||||||
* cursor. This method will not work with such database drivers.
|
* drivers.
|
||||||
*/
|
*/
|
||||||
public void update ()
|
public void update ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
if (currObject == null) {
|
if (_currObject == null) {
|
||||||
throw new NoCurrentObjectError();
|
throw new IllegalStateException("No current object");
|
||||||
}
|
}
|
||||||
table.updateVariables(result, currObject);
|
_table.updateVariables(_result, _currObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Delete current record pointed by cursor. This method can be called
|
/**
|
||||||
* only after next() method, which returns non-null object.<P>
|
* Delete current record pointed by cursor. This method can be called only
|
||||||
|
* after next() method, which returns non-null object.
|
||||||
*
|
*
|
||||||
* If you are going to update or delete selected records, you should add
|
* <P> If you are going to update or delete selected records, you should
|
||||||
* "for update" clause to select statement. So parameter of
|
* add "for update" clause to select statement. So parameter of
|
||||||
* <CODE>jora.Table.select()</CODE> statement should contain "for update"
|
* <CODE>jora.Table.select()</CODE> statement should contain "for update"
|
||||||
* clause:
|
* clause: <CODE>record.table.Select("where name='xyz' for
|
||||||
* <CODE>record.table.Select("where name='xyz' for update");</CODE><P>
|
* update");</CODE><P>
|
||||||
*
|
*
|
||||||
* <I><B>Attention!</I></B>
|
* <I><B>Attention!</I></B> Not all database drivers support delete
|
||||||
* Not all database drivers support delete operation with cursor.
|
* operation with cursor. This method will not work with such database
|
||||||
* This method will not work with such database drivers.
|
* drivers.
|
||||||
*/
|
*/
|
||||||
public void delete ()
|
public void delete ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
if (currObject == null) {
|
if (_currObject == null) {
|
||||||
throw new NoCurrentObjectError();
|
throw new IllegalStateException("No current object");
|
||||||
}
|
}
|
||||||
result.deleteRow();
|
_result.deleteRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the Cursor, even if we haven't read all the possible
|
* Close the Cursor, even if we haven't read all the possible objects.
|
||||||
* objects.
|
|
||||||
*/
|
*/
|
||||||
public void close ()
|
public void close ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
if (stmt != null) {
|
if (_result != null) {
|
||||||
stmt.close(); // also automatically closes result
|
_result.close();
|
||||||
result = null;
|
_result = null;
|
||||||
stmt = null;
|
}
|
||||||
|
if (_stmt != null) {
|
||||||
|
_stmt.close();
|
||||||
|
_stmt = null;
|
||||||
}
|
}
|
||||||
// nTables = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extracts no more than <I>maxElements</I> records from database and
|
/**
|
||||||
* store them into array. It is possible to extract rest records
|
* Extracts no more than <I>maxElements</I> records from database and store
|
||||||
* by successive next() or toArray() calls. Selected objects should
|
* them into array. It is possible to extract rest records by successive
|
||||||
* have now components of InputStream, Blob or Clob type, because
|
* next() or toArray() calls. Selected objects should have now components
|
||||||
* their data will be not available after fetching next record.
|
* of InputStream, Blob or Clob type, because their data will be not
|
||||||
|
* available after fetching next record.
|
||||||
*
|
*
|
||||||
* @param maxElements limitation for result array size (and also for number
|
* @param maxElements limitation for result array size (and also for number
|
||||||
* of fetched records)
|
* of fetched records)
|
||||||
@@ -198,58 +198,46 @@ public class Cursor<V>
|
|||||||
return al;
|
return al;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Store all objects returned by SELECT query into a list of Object.
|
/**
|
||||||
* Selected objects should have now components of InputStream, Blob or
|
* Store all objects returned by SELECT query into a list of Object.
|
||||||
* Clob type, because their data will be not available after fetching
|
* Selected objects should have now components of InputStream, Blob or Clob
|
||||||
* next record.
|
* type, because their data will be not available after fetching next
|
||||||
|
* record.
|
||||||
*
|
*
|
||||||
* @return Array with objects constructed from fetched records.
|
* @return Array with objects constructed from fetched records.
|
||||||
*/
|
*/
|
||||||
public ArrayList<V> toArrayList()
|
public ArrayList<V> toArrayList ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
return toArrayList(Integer.MAX_VALUE);
|
return toArrayList(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internals
|
protected Cursor (Table<V> table, Connection conn, String query)
|
||||||
|
|
||||||
protected Cursor (
|
|
||||||
Table<V> table, Session session, int nTables, String query)
|
|
||||||
{
|
{
|
||||||
if (session == null) {
|
_table = table;
|
||||||
session = ((SessionThread)Thread.currentThread()).session;
|
_conn = conn;
|
||||||
}
|
_query = query;
|
||||||
this.table = table;
|
|
||||||
this.session = session;
|
|
||||||
// this.nTables = nTables;
|
|
||||||
this.query = query;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Cursor (Table<V> table, Session session, int nTables, V obj,
|
protected Cursor (Table<V> table, Connection conn, V obj,
|
||||||
FieldMask mask, boolean like)
|
FieldMask mask, boolean like)
|
||||||
{
|
{
|
||||||
if (session == null) {
|
_table = table;
|
||||||
session = ((SessionThread)Thread.currentThread()).session;
|
_conn = conn;
|
||||||
}
|
_like = like;
|
||||||
this.table = table;
|
_qbeObject = obj;
|
||||||
this.session = session;
|
_qbeMask = mask;
|
||||||
// this.nTables = nTables;
|
_query = table.buildQueryList(obj, mask, like);
|
||||||
this.like = like;
|
_stmt = null;
|
||||||
qbeObject = obj;
|
|
||||||
qbeMask = mask;
|
|
||||||
query = table.buildQueryList(obj, mask, like);
|
|
||||||
stmt = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Table<V> table;
|
protected Table<V> _table;
|
||||||
private Session session;
|
protected Connection _conn;
|
||||||
// private int nTables;
|
protected ResultSet _result;
|
||||||
private ResultSet result;
|
protected String _query;
|
||||||
private String query;
|
protected Statement _stmt;
|
||||||
private Statement stmt;
|
protected V _currObject, _qbeObject;
|
||||||
private V currObject;
|
protected FieldMask _qbeMask;
|
||||||
private V qbeObject;
|
protected boolean _like;
|
||||||
private FieldMask qbeMask;
|
|
||||||
private boolean like;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
//-< FieldDescriptor.java >------------------------------------------*--------*
|
//
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
// $Id$
|
||||||
// (Java Object Relational Adapter) * /\| *
|
//
|
||||||
// * / \ *
|
// samskivert library - useful routines for java programs
|
||||||
// Created: 10-Jun-98 K.A. Knizhnik * / [] \ *
|
// Copyright (C) 2001-6 Konstantin Knizhnik, Michael Bayne
|
||||||
// Last update: 25-Jun-98 K.A. Knizhnik * GARRET *
|
//
|
||||||
//-------------------------------------------------------------------*--------*
|
// This library is free software; you can redistribute it and/or modify it
|
||||||
// Table field descriptor
|
// under the terms of the GNU Lesser General Public License as published
|
||||||
//-------------------------------------------------------------------*--------*
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
package com.samskivert.jdbc.jora;
|
||||||
|
|
||||||
@@ -14,10 +24,370 @@ import java.sql.*;
|
|||||||
import java.math.*;
|
import java.math.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
class FieldDescriptor {
|
class FieldDescriptor
|
||||||
|
{
|
||||||
|
protected FieldDescriptor (Field field, String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.field = field;
|
||||||
|
this.scale = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean isAtomic ()
|
||||||
|
{
|
||||||
|
return inType < tClosure;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean isCompound ()
|
||||||
|
{
|
||||||
|
return inType >= tCompound;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean isBuiltin ()
|
||||||
|
{
|
||||||
|
return inType <= t_boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean bindVariable (
|
||||||
|
PreparedStatement pstmt, Object obj, int column)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
switch (outType) {
|
||||||
|
case t_byte:
|
||||||
|
pstmt.setByte(column, field.getByte(obj));
|
||||||
|
break;
|
||||||
|
case t_short:
|
||||||
|
pstmt.setShort(column, field.getShort(obj));
|
||||||
|
break;
|
||||||
|
case t_int:
|
||||||
|
pstmt.setInt(column, field.getInt(obj));
|
||||||
|
break;
|
||||||
|
case t_long:
|
||||||
|
pstmt.setLong(column, field.getLong(obj));
|
||||||
|
break;
|
||||||
|
case t_float:
|
||||||
|
pstmt.setFloat(column, field.getFloat(obj));
|
||||||
|
break;
|
||||||
|
case t_double:
|
||||||
|
pstmt.setDouble(column, field.getDouble(obj));
|
||||||
|
break;
|
||||||
|
case t_boolean:
|
||||||
|
pstmt.setBoolean(column, field.getBoolean(obj));
|
||||||
|
break;
|
||||||
|
case tByte:
|
||||||
|
pstmt.setByte(column, ((Byte)field.get(obj)).byteValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tShort:
|
||||||
|
pstmt.setShort(column, ((Short)field.get(obj)).shortValue());
|
||||||
|
break;
|
||||||
|
case tInteger:
|
||||||
|
pstmt.setInt(column, ((Integer)field.get(obj)).intValue());
|
||||||
|
break;
|
||||||
|
case tLong:
|
||||||
|
pstmt.setLong(column, ((Long)field.get(obj)).longValue());
|
||||||
|
break;
|
||||||
|
case tFloat:
|
||||||
|
pstmt.setFloat(column, ((Float)field.get(obj)).floatValue());
|
||||||
|
break;
|
||||||
|
case tDouble:
|
||||||
|
pstmt.setDouble(column,((Double)field.get(obj)).doubleValue());
|
||||||
|
break;
|
||||||
|
case tBoolean:
|
||||||
|
pstmt.setBoolean(column,
|
||||||
|
((Boolean)field.get(obj)).booleanValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tDecimal:
|
||||||
|
pstmt.setBigDecimal(column, (BigDecimal)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tString:
|
||||||
|
pstmt.setString(column, (String)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tBytes:
|
||||||
|
pstmt.setBytes(column, (byte[])field.get(obj));
|
||||||
|
break;
|
||||||
|
case tDate:
|
||||||
|
pstmt.setDate(column, (java.sql.Date)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tTime:
|
||||||
|
pstmt.setTime(column, (java.sql.Time)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tTimestamp:
|
||||||
|
pstmt.setTimestamp(column, (java.sql.Timestamp)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tStream:
|
||||||
|
java.io.InputStream in = (java.io.InputStream)field.get(obj);
|
||||||
|
pstmt.setBinaryStream(column, in, in.available());
|
||||||
|
break;
|
||||||
|
case tBlob:
|
||||||
|
pstmt.setBlob(column, (Blob)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tClob:
|
||||||
|
pstmt.setClob(column, (Clob)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tAsString:
|
||||||
|
pstmt.setString(column, field.get(obj).toString());
|
||||||
|
break;
|
||||||
|
case tClosure:
|
||||||
|
// There is no reason to use piped streams because
|
||||||
|
// we need to pass total number of bytes to JDBC driver
|
||||||
|
java.io.ByteArrayOutputStream out =
|
||||||
|
new java.io.ByteArrayOutputStream();
|
||||||
|
java.io.ObjectOutputStream clu =
|
||||||
|
new java.io.ObjectOutputStream(out);
|
||||||
|
clu.writeObject(field.get(obj));
|
||||||
|
clu.close();
|
||||||
|
pstmt.setBytes(column, out.toByteArray());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(SQLException ex) {
|
||||||
|
if (outType != tClosure && outType != tAsString) {
|
||||||
|
outType = tAsString;
|
||||||
|
return bindVariable(pstmt, obj, column);
|
||||||
|
} else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} catch(IllegalAccessException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
throw new IllegalAccessError();
|
||||||
|
} catch(java.io.IOException ex) {
|
||||||
|
throw new DataTransferError(ex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean updateVariable (
|
||||||
|
ResultSet result, Object obj, int column)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
switch (outType) {
|
||||||
|
case t_byte:
|
||||||
|
result.updateByte(column, field.getByte(obj));
|
||||||
|
break;
|
||||||
|
case t_short:
|
||||||
|
result.updateShort(column, field.getShort(obj));
|
||||||
|
break;
|
||||||
|
case t_int:
|
||||||
|
result.updateInt(column, field.getInt(obj));
|
||||||
|
break;
|
||||||
|
case t_long:
|
||||||
|
result.updateLong(column, field.getLong(obj));
|
||||||
|
break;
|
||||||
|
case t_float:
|
||||||
|
result.updateFloat(column, field.getFloat(obj));
|
||||||
|
break;
|
||||||
|
case t_double:
|
||||||
|
result.updateDouble(column, field.getDouble(obj));
|
||||||
|
break;
|
||||||
|
case t_boolean:
|
||||||
|
result.updateBoolean(column, field.getBoolean(obj));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tByte:
|
||||||
|
result.updateByte(column, ((Byte)field.get(obj)).byteValue());
|
||||||
|
break;
|
||||||
|
case tShort:
|
||||||
|
result.updateShort(column,
|
||||||
|
((Short)field.get(obj)).shortValue());
|
||||||
|
break;
|
||||||
|
case tInteger:
|
||||||
|
result.updateInt(column, ((Integer)field.get(obj)).intValue());
|
||||||
|
break;
|
||||||
|
case tLong:
|
||||||
|
result.updateLong(column, ((Long)field.get(obj)).longValue());
|
||||||
|
break;
|
||||||
|
case tFloat:
|
||||||
|
result.updateFloat(column,
|
||||||
|
((Float)field.get(obj)).floatValue());
|
||||||
|
break;
|
||||||
|
case tDouble:
|
||||||
|
result.updateDouble(column,
|
||||||
|
((Double)field.get(obj)).doubleValue());
|
||||||
|
break;
|
||||||
|
case tBoolean:
|
||||||
|
result.updateBoolean(column,
|
||||||
|
((Boolean)field.get(obj)).booleanValue());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tDecimal:
|
||||||
|
result.updateBigDecimal(column, (BigDecimal)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tString:
|
||||||
|
result.updateString(column, (String)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tBytes:
|
||||||
|
result.updateBytes(column, (byte[])field.get(obj));
|
||||||
|
break;
|
||||||
|
case tDate:
|
||||||
|
result.updateDate(column, (java.sql.Date)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tTime:
|
||||||
|
result.updateTime(column, (java.sql.Time)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tTimestamp:
|
||||||
|
result.updateTimestamp(column,
|
||||||
|
(java.sql.Timestamp)field.get(obj));
|
||||||
|
break;
|
||||||
|
case tStream:
|
||||||
|
java.io.InputStream in = (java.io.InputStream)field.get(obj);
|
||||||
|
result.updateBinaryStream(column, in, in.available());
|
||||||
|
break;
|
||||||
|
case tBlob:
|
||||||
|
Blob blob = (Blob)field.get(obj);
|
||||||
|
result.updateBinaryStream(column,
|
||||||
|
blob.getBinaryStream(),
|
||||||
|
(int)blob.length());
|
||||||
|
break;
|
||||||
|
case tClob:
|
||||||
|
Clob clob = (Clob)field.get(obj);
|
||||||
|
result.updateCharacterStream(column,
|
||||||
|
clob.getCharacterStream(),
|
||||||
|
(int)clob.length());
|
||||||
|
break;
|
||||||
|
case tAsString:
|
||||||
|
result.updateString(column, field.get(obj).toString());
|
||||||
|
break;
|
||||||
|
case tClosure:
|
||||||
|
// There is no reason to use piped streams because
|
||||||
|
// we need to pass total number of bytes to JDBC driver
|
||||||
|
java.io.ByteArrayOutputStream out =
|
||||||
|
new java.io.ByteArrayOutputStream();
|
||||||
|
java.io.ObjectOutputStream clu =
|
||||||
|
new java.io.ObjectOutputStream(out);
|
||||||
|
clu.writeObject(field.get(obj));
|
||||||
|
clu.close();
|
||||||
|
result.updateBytes(column, out.toByteArray());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(SQLException ex) {
|
||||||
|
if (outType != tClosure && outType != tAsString) {
|
||||||
|
outType = tAsString;
|
||||||
|
return updateVariable(result, obj, column);
|
||||||
|
} else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} catch(IllegalAccessException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
throw new IllegalAccessError();
|
||||||
|
} catch(java.io.IOException ex) {
|
||||||
|
throw new DataTransferError(ex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean loadVariable (
|
||||||
|
ResultSet result, Object obj, int column)
|
||||||
|
throws SQLException, IllegalAccessException
|
||||||
|
{
|
||||||
|
switch (inType) {
|
||||||
|
case t_byte:
|
||||||
|
field.setByte(obj, result.getByte(column));
|
||||||
|
break;
|
||||||
|
case t_short:
|
||||||
|
field.setShort(obj, result.getShort(column));
|
||||||
|
break;
|
||||||
|
case t_int:
|
||||||
|
field.setInt(obj, result.getInt(column));
|
||||||
|
break;
|
||||||
|
case t_long:
|
||||||
|
field.setLong(obj, result.getLong(column));
|
||||||
|
break;
|
||||||
|
case t_float:
|
||||||
|
field.setFloat(obj, result.getFloat(column));
|
||||||
|
break;
|
||||||
|
case t_double:
|
||||||
|
field.setDouble(obj, result.getDouble(column));
|
||||||
|
break;
|
||||||
|
case t_boolean:
|
||||||
|
field.setBoolean(obj, result.getBoolean(column));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tByte:
|
||||||
|
byte b = result.getByte(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Byte(b));
|
||||||
|
break;
|
||||||
|
case tShort:
|
||||||
|
short s = result.getShort(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Short(s));
|
||||||
|
break;
|
||||||
|
case tInteger:
|
||||||
|
int i = result.getInt(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Integer(i));
|
||||||
|
break;
|
||||||
|
case tLong:
|
||||||
|
long l = result.getLong(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Long(l));
|
||||||
|
break;
|
||||||
|
case tFloat:
|
||||||
|
float f = result.getFloat(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Float(f));
|
||||||
|
field.setFloat(obj, result.getFloat(column));
|
||||||
|
break;
|
||||||
|
case tDouble:
|
||||||
|
double d = result.getDouble(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Double(d));
|
||||||
|
break;
|
||||||
|
case tBoolean:
|
||||||
|
boolean bl = result.getBoolean(column);
|
||||||
|
field.set(obj, result.wasNull() ? null : new Boolean(bl));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tDecimal:
|
||||||
|
field.set(obj, result.getBigDecimal(column));
|
||||||
|
break;
|
||||||
|
case tString:
|
||||||
|
field.set(obj, result.getString(column));
|
||||||
|
break;
|
||||||
|
case tBytes:
|
||||||
|
field.set(obj, result.getBytes(column));
|
||||||
|
break;
|
||||||
|
case tDate:
|
||||||
|
field.set(obj, result.getDate(column));
|
||||||
|
break;
|
||||||
|
case tTime:
|
||||||
|
field.set(obj, result.getTime(column));
|
||||||
|
break;
|
||||||
|
case tTimestamp:
|
||||||
|
field.set(obj, result.getTimestamp(column));
|
||||||
|
break;
|
||||||
|
case tStream:
|
||||||
|
field.set(obj, result.getBinaryStream(column));
|
||||||
|
break;
|
||||||
|
case tBlob:
|
||||||
|
field.set(obj, result.getBlob(column));
|
||||||
|
break;
|
||||||
|
case tClob:
|
||||||
|
field.set(obj, result.getClob(column));
|
||||||
|
break;
|
||||||
|
case tClosure:
|
||||||
|
try {
|
||||||
|
java.io.InputStream input = result.getBinaryStream(column);
|
||||||
|
java.io.ObjectInputStream in =
|
||||||
|
new java.io.ObjectInputStream(input);
|
||||||
|
field.set(obj, in.readObject());
|
||||||
|
in.close();
|
||||||
|
} catch(ClassNotFoundException ex) {
|
||||||
|
throw new DataTransferError(ex);
|
||||||
|
} catch(java.io.IOException ex) {
|
||||||
|
throw new DataTransferError(ex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected int inType; // type tag for field input (see constants below)
|
protected int inType; // type tag for field input (see constants below)
|
||||||
protected int outType; // type tag for field output
|
protected int outType; // type tag for field output
|
||||||
protected int scale; // scale for tDecimal type,
|
protected int scale; // scale for tDecimal type,
|
||||||
protected String name; // full (compound) name of component
|
protected String name; // full (compound) name of component
|
||||||
protected Field field; // field info from java.lang.reflect
|
protected Field field; // field info from java.lang.reflect
|
||||||
|
|
||||||
@@ -52,379 +422,30 @@ class FieldDescriptor {
|
|||||||
protected static final int tCompound = 25;
|
protected static final int tCompound = 25;
|
||||||
|
|
||||||
protected static final int[] sqlTypeMapping = {
|
protected static final int[] sqlTypeMapping = {
|
||||||
Types.INTEGER, // t_byte
|
Types.INTEGER, // t_byte
|
||||||
Types.INTEGER, // t_short
|
Types.INTEGER, // t_short
|
||||||
Types.INTEGER, // t_int
|
Types.INTEGER, // t_int
|
||||||
Types.BIGINT, // t_long
|
Types.BIGINT, // t_long
|
||||||
Types.FLOAT, // t_float
|
Types.FLOAT, // t_float
|
||||||
Types.DOUBLE, // t_double
|
Types.DOUBLE, // t_double
|
||||||
Types.BIT, // t_boolean
|
Types.BIT, // t_boolean
|
||||||
Types.INTEGER, // tByte
|
Types.INTEGER, // tByte
|
||||||
Types.INTEGER, // tShort
|
Types.INTEGER, // tShort
|
||||||
Types.INTEGER, // tInteger
|
Types.INTEGER, // tInteger
|
||||||
Types.BIGINT, // tLong
|
Types.BIGINT, // tLong
|
||||||
Types.FLOAT, // tFloat
|
Types.FLOAT, // tFloat
|
||||||
Types.DOUBLE, // tDouble
|
Types.DOUBLE, // tDouble
|
||||||
Types.BIT, // tBoolean
|
Types.BIT, // tBoolean
|
||||||
Types.NUMERIC, // tDecimal
|
Types.NUMERIC, // tDecimal
|
||||||
Types.VARCHAR, // tString
|
Types.VARCHAR, // tString
|
||||||
Types.VARBINARY,// tBytes
|
Types.VARBINARY,// tBytes
|
||||||
Types.DATE, // tDate
|
Types.DATE, // tDate
|
||||||
Types.TIME, // tTime
|
Types.TIME, // tTime
|
||||||
Types.TIMESTAMP, // tTimestamp
|
Types.TIMESTAMP, // tTimestamp
|
||||||
Types.LONGVARBINARY, // tStream
|
Types.LONGVARBINARY, // tStream
|
||||||
Types.LONGVARBINARY, // tBlob
|
Types.LONGVARBINARY, // tBlob
|
||||||
Types.LONGVARCHAR, // tClob
|
Types.LONGVARCHAR, // tClob
|
||||||
Types.VARCHAR, // tAsString
|
Types.VARCHAR, // tAsString
|
||||||
Types.LONGVARBINARY // tClosure
|
Types.LONGVARBINARY // tClosure
|
||||||
};
|
};
|
||||||
|
|
||||||
protected FieldDescriptor(Field field, String name) {
|
|
||||||
this.name = name;
|
|
||||||
this.field = field;
|
|
||||||
this.scale = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final boolean isAtomic() { return inType < tClosure; }
|
|
||||||
|
|
||||||
protected final boolean isCompound() { return inType >= tCompound; }
|
|
||||||
|
|
||||||
protected final boolean isBuiltin() { return inType <= t_boolean; }
|
|
||||||
|
|
||||||
|
|
||||||
protected final boolean bindVariable(PreparedStatement pstmt,
|
|
||||||
Object obj, int column)
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
switch (outType) {
|
|
||||||
case t_byte:
|
|
||||||
pstmt.setByte(column, field.getByte(obj));
|
|
||||||
break;
|
|
||||||
case t_short:
|
|
||||||
pstmt.setShort(column, field.getShort(obj));
|
|
||||||
break;
|
|
||||||
case t_int:
|
|
||||||
pstmt.setInt(column, field.getInt(obj));
|
|
||||||
break;
|
|
||||||
case t_long:
|
|
||||||
pstmt.setLong(column, field.getLong(obj));
|
|
||||||
break;
|
|
||||||
case t_float:
|
|
||||||
pstmt.setFloat(column, field.getFloat(obj));
|
|
||||||
break;
|
|
||||||
case t_double:
|
|
||||||
pstmt.setDouble(column, field.getDouble(obj));
|
|
||||||
break;
|
|
||||||
case t_boolean:
|
|
||||||
pstmt.setBoolean(column, field.getBoolean(obj));
|
|
||||||
break;
|
|
||||||
case tByte:
|
|
||||||
pstmt.setByte(column, ((Byte)field.get(obj)).byteValue());
|
|
||||||
break;
|
|
||||||
case tShort:
|
|
||||||
pstmt.setShort(column, ((Short)field.get(obj)).shortValue());
|
|
||||||
break;
|
|
||||||
case tInteger:
|
|
||||||
pstmt.setInt(column, ((Integer)field.get(obj)).intValue());
|
|
||||||
break;
|
|
||||||
case tLong:
|
|
||||||
pstmt.setLong(column, ((Long)field.get(obj)).longValue());
|
|
||||||
break;
|
|
||||||
case tFloat:
|
|
||||||
pstmt.setFloat(column, ((Float)field.get(obj)).floatValue());
|
|
||||||
break;
|
|
||||||
case tDouble:
|
|
||||||
pstmt.setDouble(column,((Double)field.get(obj)).doubleValue());
|
|
||||||
break;
|
|
||||||
case tBoolean:
|
|
||||||
pstmt.setBoolean(column,
|
|
||||||
((Boolean)field.get(obj)).booleanValue());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tDecimal:
|
|
||||||
pstmt.setBigDecimal(column, (BigDecimal)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tString:
|
|
||||||
pstmt.setString(column, (String)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tBytes:
|
|
||||||
pstmt.setBytes(column, (byte[])field.get(obj));
|
|
||||||
break;
|
|
||||||
case tDate:
|
|
||||||
pstmt.setDate(column, (java.sql.Date)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tTime:
|
|
||||||
pstmt.setTime(column, (java.sql.Time)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tTimestamp:
|
|
||||||
pstmt.setTimestamp(column, (java.sql.Timestamp)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tStream:
|
|
||||||
java.io.InputStream in = (java.io.InputStream)field.get(obj);
|
|
||||||
pstmt.setBinaryStream(column, in, in.available());
|
|
||||||
break;
|
|
||||||
case tBlob:
|
|
||||||
pstmt.setBlob(column, (Blob)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tClob:
|
|
||||||
pstmt.setClob(column, (Clob)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tAsString:
|
|
||||||
pstmt.setString(column, field.get(obj).toString());
|
|
||||||
break;
|
|
||||||
case tClosure:
|
|
||||||
// There is no reason to use piped streams because
|
|
||||||
// we need to pass total number of bytes to JDBC driver
|
|
||||||
java.io.ByteArrayOutputStream out =
|
|
||||||
new java.io.ByteArrayOutputStream();
|
|
||||||
java.io.ObjectOutputStream clu =
|
|
||||||
new java.io.ObjectOutputStream(out);
|
|
||||||
clu.writeObject(field.get(obj));
|
|
||||||
clu.close();
|
|
||||||
pstmt.setBytes(column, out.toByteArray());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch(SQLException ex) {
|
|
||||||
if (outType != tClosure && outType != tAsString) {
|
|
||||||
outType = tAsString;
|
|
||||||
return bindVariable(pstmt, obj, column);
|
|
||||||
} else {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
} catch(IllegalAccessException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
throw new IllegalAccessError();
|
|
||||||
} catch(java.io.IOException ex) {
|
|
||||||
throw new DataTransferError(ex);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final boolean updateVariable(ResultSet result,
|
|
||||||
Object obj, int column)
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
switch (outType) {
|
|
||||||
case t_byte:
|
|
||||||
result.updateByte(column, field.getByte(obj));
|
|
||||||
break;
|
|
||||||
case t_short:
|
|
||||||
result.updateShort(column, field.getShort(obj));
|
|
||||||
break;
|
|
||||||
case t_int:
|
|
||||||
result.updateInt(column, field.getInt(obj));
|
|
||||||
break;
|
|
||||||
case t_long:
|
|
||||||
result.updateLong(column, field.getLong(obj));
|
|
||||||
break;
|
|
||||||
case t_float:
|
|
||||||
result.updateFloat(column, field.getFloat(obj));
|
|
||||||
break;
|
|
||||||
case t_double:
|
|
||||||
result.updateDouble(column, field.getDouble(obj));
|
|
||||||
break;
|
|
||||||
case t_boolean:
|
|
||||||
result.updateBoolean(column, field.getBoolean(obj));
|
|
||||||
break;
|
|
||||||
case tByte:
|
|
||||||
result.updateByte(column, ((Byte)field.get(obj)).byteValue());
|
|
||||||
break;
|
|
||||||
case tShort:
|
|
||||||
result.updateShort(column,
|
|
||||||
((Short)field.get(obj)).shortValue());
|
|
||||||
break;
|
|
||||||
case tInteger:
|
|
||||||
result.updateInt(column, ((Integer)field.get(obj)).intValue());
|
|
||||||
break;
|
|
||||||
case tLong:
|
|
||||||
result.updateLong(column, ((Long)field.get(obj)).longValue());
|
|
||||||
break;
|
|
||||||
case tFloat:
|
|
||||||
result.updateFloat(column,
|
|
||||||
((Float)field.get(obj)).floatValue());
|
|
||||||
break;
|
|
||||||
case tDouble:
|
|
||||||
result.updateDouble(column,
|
|
||||||
((Double)field.get(obj)).doubleValue());
|
|
||||||
break;
|
|
||||||
case tBoolean:
|
|
||||||
result.updateBoolean(column,
|
|
||||||
((Boolean)field.get(obj)).booleanValue());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tDecimal:
|
|
||||||
result.updateBigDecimal(column, (BigDecimal)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tString:
|
|
||||||
result.updateString(column, (String)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tBytes:
|
|
||||||
result.updateBytes(column, (byte[])field.get(obj));
|
|
||||||
break;
|
|
||||||
case tDate:
|
|
||||||
result.updateDate(column, (java.sql.Date)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tTime:
|
|
||||||
result.updateTime(column, (java.sql.Time)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tTimestamp:
|
|
||||||
result.updateTimestamp(column,
|
|
||||||
(java.sql.Timestamp)field.get(obj));
|
|
||||||
break;
|
|
||||||
case tStream:
|
|
||||||
java.io.InputStream in = (java.io.InputStream)field.get(obj);
|
|
||||||
result.updateBinaryStream(column, in, in.available());
|
|
||||||
break;
|
|
||||||
case tBlob:
|
|
||||||
Blob blob = (Blob)field.get(obj);
|
|
||||||
result.updateBinaryStream(column,
|
|
||||||
blob.getBinaryStream(),
|
|
||||||
(int)blob.length());
|
|
||||||
break;
|
|
||||||
case tClob:
|
|
||||||
Clob clob = (Clob)field.get(obj);
|
|
||||||
result.updateCharacterStream(column,
|
|
||||||
clob.getCharacterStream(),
|
|
||||||
(int)clob.length());
|
|
||||||
break;
|
|
||||||
case tAsString:
|
|
||||||
result.updateString(column, field.get(obj).toString());
|
|
||||||
break;
|
|
||||||
case tClosure:
|
|
||||||
// There is no reason to use piped streams because
|
|
||||||
// we need to pass total number of bytes to JDBC driver
|
|
||||||
java.io.ByteArrayOutputStream out =
|
|
||||||
new java.io.ByteArrayOutputStream();
|
|
||||||
java.io.ObjectOutputStream clu =
|
|
||||||
new java.io.ObjectOutputStream(out);
|
|
||||||
clu.writeObject(field.get(obj));
|
|
||||||
clu.close();
|
|
||||||
result.updateBytes(column, out.toByteArray());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch(SQLException ex) {
|
|
||||||
if (outType != tClosure && outType != tAsString) {
|
|
||||||
outType = tAsString;
|
|
||||||
return updateVariable(result, obj, column);
|
|
||||||
} else {
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
} catch(IllegalAccessException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
throw new IllegalAccessError();
|
|
||||||
} catch(java.io.IOException ex) {
|
|
||||||
throw new DataTransferError(ex);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final boolean loadVariable(ResultSet result,
|
|
||||||
Object obj, int column)
|
|
||||||
throws SQLException, IllegalAccessException
|
|
||||||
{
|
|
||||||
switch (inType) {
|
|
||||||
case t_byte:
|
|
||||||
field.setByte(obj, result.getByte(column));
|
|
||||||
break;
|
|
||||||
case t_short:
|
|
||||||
field.setShort(obj, result.getShort(column));
|
|
||||||
break;
|
|
||||||
case t_int:
|
|
||||||
field.setInt(obj, result.getInt(column));
|
|
||||||
break;
|
|
||||||
case t_long:
|
|
||||||
field.setLong(obj, result.getLong(column));
|
|
||||||
break;
|
|
||||||
case t_float:
|
|
||||||
field.setFloat(obj, result.getFloat(column));
|
|
||||||
break;
|
|
||||||
case t_double:
|
|
||||||
field.setDouble(obj, result.getDouble(column));
|
|
||||||
break;
|
|
||||||
case t_boolean:
|
|
||||||
field.setBoolean(obj, result.getBoolean(column));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tByte:
|
|
||||||
byte b = result.getByte(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Byte(b));
|
|
||||||
break;
|
|
||||||
case tShort:
|
|
||||||
short s = result.getShort(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Short(s));
|
|
||||||
break;
|
|
||||||
case tInteger:
|
|
||||||
int i = result.getInt(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Integer(i));
|
|
||||||
break;
|
|
||||||
case tLong:
|
|
||||||
long l = result.getLong(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Long(l));
|
|
||||||
break;
|
|
||||||
case tFloat:
|
|
||||||
float f = result.getFloat(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Float(f));
|
|
||||||
field.setFloat(obj, result.getFloat(column));
|
|
||||||
break;
|
|
||||||
case tDouble:
|
|
||||||
double d = result.getDouble(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Double(d));
|
|
||||||
break;
|
|
||||||
case tBoolean:
|
|
||||||
boolean bl = result.getBoolean(column);
|
|
||||||
field.set(obj, result.wasNull() ? null : new Boolean(bl));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tDecimal:
|
|
||||||
field.set(obj, result.getBigDecimal(column));
|
|
||||||
break;
|
|
||||||
case tString:
|
|
||||||
field.set(obj, result.getString(column));
|
|
||||||
break;
|
|
||||||
case tBytes:
|
|
||||||
field.set(obj, result.getBytes(column));
|
|
||||||
break;
|
|
||||||
case tDate:
|
|
||||||
field.set(obj, result.getDate(column));
|
|
||||||
break;
|
|
||||||
case tTime:
|
|
||||||
field.set(obj, result.getTime(column));
|
|
||||||
break;
|
|
||||||
case tTimestamp:
|
|
||||||
field.set(obj, result.getTimestamp(column));
|
|
||||||
break;
|
|
||||||
case tStream:
|
|
||||||
field.set(obj, result.getBinaryStream(column));
|
|
||||||
break;
|
|
||||||
case tBlob:
|
|
||||||
field.set(obj, result.getBlob(column));
|
|
||||||
break;
|
|
||||||
case tClob:
|
|
||||||
field.set(obj, result.getClob(column));
|
|
||||||
break;
|
|
||||||
case tClosure:
|
|
||||||
try {
|
|
||||||
java.io.InputStream input = result.getBinaryStream(column);
|
|
||||||
java.io.ObjectInputStream in =
|
|
||||||
new java.io.ObjectInputStream(input);
|
|
||||||
field.set(obj, in.readObject());
|
|
||||||
in.close();
|
|
||||||
} catch(ClassNotFoundException ex) {
|
|
||||||
throw new DataTransferError(ex);
|
|
||||||
} catch(java.io.IOException ex) {
|
|
||||||
throw new DataTransferError(ex);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
//-< NoCurrentObjectError.java >-------------------------------------*--------*
|
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
|
||||||
// (Java Object Relational Adapter) * /\| *
|
|
||||||
// * / \ *
|
|
||||||
// Created: 10-Jun-98 K.A. Knizhnik * / [] \ *
|
|
||||||
// Last update: 16-Jun-98 K.A. Knizhnik * GARRET *
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
// Exception raised when UPDATE/REMOVE operation is applied to Cursor
|
|
||||||
// with no current object
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
|
||||||
|
|
||||||
/** Error raised when update/remove operation is applied to
|
|
||||||
* cursor with no current object (before first call of <TT>next()</TT>
|
|
||||||
* method).
|
|
||||||
*/
|
|
||||||
public class NoCurrentObjectError extends java.lang.Error {
|
|
||||||
NoCurrentObjectError() {
|
|
||||||
super("Cursor doesn't specify current object");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
//-< NoPrimaryKeyError.java >----------------------------------------*--------*
|
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
|
||||||
// (Java Object Relational Adapter) * /\| *
|
|
||||||
// * / \ *
|
|
||||||
// Created: 10-Jun-98 K.A. Knizhnik * / [] \ *
|
|
||||||
// Last update: 16-Jun-98 K.A. Knizhnik * GARRET *
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
// Exception raised when UPDATE/REMOVE operation is appllied to Table with
|
|
||||||
// no primary key
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
|
||||||
|
|
||||||
/** Error raised when unpdate/remove operation is invoked for the table
|
|
||||||
* with no correct primary key defined (key was not specified or
|
|
||||||
* type of the key component is not atomic).
|
|
||||||
*/
|
|
||||||
public class NoPrimaryKeyError extends java.lang.Error {
|
|
||||||
NoPrimaryKeyError(Table table) {
|
|
||||||
super("Table " + table.name + " has no atomic primary key");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
//-< SQLError.java >-------------------------------------------------*--------*
|
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
|
||||||
// (Java Object Relational Adapter) * /\| *
|
|
||||||
// * / \ *
|
|
||||||
// Created: 10-Jun-98 K.A. Knizhnik * / [] \ *
|
|
||||||
// Last update: 16-Jun-98 K.A. Knizhnik * GARRET *
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
// Database error
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
|
||||||
|
|
||||||
/** Database error. Exception SQLException was catched by JORA.
|
|
||||||
*/
|
|
||||||
public class SQLError extends java.lang.RuntimeException {
|
|
||||||
java.sql.SQLException ex;
|
|
||||||
SQLError(java.sql.SQLException x) {
|
|
||||||
super("Database session aborted due to critical error");
|
|
||||||
ex = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
//-< Session.java >--------------------------------------------------*--------*
|
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
|
||||||
// (Java Object Relational Adapter) * /\| *
|
|
||||||
// * / \ *
|
|
||||||
// Created: 10-Jun-98 K.A. Knizhnik * / [] \ *
|
|
||||||
// Last update: 20-Jun-98 K.A. Knizhnik * GARRET *
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
// Database session abstraction
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.sql.*;
|
|
||||||
|
|
||||||
import com.samskivert.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is reposnsible for establishing connection with database
|
|
||||||
* and handling database errors.
|
|
||||||
*/
|
|
||||||
public class Session {
|
|
||||||
public Connection connection;
|
|
||||||
|
|
||||||
/** Session consructor
|
|
||||||
*
|
|
||||||
* @param driverClass class of database driver
|
|
||||||
*/
|
|
||||||
public Session(String driverClass)
|
|
||||||
{
|
|
||||||
driver = driverClass;
|
|
||||||
preparedStmtHash = new Hashtable<String,PreparedStatement>();
|
|
||||||
connectionID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Construct a session with a pre-existing connection instance. In
|
|
||||||
* this case, {@link #open} should not be called on this session.
|
|
||||||
*
|
|
||||||
* @param connection the connection to use.
|
|
||||||
*/
|
|
||||||
public Session(Connection connection)
|
|
||||||
{
|
|
||||||
connectionID = 0;
|
|
||||||
preparedStmtHash = new Hashtable<String,PreparedStatement>();
|
|
||||||
setConnection(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Session consructor for ODBC bridge driver
|
|
||||||
*/
|
|
||||||
public Session() { this("sun.jdbc.odbc.JdbcOdbcDriver"); }
|
|
||||||
|
|
||||||
/** Sets the connection that should be used by this session.
|
|
||||||
*/
|
|
||||||
public void setConnection(Connection conn)
|
|
||||||
{
|
|
||||||
// only up the connection id if this is a new connection
|
|
||||||
if (connection != conn) {
|
|
||||||
// clear out our prepared statement hash because we've got a
|
|
||||||
// new connection
|
|
||||||
for (PreparedStatement pstmt : preparedStmtHash.values()) {
|
|
||||||
try {
|
|
||||||
pstmt.close();
|
|
||||||
} catch (SQLException sqe) {
|
|
||||||
Log.warning("Error closing cached prepared statement " +
|
|
||||||
"[error=" + sqe + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
preparedStmtHash.clear();
|
|
||||||
|
|
||||||
// switch to our new connection
|
|
||||||
connection = conn;
|
|
||||||
connectionID += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Handler of database session errors. Programmer should override
|
|
||||||
* this method in derived class in order to provide application
|
|
||||||
* dependent error handling.
|
|
||||||
*
|
|
||||||
* @param ex exception thrown by some of JDBC methods
|
|
||||||
*/
|
|
||||||
public void handleSQLException(SQLException ex) {
|
|
||||||
// A SQLException was generated. Catch it and
|
|
||||||
// display the error information. Note that there
|
|
||||||
// could be multiple error objects chained
|
|
||||||
// together
|
|
||||||
System.out.println ("*** SQLException caught ***");
|
|
||||||
SQLException x = ex;
|
|
||||||
while (ex != null) {
|
|
||||||
System.out.println("SQLState: " + ex.getSQLState ());
|
|
||||||
System.out.println("Message: " + ex.getMessage ());
|
|
||||||
System.out.println("Vendor: " + ex.getErrorCode ());
|
|
||||||
ex = ex.getNextException();
|
|
||||||
System.out.println ("");
|
|
||||||
}
|
|
||||||
throw new SQLError(x); // terminate program execution
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Open database session.
|
|
||||||
* Attempt to establish a connection to the given database URL.
|
|
||||||
* The DriverManager attempts to select an appropriate driver from
|
|
||||||
* the set of registered JDBC drivers.
|
|
||||||
*
|
|
||||||
* @param dataSource a database url of the form
|
|
||||||
* jdbc:<em>subprotocol</em>:<em>subname</em>
|
|
||||||
* @param user the database user on whose behalf the Connection is
|
|
||||||
* being made
|
|
||||||
* @param password the user's password
|
|
||||||
* @return true if session is succesfully openned, false otherwise
|
|
||||||
*/
|
|
||||||
public boolean open(String dataSource, String user, String password)
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
Class.forName(driver);
|
|
||||||
|
|
||||||
connection =
|
|
||||||
DriverManager.getConnection(dataSource, user, password);
|
|
||||||
connectionID += 1;
|
|
||||||
}
|
|
||||||
// catch(SQLException ex) {
|
|
||||||
// handleSQLException(ex);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
catch(ClassNotFoundException ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Close database session and release all resources holded by session.
|
|
||||||
*/
|
|
||||||
public void close()
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
for (PreparedStatement pstmt : preparedStmtHash.values()) {
|
|
||||||
pstmt.close();
|
|
||||||
}
|
|
||||||
preparedStmtHash.clear();
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
|
|
||||||
* SQL statements that return nothing such as SQL DDL statements
|
|
||||||
* can be executed.
|
|
||||||
*
|
|
||||||
* @param sql a SQL INSERT, UPDATE or DELETE statement or a SQL
|
|
||||||
* statement that returns nothing
|
|
||||||
* @return either the row count for INSERT, UPDATE or DELETE or 0
|
|
||||||
* for SQL statements that return nothing
|
|
||||||
*/
|
|
||||||
public int execute(String sql)
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
// try {
|
|
||||||
Statement stmt = connection.createStatement();
|
|
||||||
int result = stmt.executeUpdate(sql);
|
|
||||||
stmt.close();
|
|
||||||
return result;
|
|
||||||
// } catch(SQLException ex) { handleSQLException(ex); }
|
|
||||||
// return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commit makes all changes made since the previous
|
|
||||||
* commit/rollback permanent and releases any database locks
|
|
||||||
* currently held by the Connection. This method should only be
|
|
||||||
* used when auto commit has been disabled.
|
|
||||||
*/
|
|
||||||
public void commit()
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
// try {
|
|
||||||
connection.commit();
|
|
||||||
// } catch(SQLException ex) { handleSQLException(ex); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rollback drops all changes made since the previous
|
|
||||||
* commit/rollback and releases any database locks currently held
|
|
||||||
* by the Connection. This method should only be used when auto
|
|
||||||
* commit has been disabled.
|
|
||||||
*/
|
|
||||||
public void rollback()
|
|
||||||
throws SQLException
|
|
||||||
{
|
|
||||||
// try {
|
|
||||||
connection.rollback();
|
|
||||||
// } catch(SQLException ex) { handleSQLException(ex); }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String driver; // driver class name
|
|
||||||
protected Hashtable<String,PreparedStatement> preparedStmtHash;
|
|
||||||
protected int connectionID;
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
//-< SessionThread.java >--------------------------------------------*--------*
|
|
||||||
// JORA Version 2.0 (c) 1998 GARRET * ? *
|
|
||||||
// (Java Object Relational Adapter) * /\| *
|
|
||||||
// * / \ *
|
|
||||||
// Created: 18-Jun-99 K.A. Knizhnik * / [] \ *
|
|
||||||
// Last update: 18-Jun-99 K.A. Knizhnik * GARRET *
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
// Thread associated with database session
|
|
||||||
//-------------------------------------------------------------------*--------*
|
|
||||||
|
|
||||||
package com.samskivert.jdbc.jora;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class representing thread associated with users database session.
|
|
||||||
* If there is single database session opened by application, that it is
|
|
||||||
* possible to associate it with Table object statically. Otherwise it is
|
|
||||||
* needed either to explicitly specify session object in each insert,select
|
|
||||||
* or update statement or associate session with thread by means of
|
|
||||||
* SessionThread class.
|
|
||||||
*/
|
|
||||||
public class SessionThread extends Thread {
|
|
||||||
Session session;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object and associate it with
|
|
||||||
* the specified session. This constructor has the same effect as
|
|
||||||
* <code>SessionThread(session, null, null,</code>
|
|
||||||
* <i>gname</i><code>)</code>, where <b><i>gname</i></b> is
|
|
||||||
* a newly generated name. Automatically generated names are of the
|
|
||||||
* form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
|
|
||||||
* <p>
|
|
||||||
* Threads created this way must have overridden their
|
|
||||||
* <code>run()</code> method to actually do anything.
|
|
||||||
*
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session) {
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object and associate it with
|
|
||||||
* the specified session. This constructor has the same effect as
|
|
||||||
* <code>SessionThread(session, target, null,</code>
|
|
||||||
* <i>gname</i><code>)</code>, where <b><i>gname</i></b> is
|
|
||||||
* a newly generated name. Automatically generated names are of the
|
|
||||||
* form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
|
|
||||||
* <p>
|
|
||||||
* Threads created this way must have overridden their
|
|
||||||
* <code>run()</code> method to actually do anything.
|
|
||||||
*
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @param target the object whose <code>run</code> method is called.
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session, Runnable target) {
|
|
||||||
super(target);
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object and associate it with
|
|
||||||
* the specified session. This constructor has the same effect as
|
|
||||||
* <code>SessionThread(session, target, group,</code>
|
|
||||||
* <i>gname</i><code>)</code>, where <b><i>gname</i></b> is
|
|
||||||
* a newly generated name. Automatically generated names are of the
|
|
||||||
* form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer.
|
|
||||||
* <p>
|
|
||||||
* Threads created this way must have overridden their
|
|
||||||
* <code>run()</code> method to actually do anything.
|
|
||||||
*
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @param group the thread group.
|
|
||||||
* @param target the object whose <code>run</code> method is called.
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session, ThreadGroup group, Runnable target) {
|
|
||||||
super(target);
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object. This constructor has
|
|
||||||
* the same effect as <code>SessionThread(session, null, null, name)</code>.
|
|
||||||
*
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @param name the name of the new thread.
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session, String name) {
|
|
||||||
super(name);
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object. This constructor has
|
|
||||||
* the same effect as <code>SessionThread(session, group, null, name)</code>.
|
|
||||||
*
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @param group the thread group.
|
|
||||||
* @param name the name of the new thread.
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session, ThreadGroup group, String name) {
|
|
||||||
super(group, name);
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object. This constructor has
|
|
||||||
* the same effect as <code>SessionThread(session, null, target, name)</code> *
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @param target the object whose <code>run</code> method is called.
|
|
||||||
* @param name the name of the new thread.
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session, Runnable target, String name) {
|
|
||||||
super(target, name);
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a new <code>SessionThread</code> object so that it has
|
|
||||||
* <code>target</code> as its run object, has the specified
|
|
||||||
* <code>name</code> as its name, and belongs to the thread group
|
|
||||||
* referred to by <code>group</code>.
|
|
||||||
* <p>
|
|
||||||
* @param session user database session associated with this thread
|
|
||||||
* @param group the thread group.
|
|
||||||
* @param target the object whose <code>run</code> method is called.
|
|
||||||
* @param name the name of the new thread.
|
|
||||||
* @see java.lang.Thread#Thread(java.lang.ThreadGroup,
|
|
||||||
* java.lang.Runnable, java.lang.String)
|
|
||||||
*/
|
|
||||||
public SessionThread(Session session, ThreadGroup group, Runnable target,
|
|
||||||
String name)
|
|
||||||
{
|
|
||||||
super(group, target, name);
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,6 @@ import com.samskivert.jdbc.JORARepository;
|
|||||||
import com.samskivert.jdbc.StaticConnectionProvider;
|
import com.samskivert.jdbc.StaticConnectionProvider;
|
||||||
import com.samskivert.jdbc.jora.Cursor;
|
import com.samskivert.jdbc.jora.Cursor;
|
||||||
import com.samskivert.jdbc.jora.FieldMask;
|
import com.samskivert.jdbc.jora.FieldMask;
|
||||||
import com.samskivert.jdbc.jora.Session;
|
|
||||||
import com.samskivert.jdbc.jora.Table;
|
import com.samskivert.jdbc.jora.Table;
|
||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.HashIntMap;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
@@ -134,30 +133,15 @@ public class UserRepository extends JORARepository
|
|||||||
* @return the user associated with the specified session or null of
|
* @return the user associated with the specified session or null of
|
||||||
* no session exists with the supplied identifier.
|
* no session exists with the supplied identifier.
|
||||||
*/
|
*/
|
||||||
public User loadUserBySession (final String sessionKey)
|
public User loadUserBySession (String sessionKey)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<User>() {
|
User user = load(_utable, "where authcode = '" + sessionKey + "' AND " +
|
||||||
public User invoke (Connection conn, DatabaseLiaison liaison)
|
"sessions.userId = users.userId");
|
||||||
throws PersistenceException, SQLException
|
if (user != null) {
|
||||||
{
|
user.setDirtyMask(_utable.getFieldMask());
|
||||||
String query = "where authcode = '" + sessionKey +
|
}
|
||||||
"' AND sessions.userId = users.userId";
|
return user;
|
||||||
// look up the user
|
|
||||||
Cursor<User> ec = _utable.select("sessions", query);
|
|
||||||
|
|
||||||
// fetch the user from the cursor
|
|
||||||
User user = ec.next();
|
|
||||||
if (user != null) {
|
|
||||||
// call next() again to cause the cursor to close itself
|
|
||||||
ec.next();
|
|
||||||
// configure the user record with its field mask
|
|
||||||
user.setDirtyMask(_utable.getFieldMask());
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -168,29 +152,15 @@ public class UserRepository extends JORARepository
|
|||||||
public HashIntMap<User> loadUsersFromId (int[] userIds)
|
public HashIntMap<User> loadUsersFromId (int[] userIds)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
// make sure we actually have something to do
|
HashIntMap<User> data = new HashIntMap<User>();
|
||||||
if (userIds.length == 0) {
|
if (userIds.length > 0) {
|
||||||
return new HashIntMap<User>();
|
String query = "where userid in (" + genIdString(userIds) + ")";
|
||||||
}
|
for (User user : loadAll(_utable, query)) {
|
||||||
|
user.setDirtyMask(_utable.getFieldMask());
|
||||||
final String ids = genIdString(userIds);
|
data.put(user.userId, user);
|
||||||
|
|
||||||
return execute(new Operation<HashIntMap<User>>() {
|
|
||||||
public HashIntMap<User> invoke (Connection conn,
|
|
||||||
DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
Cursor<User> ec = _utable.select(
|
|
||||||
"where userid in (" + ids + ")");
|
|
||||||
User user;
|
|
||||||
HashIntMap<User> data = new HashIntMap<User>();
|
|
||||||
while ((user = ec.next()) != null) {
|
|
||||||
user.setDirtyMask(_utable.getFieldMask());
|
|
||||||
data.put(user.userId, user);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,16 +174,7 @@ public class UserRepository extends JORARepository
|
|||||||
public ArrayList<User> lookupUsersByEmail (String email)
|
public ArrayList<User> lookupUsersByEmail (String email)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
final String where = "where email = " +
|
return loadAll(_utable, "where email = " + JDBCUtil.escape(email));
|
||||||
JDBCUtil.escape(email);
|
|
||||||
return execute(new Operation<ArrayList<User>>() {
|
|
||||||
public ArrayList<User> invoke (Connection conn,
|
|
||||||
DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
return _utable.select(where).toArrayList();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,20 +188,12 @@ public class UserRepository extends JORARepository
|
|||||||
public ArrayList<User> lookupUsersWhere (final String where)
|
public ArrayList<User> lookupUsersWhere (final String where)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<ArrayList<User>>() {
|
ArrayList<User> users = loadAll(_utable, where);
|
||||||
public ArrayList<User> invoke (
|
for (User user : users) {
|
||||||
Connection conn, DatabaseLiaison liaison)
|
// configure the user record with its field mask
|
||||||
throws PersistenceException, SQLException
|
user.setDirtyMask(_utable.getFieldMask());
|
||||||
{
|
}
|
||||||
ArrayList<User> users =
|
return users;
|
||||||
_utable.select("where " + where).toArrayList();
|
|
||||||
for (User user : users) {
|
|
||||||
// configure the user record with its field mask
|
|
||||||
user.setDirtyMask(_utable.getFieldMask());
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,17 +212,7 @@ public class UserRepository extends JORARepository
|
|||||||
// nothing doing!
|
// nothing doing!
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
update(_utable, user, user.getDirtyMask());
|
||||||
executeUpdate(new Operation<Object>() {
|
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
_utable.update(user, user.getDirtyMask());
|
|
||||||
// nothing to return
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +260,7 @@ public class UserRepository extends JORARepository
|
|||||||
try {
|
try {
|
||||||
user.username = StringUtil.truncate(
|
user.username = StringUtil.truncate(
|
||||||
ii + "=" + oldName, 24);
|
ii + "=" + oldName, 24);
|
||||||
_utable.update(user, mask);
|
_utable.update(conn, user, mask);
|
||||||
return null; // nothing to return
|
return null; // nothing to return
|
||||||
} catch (SQLException se) {
|
} catch (SQLException se) {
|
||||||
if (!liaison.isDuplicateRowException(se)) {
|
if (!liaison.isDuplicateRowException(se)) {
|
||||||
@@ -350,18 +293,8 @@ public class UserRepository extends JORARepository
|
|||||||
final Date expires = new Date(cal.getTime().getTime());
|
final Date expires = new Date(cal.getTime().getTime());
|
||||||
|
|
||||||
// insert the session into the database
|
// insert the session into the database
|
||||||
executeUpdate(new Operation<Object>() {
|
update("insert into sessions (authcode, userId, expires) values('" +
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
authcode + "', " + user.userId + ", '" + expires + "')");
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
_session.execute("insert into sessions " +
|
|
||||||
"(authcode, userId, expires) values('" +
|
|
||||||
authcode + "', " + user.userId + ", '" +
|
|
||||||
expires + "')");
|
|
||||||
// nothing to return
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// and let the user know what the session identifier is
|
// and let the user know what the session identifier is
|
||||||
return authcode;
|
return authcode;
|
||||||
@@ -373,16 +306,7 @@ public class UserRepository extends JORARepository
|
|||||||
public void pruneSessions ()
|
public void pruneSessions ()
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
executeUpdate(new Operation<Object>() {
|
update("delete from sessions where expires <= CURRENT_DATE()");
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
|
||||||
throws PersistenceException, SQLException
|
|
||||||
{
|
|
||||||
_session.execute("delete from sessions where " +
|
|
||||||
"expires <= CURRENT_DATE()");
|
|
||||||
// nothing to return
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -420,7 +344,7 @@ public class UserRepository extends JORARepository
|
|||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws PersistenceException, SQLException
|
throws PersistenceException, SQLException
|
||||||
{
|
{
|
||||||
Statement stmt = _session.connection.createStatement();
|
Statement stmt = conn.createStatement();
|
||||||
try {
|
try {
|
||||||
String query = "select realname from users";
|
String query = "select realname from users";
|
||||||
ResultSet rs = stmt.executeQuery(query);
|
ResultSet rs = stmt.executeQuery(query);
|
||||||
@@ -469,7 +393,7 @@ public class UserRepository extends JORARepository
|
|||||||
throws PersistenceException, SQLException
|
throws PersistenceException, SQLException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
_utable.insert(user);
|
_utable.insert(conn, user);
|
||||||
// update the userid now that it's known
|
// update the userid now that it's known
|
||||||
user.userId = liaison.lastInsertedId(conn);
|
user.userId = liaison.lastInsertedId(conn);
|
||||||
// nothing to return
|
// nothing to return
|
||||||
@@ -489,31 +413,17 @@ public class UserRepository extends JORARepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads up a user record that matches the specified where clause.
|
* Loads up a user record that matches the specified where clause. Returns
|
||||||
* Returns null if no record matches.
|
* null if no record matches.
|
||||||
*/
|
*/
|
||||||
protected User loadUserWhere (final String whereClause)
|
protected User loadUserWhere (String where)
|
||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
return execute(new Operation<User>() {
|
User user = load(_utable, where);
|
||||||
public User invoke (Connection conn, DatabaseLiaison liaison)
|
if (user != null) {
|
||||||
throws PersistenceException, SQLException
|
user.setDirtyMask(_utable.getFieldMask());
|
||||||
{
|
}
|
||||||
// look up the user
|
return user;
|
||||||
Cursor<User> ec = _utable.select(whereClause);
|
|
||||||
|
|
||||||
// fetch the user from the cursor
|
|
||||||
User user = ec.next();
|
|
||||||
if (user != null) {
|
|
||||||
// call next() again to cause the cursor to close itself
|
|
||||||
ec.next();
|
|
||||||
// configure the user record with its field mask
|
|
||||||
user.setDirtyMask(_utable.getFieldMask());
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String[] loadNames (int[] userIds, final String column)
|
protected String[] loadNames (int[] userIds, final String column)
|
||||||
@@ -524,16 +434,14 @@ public class UserRepository extends JORARepository
|
|||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
final String ids = genIdString(userIds);
|
|
||||||
|
|
||||||
final HashIntMap<String> map = new HashIntMap<String>();
|
|
||||||
|
|
||||||
// do the query
|
// do the query
|
||||||
|
final String ids = genIdString(userIds);
|
||||||
|
final HashIntMap<String> map = new HashIntMap<String>();
|
||||||
execute(new Operation<Object>() {
|
execute(new Operation<Object>() {
|
||||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
||||||
throws PersistenceException, SQLException
|
throws PersistenceException, SQLException
|
||||||
{
|
{
|
||||||
Statement stmt = _session.connection.createStatement();
|
Statement stmt = conn.createStatement();
|
||||||
try {
|
try {
|
||||||
String query = "select userId, " + column +
|
String query = "select userId, " + column +
|
||||||
" from users " +
|
" from users " +
|
||||||
@@ -559,14 +467,13 @@ public class UserRepository extends JORARepository
|
|||||||
for (int i = 0; i < userIds.length; i++) {
|
for (int i = 0; i < userIds.length; i++) {
|
||||||
result[i] = map.get(userIds[i]);
|
result[i] = map.get(userIds[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take the passed in int array and create the a string suitable for
|
* Take the passed in int array and create the a string suitable for using
|
||||||
* using in a SQL set query (I.e., "select foo, from bar where userid
|
* in a SQL set query (I.e., "select foo, from bar where userid in
|
||||||
* in (genIdString(userIds))"; )
|
* (genIdString(userIds))"; )
|
||||||
*/
|
*/
|
||||||
protected String genIdString (int[] userIds)
|
protected String genIdString (int[] userIds)
|
||||||
{
|
{
|
||||||
@@ -583,10 +490,10 @@ public class UserRepository extends JORARepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void createTables (Session session)
|
protected void createTables ()
|
||||||
{
|
{
|
||||||
// create our table object
|
// create our table object
|
||||||
_utable = new Table<User>(User.class, "users", session, "userId");
|
_utable = new Table<User>(User.class, "users", "userId");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A wrapper that provides access to the userstable. */
|
/** A wrapper that provides access to the userstable. */
|
||||||
|
|||||||
Reference in New Issue
Block a user