|
|
|
This one time, at band camp, Martin Fuchs said:
MF>while looking through in Castor's source code the following question I'm not sure why the getConnection() method is not exposed in the MF>Second: Why is the cast to Connection necessary? The cast to java.sql.Connection is explained above. Castor has MF>I would propose to change the return type of the getConnection() functions I disagree here and have explained the reaasons for this above. MF>What do you think? I've been pondering this myself over the last month or so. Especially ------------
------------ ----------- ---------------------
--------------------- -------------------------
------------------------- For a description of this ASCII UML, please see the following doc: http://c2.com/cgi/wiki?UmlAsciiArt In the diagram above, the DataSource interface would replace the Bear in mind that changes this significant would not go into the Bruce -------------------------------------------------------- MF>I can show you my typical needs for session intializations: No, I was only speaking of exposing method calls on the java.sql.Connetion Bruce OK, the following patch will contain only the extension of the Database
interface by getConnection() to expose DatabaseImpl.getConnection() without the need for a (DatabaseImpl) typecast. Created an attachment (id=663)
Patch for org.exolab.castor.jdo.Database interface >I'm not sure why the getConnection() method is not exposed in the
>Database interface. Not am I, but I thin the original intention was to make it 'quite difficult' to obtain a JDBC Connection from a Datbase instance. Here's why: a) Castor JDO is an o/r mapper, first and foremost. We do not want people to Because of this, I am really not sure whether we should expose getConnection I've seen all the design ideas, bug I do not have the time to comment now. > Not am I, but I thin the original intention was to make it 'quite difficult'
to > obtain a JDBC Connection from a Datbase instance. Here's why: Then this goal of making it 'quite difficult' has been reached. > a) Castor JDO is an o/r mapper, first and foremost. We do not want people to But you see, there is the need for some way to get access to the underlying SQL
So we should try to come up with a more convenient solution. > b) One must NOT close this connection instance, as this would interfer with If forbidding to call close() for the connection instance is the main reason Btw. a callback mechanism to allow initializing a database connection just > Initializing the database connection by setting some DB parameters
> or calling some stored procedures in the database. In the case of setting parameters, are you doing this by setting properties. Iow, can you please give a short example of what you'd be doing (e.g. using vanilla JDBC calls). > Calling stored procedures later on to process business logic. > Btw. a callback mechanism to allow initializing a database connection
> just after Castor created it, would also be a very kind thing. Imho, I'd really favour implementing such a feature. As far as I can see, one might have to deal with the fact that the underlying JDBC connection is not created at Database instantiation time. But I still believe that - as long as a handler is registered properly - it will be called, eventually. This example is already in the mails from above, but OK - here again.
This is an example of changing some database parameters using JDBC execute Statement stmt = conn.createStatement(); try { stmt.execute("set role ROLE_XXX identified by PASSWORD"); stmt.execute("alter session set nls_language = GERMAN"); stmt.execute("alter session set nls_territory = GERMANY"); stmt.execute("alter session set nls_numeric_characters = ',.'"); } catch(... To use the "CALL SQL" syntax I would have to create a OQLQuery. (Correct me if OQLQuery oql = db.getOQLQuery("CALL SQL alter session set nls_language = > This example is already in the mails from above, but OK - here again.
Oops, sorry , but I was picking up on the use of the word 'properties' again ... ![]() > To use the "CALL SQL" syntax I would have to create a OQLQuery. (Correct
> me if I have overseen another possibility.) But OQLQuery expects a query with > result set. Correct, and I wish I could correct you ... but unfortunately your assessment is true. Maybe we should allow for 'updates' to be used as part of a CALL SQL statement. Extending OQL to allow 'update' statements may also be a possibility.
You think about something like the following, right? db.execute("CALL SQL alter session set nls_language = GERMAN"); But then why no immediately allow to issue SQL statements, using e.g.: Exposing an Database.execute() function as in the first example would imply, Alright, there's too many threads in here (un)related to the original issue, i.e. exposing DatabaseImpl.getConnection() more formally (through the interface Database.java) and change its return type).
Me thinks that if we really, really expose a getConnection() method through the Database interface, we will have to provide very good documentation on this subject, as misuse can easily cause quite some problems. What about a getConnection() method in JDOManager that will return a java.sql.Connection. As that connection will not be associated with a TransactionManager the interference with castor would only be the cached objects. Its implementation would also be easy as we only need to call DatabaseRegistry.createConnection().
I also don't like to expose the DatabaseImpl.getConnection() method according to the reasons Werner mentioned. I think the ability to retrieve the DatabaseImpl connection is vital for several reasons:
1) In a transaction-oriented environment, the only way to get a safe set of operations is to do so on a single connection, in that single transaction, which can then guarantee rollback capability. 2) While calling passthrough SQL for all possible operations is possible, doing so will require the support of all of the semantics; that means allowing me to call any stored procedure to get any ResultSet I choose, not requiring me to create non-trivial mappings for a bunch of trivial SQL. There's no doubt that this isn't an 'entry level' operation - direct SQL calls can change, for example, the transaction type to READ_UNCOMMITTED, and watch your dataset torch itself when you do. However, without doing this, there's no way to build hybrid applications - you're 100% OQL, or you're 100% SQL, and never the twain shall meet - because I can't afford for my SQL operation to lock dead, waiting on an OQL transaction that can't complete until my SQL operation is done. DBLocked implies a requirement of the existence of that SQL Connection API. And, to boot, if the concern is that we don't want to expose an API because we can't guess at what the type is, build a typesafe implementation that does a public Object getNativeConnection(Class expectedType); that verifies that the connection we've got is of the same type as we're expecting, and return a null if they don't match the expected results. All in all, this is something that we need to add. We haven't got a choice; it's unreasonable to expect users to never build hybrid applications, and DBLocked is a very important feature for anyone who needs to build one. If you're THAT concerned about it's usage, have the getNativeConnection() class fail unless a flag is turned on in castor.properties, where it logs an error stating that you attempted to get a native connection from the current DB instance without first configuring it to allow it. But not implementing it, IMO, just isn't an option. Very good point Greogory. Your arguments conviced me to change my opinon to offer the Database.getConnection() method.
None the less I think we also should offer JDOManager.getConnection() for those SQL statements that need not to be in the same transaction with OQL statements. The javadoc for both methods should state when to use one or the other. What do you think about that? > None the less I think we also should offer JDOManager.getConnection() for those
> SQL statements that need not to be in the same transaction with OQL statements. > The javadoc for both methods should state when to use one or the other. What do > you think about that? Not sure, to be honest. What transactional semantics would be applied to such a scenario ? If you allow a user to obtain a connection from JDOManager, will 'auto-commit' mode be used or something else ? Do we want this to be configurable. As I've said, not sure. Other than this, let's move forward with this issue. Iow, +1.
Everything happens within someone's transactional context; as such, I see zero issue with asking a user to get a database object in order to get the connection...
The higher-level equivalent would be to ask JDOManager for the DataSource, and I don't necessarily feel that's wise. I don't see any issue with restricting it to Database only. And I look forward to getting rid of my DatabaseImpl cast. This is an update of the previous patch (plus some more Javadocs), and the removal of e.printStackTrace() calls.
One remaining question, though: in DatabaseImpl#getJdbcConnection(), do we really want to just log the PersistenceException being thrown in TransactionContext ?
Based upon a short discussion yesterday, we've settled to add a throws clause to Database.getJdbcConnection(). Will update the patch in due time and commit.
Updated patch to reflect the exception handling as discussed above.
Btw, any issues covered in this issue report that have not been addressed by the patch should be moved to new issues.
|
Implementation of Database.getJdbcConnection()