mirror of https://github.com/apache/openjpa.git
OPENJPA-477 Making StoreManager more flexible and extensible
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@614763 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8d18daabd7
commit
a8f6d3c116
|
@ -181,7 +181,7 @@ public abstract class AbstractUpdateManager
|
|||
/**
|
||||
* Recursive method to insert the given instance, base class first.
|
||||
*/
|
||||
private void insert(OpenJPAStateManager sm, ClassMapping mapping,
|
||||
protected void insert(OpenJPAStateManager sm, ClassMapping mapping,
|
||||
RowManager rowMgr, JDBCStore store, Collection customs)
|
||||
throws SQLException {
|
||||
Boolean custom = mapping.isCustomInsert(sm, store);
|
||||
|
@ -228,7 +228,7 @@ public abstract class AbstractUpdateManager
|
|||
/**
|
||||
* Recursive method to delete the given instance, base class last.
|
||||
*/
|
||||
private void delete(OpenJPAStateManager sm, ClassMapping mapping,
|
||||
protected void delete(OpenJPAStateManager sm, ClassMapping mapping,
|
||||
RowManager rowMgr, JDBCStore store, Collection customs)
|
||||
throws SQLException {
|
||||
Boolean custom = mapping.isCustomDelete(sm, store);
|
||||
|
@ -271,7 +271,7 @@ public abstract class AbstractUpdateManager
|
|||
/**
|
||||
* Recursive method to update the given instance.
|
||||
*/
|
||||
private void update(OpenJPAStateManager sm, BitSet dirty,
|
||||
protected void update(OpenJPAStateManager sm, BitSet dirty,
|
||||
ClassMapping mapping, RowManager rowMgr, JDBCStore store,
|
||||
Collection customs) throws SQLException {
|
||||
Boolean custom = mapping.isCustomUpdate(sm, store);
|
||||
|
@ -300,7 +300,7 @@ public abstract class AbstractUpdateManager
|
|||
/**
|
||||
* Update version and discriminator indicators.
|
||||
*/
|
||||
private void updateIndicators(OpenJPAStateManager sm, ClassMapping mapping,
|
||||
protected void updateIndicators(OpenJPAStateManager sm, ClassMapping mapping,
|
||||
RowManager rowMgr, JDBCStore store, Collection customs,
|
||||
boolean versionUpdateOnly) throws SQLException {
|
||||
while (mapping.getJoinablePCSuperclassMapping() != null)
|
||||
|
|
|
@ -140,7 +140,7 @@ public class JDBCBrokerFactory
|
|||
/**
|
||||
* Synchronize the mappings of the classes listed in the configuration.
|
||||
*/
|
||||
private void synchronizeMappings(ClassLoader loader) {
|
||||
protected void synchronizeMappings(ClassLoader loader) {
|
||||
JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
|
||||
String action = conf.getSynchronizeMappings();
|
||||
if (StringUtils.isEmpty(action))
|
||||
|
|
|
@ -272,7 +272,7 @@ public class JDBCStoreManager
|
|||
/**
|
||||
* Initialize a newly-loaded instance.
|
||||
*/
|
||||
private boolean initializeState(OpenJPAStateManager sm, PCState state,
|
||||
protected boolean initializeState(OpenJPAStateManager sm, PCState state,
|
||||
JDBCFetchConfiguration fetch, ConnectionInfo info)
|
||||
throws ClassNotFoundException, SQLException {
|
||||
Object oid = sm.getObjectId();
|
||||
|
@ -294,7 +294,7 @@ public class JDBCStoreManager
|
|||
Select.SUBS_EXACT);
|
||||
if (res == null && !selectPrimaryKey(sm, mapping, fetch))
|
||||
return false;
|
||||
if (res != null && !res.next())
|
||||
if (isEmptyResult(res))
|
||||
return false;
|
||||
} else {
|
||||
ClassMapping[] mappings = mapping.
|
||||
|
@ -311,16 +311,14 @@ public class JDBCStoreManager
|
|||
} else
|
||||
res = getInitializeStateUnionResult(sm, mapping, mappings,
|
||||
fetch);
|
||||
if (res != null && !res.next())
|
||||
if (isEmptyResult(res))
|
||||
return false;
|
||||
}
|
||||
|
||||
// figure out what type of object this is; the state manager
|
||||
// only guarantees to provide a base class
|
||||
Class type;
|
||||
if (res == null)
|
||||
type = mapping.getDescribedType();
|
||||
else {
|
||||
if ((type = getType(res, mapping)) == null) {
|
||||
if (res.getBaseMapping() != null)
|
||||
mapping = res.getBaseMapping();
|
||||
res.startDataRequest(mapping.getDiscriminator());
|
||||
|
@ -342,7 +340,7 @@ public class JDBCStoreManager
|
|||
// re-get the mapping in case the instance was a subclass
|
||||
mapping = (ClassMapping) sm.getMetaData();
|
||||
load(mapping, sm, fetch, res);
|
||||
mapping.getVersion().afterLoad(sm, this);
|
||||
getVersion(mapping, sm, res);
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
|
@ -350,6 +348,35 @@ public class JDBCStoreManager
|
|||
res.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of getting version from the result set.
|
||||
*/
|
||||
protected void getVersion(ClassMapping mapping, OpenJPAStateManager sm,
|
||||
Result res) throws SQLException {
|
||||
mapping.getVersion().afterLoad(sm, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of checking whether the result set is empty or not.
|
||||
*/
|
||||
protected boolean isEmptyResult(Result res) throws SQLException {
|
||||
if (res != null && !res.next())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of getting type from the result set.
|
||||
*/
|
||||
protected Class getType(Result res, ClassMapping mapping){
|
||||
if (res == null)
|
||||
return mapping.getDescribedType();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the mapping to custom load data. Return null if the mapping
|
||||
|
@ -427,7 +454,7 @@ public class JDBCStoreManager
|
|||
sel.wherePrimaryKey(sm.getObjectId(), base, this);
|
||||
Result exists = sel.execute(this, fetch);
|
||||
try {
|
||||
if (!exists.next())
|
||||
if (isEmptyResult(exists))
|
||||
return false;
|
||||
|
||||
// record locked?
|
||||
|
@ -478,7 +505,7 @@ public class JDBCStoreManager
|
|||
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
||||
res = sel.execute(this, jfetch, lockLevel);
|
||||
try {
|
||||
if (!res.next())
|
||||
if (isEmptyResult(res))
|
||||
return false;
|
||||
load(mapping, sm, jfetch, res);
|
||||
} finally {
|
||||
|
|
|
@ -499,11 +499,11 @@ public class JDBCStoreQuery
|
|||
for (int i = 0; i < sql.length; i++) {
|
||||
stmnt = null;
|
||||
try {
|
||||
stmnt = sql[i].prepareStatement(conn);
|
||||
count += stmnt.executeUpdate();
|
||||
stmnt = prepareStatement(conn, sql[i]);
|
||||
count += executeUpdate(conn, stmnt, sql[i], isUpdate);
|
||||
} catch (SQLException se) {
|
||||
throw SQLExceptions.getStore(se, sql[i].getSQL(),
|
||||
_store.getDBDictionary());
|
||||
_store.getDBDictionary());
|
||||
} finally {
|
||||
if (stmnt != null)
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
|
@ -649,4 +649,22 @@ public class JDBCStoreQuery
|
|||
sql[i] = ((Select) sels.get(i)).toSelect(false, fetch).getSQL(true);
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing update.
|
||||
*/
|
||||
protected int executeUpdate(Connection conn, PreparedStatement stmnt,
|
||||
SQLBuffer sqlBuf, boolean isUpdate) throws SQLException {
|
||||
return stmnt.executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn, SQLBuffer sql)
|
||||
throws SQLException {
|
||||
return sql.prepareStatement(conn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,18 +132,10 @@ public class PessimisticLockManager
|
|||
PreparedStatement stmnt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
stmnt = sql.prepareStatement(conn);
|
||||
if (timeout >= 0 && dict.supportsQueryTimeout) {
|
||||
if (timeout < 1000) {
|
||||
timeout = 1000;
|
||||
if (log.isWarnEnabled())
|
||||
log.warn(_loc.get("millis-query-timeout"));
|
||||
}
|
||||
stmnt.setQueryTimeout(timeout / 1000);
|
||||
}
|
||||
rs = stmnt.executeQuery();
|
||||
if (!rs.next())
|
||||
throw new LockException(sm.getManagedInstance());
|
||||
stmnt = prepareStatement(conn, sql);
|
||||
setTimeout(stmnt, timeout);
|
||||
rs = executeQuery(conn, stmnt, sql);
|
||||
checkLock(rs, sm);
|
||||
} catch (SQLException se) {
|
||||
throw SQLExceptions.getStore(se, dict);
|
||||
} finally {
|
||||
|
@ -168,4 +160,54 @@ public class PessimisticLockManager
|
|||
log.info(_loc.get("start-trans-for-lock"));
|
||||
}
|
||||
}
|
||||
|
||||
public JDBCStore getStore() {
|
||||
return _store;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn, SQLBuffer sql)
|
||||
throws SQLException {
|
||||
return sql.prepareStatement(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of setting query timeout.
|
||||
*/
|
||||
protected void setTimeout(PreparedStatement stmnt, int timeout)
|
||||
throws SQLException {
|
||||
DBDictionary dict = _store.getDBDictionary();
|
||||
if (timeout >= 0 && dict.supportsQueryTimeout) {
|
||||
if (timeout < 1000) {
|
||||
timeout = 1000;
|
||||
if (log.isWarnEnabled())
|
||||
log.warn(_loc.get("millis-query-timeout"));
|
||||
}
|
||||
stmnt.setQueryTimeout(timeout / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing query.
|
||||
*/
|
||||
protected ResultSet executeQuery(Connection conn, PreparedStatement stmnt,
|
||||
SQLBuffer sql) throws SQLException {
|
||||
return stmnt.executeQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of checking lock from the result set.
|
||||
*/
|
||||
protected void checkLock(ResultSet rs, OpenJPAStateManager sm)
|
||||
throws SQLException {
|
||||
if (!rs.next())
|
||||
throw new LockException(sm.getManagedInstance());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.openjpa.lib.util.Localizer;
|
|||
import org.apache.openjpa.util.ApplicationIds;
|
||||
import org.apache.openjpa.util.OpenJPAException;
|
||||
import org.apache.openjpa.util.OptimisticException;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
|
||||
/**
|
||||
* Basic prepared statement manager implementation.
|
||||
|
@ -89,12 +88,13 @@ public class PreparedStatementManagerImpl
|
|||
|
||||
// prepare statement
|
||||
String sql = row.getSQL(_dict);
|
||||
PreparedStatement stmnt = _conn.prepareStatement(sql);
|
||||
|
||||
PreparedStatement stmnt = prepareStatement(sql);
|
||||
|
||||
// setup parameters and execute statement
|
||||
row.flush(stmnt, _dict, _store);
|
||||
if (stmnt != null)
|
||||
row.flush(stmnt, _dict, _store);
|
||||
try {
|
||||
int count = stmnt.executeUpdate();
|
||||
int count = executeUpdate(stmnt, sql, row);
|
||||
if (count != 1) {
|
||||
Object failed = row.getFailedObject();
|
||||
if (failed != null)
|
||||
|
@ -107,7 +107,8 @@ public class PreparedStatementManagerImpl
|
|||
} catch (SQLException se) {
|
||||
throw SQLExceptions.getStore(se, row.getFailedObject(), _dict);
|
||||
} finally {
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
if (stmnt != null)
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
}
|
||||
|
||||
// set auto assign values
|
||||
|
@ -128,4 +129,22 @@ public class PreparedStatementManagerImpl
|
|||
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing update.
|
||||
*/
|
||||
protected int executeUpdate(PreparedStatement stmnt, String sql,
|
||||
RowImpl row) throws SQLException {
|
||||
return stmnt.executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(String sql)
|
||||
throws SQLException {
|
||||
return _conn.prepareStatement(sql);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.io.StreamTokenizer;
|
|||
import java.io.StringReader;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -157,7 +158,7 @@ public class SQLStoreQuery
|
|||
/**
|
||||
* Executes the filter as a SQL query.
|
||||
*/
|
||||
private static class SQLExecutor
|
||||
protected static class SQLExecutor
|
||||
extends AbstractExecutor {
|
||||
|
||||
private final ClassMetaData _meta;
|
||||
|
@ -224,20 +225,14 @@ public class SQLStoreQuery
|
|||
|
||||
PreparedStatement stmnt = null;
|
||||
try {
|
||||
stmnt = buf.prepareCall(conn);
|
||||
stmnt = prepareCall(conn, buf);
|
||||
|
||||
int index = 0;
|
||||
for (Iterator i = paramList.iterator(); i.hasNext();)
|
||||
for (Iterator i = paramList.iterator(); i.hasNext() &&
|
||||
stmnt != null;)
|
||||
dict.setUnknown(stmnt, ++index, i.next(), null);
|
||||
|
||||
int count = 0;
|
||||
if (_call && stmnt.execute() == false) {
|
||||
count = stmnt.getUpdateCount();
|
||||
}
|
||||
else {
|
||||
// native insert, update, delete
|
||||
count = stmnt.executeUpdate();
|
||||
}
|
||||
int count = executeUpdate(store, conn, stmnt, buf);
|
||||
return Numbers.valueOf(count);
|
||||
} catch (SQLException se) {
|
||||
if (stmnt != null)
|
||||
|
@ -276,20 +271,23 @@ public class SQLStoreQuery
|
|||
try {
|
||||
// use the right method depending on sel vs. proc, lrs setting
|
||||
if (_select && !range.lrs)
|
||||
stmnt = buf.prepareStatement(conn);
|
||||
stmnt = prepareStatement(conn, buf);
|
||||
else if (_select)
|
||||
stmnt = buf.prepareStatement(conn, fetch, -1, -1);
|
||||
stmnt = prepareStatement(conn, buf, fetch, -1, -1);
|
||||
else if (!range.lrs)
|
||||
stmnt = buf.prepareCall(conn);
|
||||
stmnt = prepareCall(conn, buf);
|
||||
else
|
||||
stmnt = buf.prepareCall(conn, fetch, -1, -1);
|
||||
stmnt = prepareCall(conn, buf, fetch, -1, -1);
|
||||
|
||||
int index = 0;
|
||||
for (Iterator i = paramList.iterator(); i.hasNext();)
|
||||
for (Iterator i = paramList.iterator(); i.hasNext() &&
|
||||
stmnt != null;)
|
||||
dict.setUnknown(stmnt, ++index, i.next(), null);
|
||||
|
||||
ResultSetResult res = new ResultSetResult(conn, stmnt,
|
||||
stmnt.executeQuery(), store);
|
||||
ResultSet rs = executeQuery(store, conn, stmnt, buf, paramList);
|
||||
ResultSetResult res = stmnt != null ?
|
||||
new ResultSetResult(conn, stmnt, rs, store) :
|
||||
new ResultSetResult(conn, rs, dict);
|
||||
if (_resultMapping != null)
|
||||
rop = new MappedQueryResultObjectProvider(_resultMapping,
|
||||
store, fetch, res);
|
||||
|
@ -319,5 +317,71 @@ public class SQLStoreQuery
|
|||
public boolean isPacking(StoreQuery q) {
|
||||
return q.getContext().getCandidateType() == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing call statement.
|
||||
*/
|
||||
protected PreparedStatement prepareCall(Connection conn, SQLBuffer buf)
|
||||
throws SQLException {
|
||||
return buf.prepareCall(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing update.
|
||||
*/
|
||||
protected int executeUpdate(JDBCStore store, Connection conn,
|
||||
PreparedStatement stmnt, SQLBuffer buf)
|
||||
throws SQLException {
|
||||
int count = 0;
|
||||
if (_call && stmnt.execute() == false) {
|
||||
count = stmnt.getUpdateCount();
|
||||
}
|
||||
else {
|
||||
// native insert, update, delete
|
||||
count = stmnt.executeUpdate();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing call statement.
|
||||
*/
|
||||
protected PreparedStatement prepareCall(Connection conn, SQLBuffer buf,
|
||||
JDBCFetchConfiguration fetch, int rsType, int rsConcur)
|
||||
throws SQLException {
|
||||
return buf.prepareCall(conn, fetch, rsType, rsConcur);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn,
|
||||
SQLBuffer buf) throws SQLException {
|
||||
return buf.prepareStatement(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn,
|
||||
SQLBuffer buf, JDBCFetchConfiguration fetch, int rsType,
|
||||
int rsConcur) throws SQLException {
|
||||
return buf.prepareStatement(conn, fetch, rsType, rsConcur);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing query.
|
||||
*/
|
||||
protected ResultSet executeQuery(JDBCStore store, Connection conn,
|
||||
PreparedStatement stmnt, SQLBuffer buf, List paramList)
|
||||
throws SQLException {
|
||||
return stmnt.executeQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
|||
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
|
||||
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||
import org.apache.openjpa.jdbc.schema.Column;
|
||||
import org.apache.openjpa.jdbc.schema.Index;
|
||||
import org.apache.openjpa.jdbc.schema.PrimaryKey;
|
||||
import org.apache.openjpa.jdbc.schema.Schema;
|
||||
import org.apache.openjpa.jdbc.schema.SchemaGroup;
|
||||
|
@ -38,6 +37,7 @@ import org.apache.openjpa.jdbc.schema.SchemaTool;
|
|||
import org.apache.openjpa.jdbc.schema.Schemas;
|
||||
import org.apache.openjpa.jdbc.schema.Table;
|
||||
import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||
import org.apache.openjpa.jdbc.sql.RowImpl;
|
||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||
import org.apache.openjpa.jdbc.sql.SQLExceptions;
|
||||
import org.apache.openjpa.lib.conf.Configurable;
|
||||
|
@ -431,8 +431,8 @@ public class TableJDBCSeq
|
|||
|
||||
PreparedStatement stmnt = null;
|
||||
try {
|
||||
stmnt = insert.prepareStatement(conn);
|
||||
stmnt.executeUpdate();
|
||||
stmnt = prepareStatement(conn, insert);
|
||||
executeUpdate(_conf, conn, stmnt, insert, RowImpl.ACTION_INSERT);
|
||||
} finally {
|
||||
if (stmnt != null)
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
|
@ -464,17 +464,16 @@ public class TableJDBCSeq
|
|||
null, false, dict.supportsSelectForUpdate, 0, Long.MAX_VALUE,
|
||||
false, true);
|
||||
|
||||
PreparedStatement stmnt = select.prepareStatement(conn);
|
||||
PreparedStatement stmnt = prepareStatement(conn, select);
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
rs = stmnt.executeQuery();
|
||||
if (!rs.next())
|
||||
return -1;
|
||||
return dict.getLong(rs, 1);
|
||||
rs = executeQuery(_conf, conn, stmnt, select);
|
||||
return getSequence(rs, dict);
|
||||
} finally {
|
||||
if (rs != null)
|
||||
try { rs.close(); } catch (SQLException se) {}
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
if (stmnt != null)
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,8 +521,8 @@ public class TableJDBCSeq
|
|||
append(_seqColumn).append(" = ").
|
||||
appendValue(Numbers.valueOf(cur), _seqColumn);
|
||||
|
||||
stmnt = upd.prepareStatement(conn);
|
||||
updates = stmnt.executeUpdate();
|
||||
stmnt = prepareStatement(conn, upd);
|
||||
updates = executeUpdate(_conf, conn, stmnt, upd, RowImpl.ACTION_UPDATE);
|
||||
} finally {
|
||||
if (rs != null)
|
||||
try { rs.close(); } catch (SQLException se) {}
|
||||
|
@ -704,4 +703,41 @@ public class TableJDBCSeq
|
|||
public long seq = 1L;
|
||||
public long max = 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn, SQLBuffer buf)
|
||||
throws SQLException {
|
||||
return buf.prepareStatement(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing update.
|
||||
*/
|
||||
protected int executeUpdate(JDBCConfiguration conf, Connection conn,
|
||||
PreparedStatement stmnt, SQLBuffer buf, int opcode) throws SQLException {
|
||||
return stmnt.executeUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing query.
|
||||
*/
|
||||
protected ResultSet executeQuery(JDBCConfiguration conf, Connection conn,
|
||||
PreparedStatement stmnt, SQLBuffer buf) throws SQLException {
|
||||
return stmnt.executeQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of getting sequence from the result set.
|
||||
*/
|
||||
protected long getSequence(ResultSet rs, DBDictionary dict) throws SQLException {
|
||||
if (rs == null || !rs.next())
|
||||
return -1;
|
||||
return dict.getLong(rs, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ import org.apache.openjpa.util.UserException;
|
|||
*
|
||||
* @author Abe White
|
||||
*/
|
||||
class PCPath
|
||||
public class PCPath
|
||||
extends AbstractVal
|
||||
implements JDBCPath {
|
||||
|
||||
|
@ -549,7 +549,7 @@ class PCPath
|
|||
/**
|
||||
* Expression state.
|
||||
*/
|
||||
private static class PathExpState
|
||||
public static class PathExpState
|
||||
extends ExpState {
|
||||
|
||||
public FieldMapping field = null;
|
||||
|
|
|
@ -93,7 +93,7 @@ public class Param
|
|||
/**
|
||||
* Expression state.
|
||||
*/
|
||||
private static class ParamExpState
|
||||
public static class ParamExpState
|
||||
extends ConstExpState {
|
||||
|
||||
public Object sqlValue = null;
|
||||
|
|
|
@ -87,7 +87,6 @@ import org.apache.openjpa.jdbc.schema.Unique;
|
|||
import org.apache.openjpa.kernel.Filters;
|
||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||
import org.apache.openjpa.kernel.exps.Path;
|
||||
import org.apache.openjpa.kernel.exps.Literal;
|
||||
import org.apache.openjpa.lib.conf.Configurable;
|
||||
import org.apache.openjpa.lib.conf.Configuration;
|
||||
import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
|
||||
|
@ -1982,7 +1981,7 @@ public class DBDictionary
|
|||
ExpState state = val.initialize(sel, ctx, 0);
|
||||
// JDBC Paths are always PCPaths; PCPath implements Val
|
||||
ExpState pathState = ((Val) path).initialize(sel, ctx, 0);
|
||||
val.calculateValue(sel, ctx, state, (Val) path, pathState);
|
||||
calculateValue(val, sel, ctx, state, path, pathState);
|
||||
|
||||
// append the value with a null for the Select; i
|
||||
// indicates that the
|
||||
|
@ -3476,7 +3475,7 @@ public class DBDictionary
|
|||
if (str == null)
|
||||
return new Sequence[0];
|
||||
|
||||
PreparedStatement stmnt = conn.prepareStatement(str);
|
||||
PreparedStatement stmnt = prepareStatement(conn, str);
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
int idx = 1;
|
||||
|
@ -3485,21 +3484,19 @@ public class DBDictionary
|
|||
if (sequenceName != null)
|
||||
stmnt.setString(idx++, sequenceName);
|
||||
|
||||
rs = stmnt.executeQuery();
|
||||
List seqList = new ArrayList();
|
||||
while (rs.next())
|
||||
seqList.add(newSequence(rs));
|
||||
return (Sequence[]) seqList.toArray(new Sequence[seqList.size()]);
|
||||
} finally {
|
||||
rs = executeQuery(conn, stmnt, str);
|
||||
return getSequence(rs);
|
||||
} finally {
|
||||
if (rs != null)
|
||||
try {
|
||||
rs.close();
|
||||
} catch (SQLException se) {
|
||||
}
|
||||
try {
|
||||
stmnt.close();
|
||||
} catch (SQLException se) {
|
||||
}
|
||||
if (stmnt != null)
|
||||
try {
|
||||
stmnt.close();
|
||||
} catch (SQLException se) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3880,20 +3877,16 @@ public class DBDictionary
|
|||
});
|
||||
}
|
||||
|
||||
PreparedStatement stmnt = conn.prepareStatement(query);
|
||||
PreparedStatement stmnt = prepareStatement(conn, query);
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
rs = stmnt.executeQuery();
|
||||
if (!rs.next())
|
||||
throw new StoreException(_loc.get("no-genkey"));
|
||||
Object key = rs.getObject(1);
|
||||
if (key == null)
|
||||
log.warn(_loc.get("invalid-genkey", col));
|
||||
return key;
|
||||
rs = executeQuery(conn, stmnt, query);
|
||||
return getKey(rs, col);
|
||||
} finally {
|
||||
if (rs != null)
|
||||
try { rs.close(); } catch (SQLException se) {}
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
if (stmnt != null)
|
||||
try { stmnt.close(); } catch (SQLException se) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4277,4 +4270,55 @@ public class DBDictionary
|
|||
OpenJPAStateManager sm, ClassMapping cmd ) {
|
||||
return disableBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing query.
|
||||
*/
|
||||
protected ResultSet executeQuery(Connection conn, PreparedStatement stmnt, String sql
|
||||
) throws SQLException {
|
||||
return stmnt.executeQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn, String sql)
|
||||
throws SQLException {
|
||||
return conn.prepareStatement(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of getting sequence from the result set.
|
||||
*/
|
||||
protected Sequence[] getSequence(ResultSet rs) throws SQLException {
|
||||
List seqList = new ArrayList();
|
||||
while (rs != null && rs.next())
|
||||
seqList.add(newSequence(rs));
|
||||
return (Sequence[]) seqList.toArray(new Sequence[seqList.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of getting key from the result set.
|
||||
*/
|
||||
protected Object getKey (ResultSet rs, Column col) throws SQLException {
|
||||
if (!rs.next())
|
||||
throw new StoreException(_loc.get("no-genkey"));
|
||||
Object key = rs.getObject(1);
|
||||
if (key == null)
|
||||
log.warn(_loc.get("invalid-genkey", col));
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of calculating value.
|
||||
*/
|
||||
protected void calculateValue(Val val, Select sel, ExpContext ctx,
|
||||
ExpState state, Path path, ExpState pathState) {
|
||||
val.calculateValue(sel, ctx, state, (Val) path, pathState);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,17 @@ public class ResultSetResult
|
|||
setStore(store);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ResultSetResult(Connection conn,
|
||||
ResultSet rs, DBDictionary dict) {
|
||||
_conn = conn;
|
||||
_stmnt = null;
|
||||
_rs = rs;
|
||||
_dict = dict;
|
||||
}
|
||||
|
||||
/**
|
||||
* JDBC 2 constructor. Relies on being able to retrieve the statement
|
||||
* from the result set, and the connection from the statement.
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.openjpa.jdbc.sql;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Array;
|
||||
|
@ -57,10 +56,10 @@ import serp.util.Numbers;
|
|||
public class RowImpl
|
||||
implements Row, Cloneable {
|
||||
|
||||
protected static final Object NULL = new Object();
|
||||
public static final Object NULL = new Object();
|
||||
protected static final int VALID = 2 << 0;
|
||||
|
||||
private static final int RAW = Integer.MIN_VALUE;
|
||||
public static final int RAW = Integer.MIN_VALUE;
|
||||
|
||||
protected byte flags = 0;
|
||||
private final Column[] _cols;
|
||||
|
@ -950,4 +949,12 @@ public class RowImpl
|
|||
if (isValid())
|
||||
row.setValid(true);
|
||||
}
|
||||
|
||||
public Object[] getVals() {
|
||||
return _vals;
|
||||
}
|
||||
|
||||
public int[] getTypes() {
|
||||
return _types;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -641,4 +641,12 @@ public final class SQLBuffer
|
|||
return sub;
|
||||
}
|
||||
}
|
||||
|
||||
public void setParameters(List params) {
|
||||
_params = params;
|
||||
}
|
||||
|
||||
public List getColumns() {
|
||||
return _cols;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,10 +297,11 @@ public class SelectImpl
|
|||
try {
|
||||
SQLBuffer sql = toSelectCount();
|
||||
conn = store.getConnection();
|
||||
stmnt = sql.prepareStatement(conn);
|
||||
rs = stmnt.executeQuery();
|
||||
rs.next();
|
||||
return rs.getInt(1);
|
||||
stmnt = prepareStatement(conn, sql, null,
|
||||
ResultSet.TYPE_FORWARD_ONLY,
|
||||
ResultSet.CONCUR_READ_ONLY, false);
|
||||
rs = executeQuery(conn, stmnt, sql, false, store);
|
||||
return getCount(rs);
|
||||
} finally {
|
||||
if (rs != null)
|
||||
try { rs.close(); } catch (SQLException se) {}
|
||||
|
@ -342,31 +343,21 @@ public class SelectImpl
|
|||
}
|
||||
|
||||
SQLBuffer sql = toSelect(forUpdate, fetch);
|
||||
int rsType = (isLRS() && supportsRandomAccess(forUpdate))
|
||||
boolean isLRS = isLRS();
|
||||
int rsType = (isLRS && supportsRandomAccess(forUpdate))
|
||||
? -1 : ResultSet.TYPE_FORWARD_ONLY;
|
||||
Connection conn = store.getConnection();
|
||||
PreparedStatement stmnt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
if (isLRS())
|
||||
stmnt = sql.prepareStatement(conn, fetch, rsType, -1);
|
||||
if (isLRS)
|
||||
stmnt = prepareStatement(conn, sql, fetch, rsType, -1, true);
|
||||
else
|
||||
stmnt = sql.prepareStatement(conn, rsType, -1);
|
||||
|
||||
// if this is a locking select and the lock timeout is greater than
|
||||
// the configured query timeout, use the lock timeout
|
||||
if (forUpdate && _dict.supportsQueryTimeout && fetch != null
|
||||
&& fetch.getLockTimeout() > stmnt.getQueryTimeout() * 1000) {
|
||||
int timeout = fetch.getLockTimeout();
|
||||
if (timeout < 1000) {
|
||||
timeout = 1000;
|
||||
Log log = _conf.getLog(JDBCConfiguration.LOG_JDBC);
|
||||
if (log.isWarnEnabled())
|
||||
log.warn(_loc.get("millis-query-timeout"));
|
||||
}
|
||||
stmnt.setQueryTimeout(timeout / 1000);
|
||||
}
|
||||
rs = stmnt.executeQuery();
|
||||
stmnt = prepareStatement(conn, sql, null, rsType, -1, false);
|
||||
|
||||
setTimeout(stmnt, forUpdate, fetch);
|
||||
|
||||
rs = executeQuery(conn, stmnt, sql, isLRS, store);
|
||||
} catch (SQLException se) {
|
||||
// clean up statement
|
||||
if (stmnt != null)
|
||||
|
@ -375,17 +366,8 @@ public class SelectImpl
|
|||
throw se;
|
||||
}
|
||||
|
||||
SelectResult res = new SelectResult(conn, stmnt, rs, _dict);
|
||||
res.setSelect(this);
|
||||
res.setStore(store);
|
||||
res.setLocking(forUpdate);
|
||||
try {
|
||||
addEagerResults(res, this, store, fetch);
|
||||
} catch (SQLException se) {
|
||||
res.close();
|
||||
throw se;
|
||||
}
|
||||
return res;
|
||||
return getEagerResult(conn, stmnt, rs, store, fetch, forUpdate,
|
||||
sql.getSQL());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -423,6 +405,80 @@ public class SelectImpl
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of preparing statement.
|
||||
*/
|
||||
protected PreparedStatement prepareStatement(Connection conn,
|
||||
SQLBuffer sql, JDBCFetchConfiguration fetch, int rsType,
|
||||
int rsConcur, boolean isLRS) throws SQLException {
|
||||
if (fetch == null)
|
||||
return sql.prepareStatement(conn, rsType, rsConcur);
|
||||
else
|
||||
return sql.prepareStatement(conn, fetch, rsType, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of setting query timeout.
|
||||
*/
|
||||
protected void setTimeout(PreparedStatement stmnt, boolean forUpdate,
|
||||
JDBCFetchConfiguration fetch) throws SQLException {
|
||||
// if this is a locking select and the lock timeout is greater than
|
||||
// the configured query timeout, use the lock timeout
|
||||
if (forUpdate && _dict.supportsQueryTimeout && fetch != null
|
||||
&& fetch.getLockTimeout() > stmnt.getQueryTimeout() * 1000) {
|
||||
int timeout = fetch.getLockTimeout();
|
||||
if (timeout < 1000) {
|
||||
timeout = 1000;
|
||||
Log log = _conf.getLog(JDBCConfiguration.LOG_JDBC);
|
||||
if (log.isWarnEnabled())
|
||||
log.warn(_loc.get("millis-query-timeout"));
|
||||
}
|
||||
stmnt.setQueryTimeout(timeout / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing query.
|
||||
*/
|
||||
protected ResultSet executeQuery(Connection conn, PreparedStatement stmnt,
|
||||
SQLBuffer sql, boolean isLRS, JDBCStore store) throws SQLException {
|
||||
return stmnt.executeQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of getting count from the result set.
|
||||
*/
|
||||
protected int getCount(ResultSet rs) throws SQLException {
|
||||
rs.next();
|
||||
return rs.getInt(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to provide override for non-JDBC or JDBC-like
|
||||
* implementation of executing eager selects.
|
||||
*/
|
||||
protected Result getEagerResult(Connection conn,
|
||||
PreparedStatement stmnt, ResultSet rs, JDBCStore store,
|
||||
JDBCFetchConfiguration fetch, boolean forUpdate, String sqlStr)
|
||||
throws SQLException {
|
||||
SelectResult res = new SelectResult(conn, stmnt, rs, _dict);
|
||||
res.setSelect(this);
|
||||
res.setStore(store);
|
||||
res.setLocking(forUpdate);
|
||||
try {
|
||||
addEagerResults(res, this, store, fetch);
|
||||
} catch (SQLException se) {
|
||||
res.close();
|
||||
throw se;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// Select implementation
|
||||
/////////////////////////
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.apache.openjpa.util.UserException;
|
|||
*/
|
||||
public class Bootstrap {
|
||||
|
||||
private static final Class[] FACTORY_ARGS =
|
||||
protected static final Class[] FACTORY_ARGS =
|
||||
new Class[]{ ConfigurationProvider.class };
|
||||
|
||||
private static Localizer s_loc = Localizer.forPackage(Bootstrap.class);
|
||||
|
@ -124,7 +124,7 @@ public class Bootstrap {
|
|||
return (BrokerFactory) meth.invoke(null, new Object[]{ conf });
|
||||
}
|
||||
|
||||
private static String getFactoryClassName(ConfigurationProvider conf,
|
||||
protected static String getFactoryClassName(ConfigurationProvider conf,
|
||||
ClassLoader loader) {
|
||||
try {
|
||||
return getFactoryClass(conf, loader).getName();
|
||||
|
|
|
@ -2420,10 +2420,7 @@ public class BrokerImpl
|
|||
}
|
||||
|
||||
// make sure we don't already have the instance cached
|
||||
StateManagerImpl other = getStateManagerImplById(id, false);
|
||||
if (other != null && !other.isDeleted() && !other.isNew())
|
||||
throw new ObjectExistsException(_loc.get("cache-exists",
|
||||
obj.getClass().getName(), id)).setFailedObject(obj);
|
||||
checkForDuplicateId(id, obj);
|
||||
|
||||
// if had embedded sm, null it
|
||||
if (sm != null)
|
||||
|
@ -3817,7 +3814,7 @@ public class BrokerImpl
|
|||
_cache.remove(id, sm);
|
||||
break;
|
||||
case STATUS_OID_ASSIGN:
|
||||
_cache.assignObjectId(id, sm);
|
||||
assignObjectId(_cache, id, sm);
|
||||
break;
|
||||
case STATUS_COMMIT_NEW:
|
||||
_cache.commitNew(id, sm);
|
||||
|
@ -4700,4 +4697,23 @@ public class BrokerImpl
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the object id to the cache. Exception will be
|
||||
* thrown if the id already exists in the cache.
|
||||
*/
|
||||
protected void assignObjectId(Object cache, Object id,
|
||||
StateManagerImpl sm) {
|
||||
((ManagedCache) cache).assignObjectId(id, sm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method makes sure we don't already have the instance cached
|
||||
*/
|
||||
protected void checkForDuplicateId(Object id, Object obj) {
|
||||
StateManagerImpl other = getStateManagerImplById(id, false);
|
||||
if (other != null && !other.isDeleted() && !other.isNew())
|
||||
throw new ObjectExistsException(_loc.get("cache-exists",
|
||||
obj.getClass().getName(), id)).setFailedObject(obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3001,7 +3001,7 @@ public class StateManagerImpl
|
|||
/**
|
||||
* Mark the field as loaded or unloaded.
|
||||
*/
|
||||
private void setLoaded(int field, boolean isLoaded) {
|
||||
public void setLoaded(int field, boolean isLoaded) {
|
||||
// don't continue if loaded state is already correct; otherwise we
|
||||
// can end up clearing _fieldImpl when we shouldn't
|
||||
if (_loaded.get(field) == isLoaded)
|
||||
|
|
|
@ -22,8 +22,6 @@ import java.lang.instrument.ClassFileTransformer;
|
|||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.spi.ClassTransformer;
|
||||
import javax.persistence.spi.PersistenceProvider;
|
||||
|
@ -73,7 +71,7 @@ public class PersistenceProviderImpl
|
|||
*/
|
||||
public OpenJPAEntityManagerFactory createEntityManagerFactory(String name,
|
||||
String resource, Map m) {
|
||||
PersistenceProductDerivation pd = new PersistenceProductDerivation();
|
||||
PersistenceProductDerivation pd = newPersistenceProductDerivation();
|
||||
try {
|
||||
Object poolValue = Configurations.removeProperty(EMF_POOL, m);
|
||||
ConfigurationProvider cp = pd.load(resource, name, m);
|
||||
|
@ -101,7 +99,7 @@ public class PersistenceProviderImpl
|
|||
}
|
||||
|
||||
if (poolValue == null || !((Boolean) poolValue).booleanValue())
|
||||
return Bootstrap.newBrokerFactory(cp, loader);
|
||||
return newBrokerFactory(cp, loader);
|
||||
else
|
||||
return Bootstrap.getBrokerFactory(cp, loader);
|
||||
}
|
||||
|
@ -201,4 +199,19 @@ public class PersistenceProviderImpl
|
|||
return _trans.transform(cl, name, previousVersion, pd, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a persistence product deviration with default setting.
|
||||
*/
|
||||
public PersistenceProductDerivation newPersistenceProductDerivation() {
|
||||
return new PersistenceProductDerivation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a broker factory for the given configuration and class loader.
|
||||
*/
|
||||
public BrokerFactory newBrokerFactory(ConfigurationProvider cp,
|
||||
ClassLoader loader) {
|
||||
return Bootstrap.newBrokerFactory(cp, loader);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue