| Summary: | INSERT call in ExpressionQueryMechanism instead of UPDATE call | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | Markus Bukowski <markus.bukowski> |
| Component: | Eclipselink | Assignee: | Project Inbox <eclipselink.foundation-inbox> |
| Status: | NEW --- | QA Contact: | |
| Severity: | normal | ||
| Priority: | P2 | CC: | douglas.clarke, tom.ware |
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| Whiteboard: | |||
|
Description
Markus Bukowski
The following session-event-listener can capture all SQL without the parameter binding. Using some additional conditions on the query type the INSERT/UPDATE/DELETE within a TXN could be captured.
public class SQLCaptureListener extends SessionEventAdapter {
@Override
public void postExecuteQuery(SessionEvent event) {
DatabaseQuery query = (DatabaseQuery) event.getQuery();
String sql = query.getTranslatedSQLString(event.getSession(), query.getTranslationRow());
System.out.println("SQL: " + sql);
}
}
Here is a transactional example that captures all modify SQL in a UnitOfWork and logs it at the end.
/**
* Capture the modify SQL statements within a transaction and log them at the
* end.
*
* @author dclarke
* @since EclipseLink 2.2
*/
public class CaptureTransactionSQL extends SessionEventAdapter {
private static final String PROPERTY = CaptureTransactionSQL.class.getName();
@Override
public void postExecuteQuery(SessionEvent event) {
DatabaseQuery query = (DatabaseQuery) event.getQuery();
if (query.isModifyQuery() && event.getSession().isUnitOfWork()) {
String sql = query.getTranslatedSQLString(event.getSession(), query.getTranslationRow());
getSQLStrings(event.getSession()).add(sql);
}
}
@SuppressWarnings("unchecked")
private List<String> getSQLStrings(Session session) {
if (!session.getProperties().containsKey(PROPERTY)) {
session.setProperty(PROPERTY, new ArrayList<String>());
}
return (List<String>) session.getProperty(PROPERTY);
}
/**
* Log the SQL statements. This could alternatively store them.
*/
@Override
public void postCommitUnitOfWork(SessionEvent event) {
System.out.println("POST COMMIT - LOG SQL:");
for (String sql : getSQLStrings(event.getSession())) {
System.out.println("\t> " + sql);
}
}
}
This fails when the query has arguments. I believe another fix is required for that but may be fine for what you described. Thanks a lot for the quick response! I think that I have identified another problem. In the method ExpressionQueryMechanism(DatabaseQueryMechanism).insertObjectForWrite() the method updateForeignKeyFieldAfterInsert(WriteObjectQuery) is called. In which a new SQLUpdateStatement is created. After the creation of the statement the modifyRow of the previous InsertObjectQuery is set to the new SQLUpdateStatement-ModifyRow whereas the SQLCall is not replaced (See below). I think that the SQLCall should also be replaced. I think this is the reason for the previously described bug (The same code seems to be in the trunk version of EL). Current code in updateForeignKeyFieldAfterInsert(WriteObjectQuery): ... StatementQueryMechanism updateMechanism = new StatementQueryMechanism(writeQuery, updateStatement); writeQuery.setModifyRow(updateStatement.getModifyRow()); updateMechanism.updateObject(); ... Possible fix for updateForeignKeyFieldAfterInsert(WriteObjectQuery): ... StatementQueryMechanism updateMechanism = new StatementQueryMechanism(writeQuery, updateStatement); writeQuery.setModifyRow(updateStatement.getModifyRow()); // possible fix?? the new DatabaseSessionImpl() is also used in the toString() // of the class SQLStatement. Perhaps annother Session can be used writeQuery.setCall(updateStatement .buildCall( new DatabaseSessionImpl( new org.eclipse.persistence.sessions.DatabaseLogin() ) ); updateMechanism.updateObject(); ... The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |