[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [eclipselink-dev] questions while running JPA JUnit tests
|
Hi Dies,
Local temporary table is visible only in the database session (connection)
that has created it.
That means several threads may create local temp. tables with the same name.
The lifespan of such temporary table may be that of either transaction or
connection.
Global temporary tables created in the same namespace as regular tables -
there can't be 2 global temp. tables with the same name.
However the contents of the table are visible only to the database session
(connection) that inserted them (I see only my data).
Because the table is possibly shared it can't be dropped.
Some db support local (Sybase) other global (DB2) temporary tables.
Judging on Symfoware's db approach to table creation (no one can use the
table until creating connection is done with it)
it looked like the temp. table would be probably local (creating connection
is the only one that has access to the temp. table).
Could there be a setting allowing temporary table to only exist until
transaction is completed?
Google search for: symfoware temporary table
returns (among other stuff)
http://sourceforge.jp/projects/dbviewer/svn/view/DBViewer/trunk/src/zigen/plugin/db/core/TableSearcher.java?view=markup&root=dbviewer&pathrev=85
that contains:
// TABLE-TYPE
// "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
// "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
Not sure what is it exactly, but looks promising.
Thanks,
Andrei
----- Original Message -----
From: "Dies Koper" <diesk@xxxxxxxxxxxxxxxxxxx>
To: "Dev mailing list for Eclipse Persistence Services"
<eclipselink-dev@xxxxxxxxxxx>
Sent: Thursday, September 24, 2009 8:11 PM
Subject: Re: [eclipselink-dev] questions while running JPA JUnit tests
Hi Andrei,
Thank you for your suggestion.
Unfortunately it did not work. When it does the INSERT on the temporary
table, the driver returns an error saying the table is in use by another
user.
From what I understand from the code (only had a brief look), the effect
of the local setting over global is that the table is dropped instead of
the data in it being deleted at the end of its use.
What I think I need is a setting to have the creation of the temporary
table be executed in a separate transaction (even separate connection as a
transaction on the current connection might already have started?) from
the execution of the INSERT above and following DELETE (or DROP, which
again would need to be done in a separate transaction).
I can see ExpressionQueryManager#buildStatementsForUpdateAllForTempTables
and #buildStatementsForDeleteAllForTempTables methods build the statements
and pass a mode to them. If we could check this mode when the statements
are executed we can obtain a separate connection and enclose calls with
mode SQLModifyAllStatementForTempTable.CLEANUP_TEMP_TABLE in begin/commit
transaction calls.
What do you think?
Thanks,
Dies
Andrei Ilitchev wrote:
Try specifying temporary tables as local rather than global.
----- Original Message ----- From: "Dies Koper"
<diesk@xxxxxxxxxxxxxxxxxxx>
To: "Dev mailing list for Eclipse Persistence Services"
<eclipselink-dev@xxxxxxxxxxx>
Sent: Thursday, September 24, 2009 8:21 AM
Subject: Re: [eclipselink-dev] questions while running JPA JUnit tests
Hi Tom,
I finally got this test suite to stop hanging and locking.
I ended up putting the transaction begin/commit statements here:
- In SchemaManager#createObject/dropObject(in the if
(shouldWriteToDatabase()) block).
- In SequenceDefinition#createOnDatabase I put "checkIfExist(session)"
in a try-finally block, with a rollback in the finally clause, followed
by a beginTransaction. This was necessary because in the case of
sequence objects (not sequence tables), checkIfExist did a SELECT
nextval and createOnDatabase did a CREATE SEQUENCE, so I needed to
separate the DML from the DDL.
With that I still had problems with the global temporary table. A number
of tests in this suite rely on updateAll and deleteAll.
With global temporary tables disabled
(shouldAlwaysUseTempStorageForModifyAll() returns false), I get no
hangs/locks but I get an SQLException (see last week's e-mail "same
table in from clauses of query and subquery").
With global temporary tables implemented, creation of the table goes
fine, but the following INSERT fails because the table is "locked". I'm
not sure if I can (or should) put this table's create statement in a
transaction, I suppose this whole query could already be running in a
transaction.
Another issue with Symfoware's temporary tables is that the table space
name for the table must be specified at creation time. It does not
default to the table space that creation of normal tables default to. So
we'd need a way for the user to define this table space.
In what cases are updateAll/deleteAll required exactly? Are they
related to JPA 2.0 functions? Are they required for JPA 1.0
functionality too?
As I see no clean solution I wonder what the impact is of making this a
limitation for this platform for now.
With the global table disabled, I pass 176 tests (72%) of
EntityManagerJUnitTestSuite. The 45 errors are all due to the problem
above. Good news I suppose.
I'll try some more suites tomorrow.
If I no longer run into locking issues, what will the final solution
look like? Can I add a method createObjectsInTransactions() to the DB
platforms, defaulting to false of course, true for Symfoware, that
begins/commits/rolls back transactions in the locations I described
above?
Thanks,
Dies
Dies Koper wrote:
Hi Tom,
I am trying to enclose DDL calls with transactions. Inside
schemaManager.createSequences() there are mixed DDL and DML (select and
inserts on the sequence table/object), so just I'm moving the
transaction calls deeper into the call stack.
The locking error I get now is from the SELECT statement on table
CMP3_ENTITYB_SEQ in the following call in SchemaManager#createObject.
databaseObjectDefinition.createOnDatabase(getSession());
I did put a getSession().beginTransaction(); before this call, so I'm
not sure yet what the problem is. I'll investigate a bit more and let
you know.
Thanks,
Dies
The idea is that we would add calls that begin and commit transactions
around table creation calls.
Lets see if it works before we design the final solution:
- Find the
org.eclipse.persistence.tools.schemaframework.TableCreator.replaceTables(session,
schemaManager) method
- Add transactional boundaries
public void
replaceTables(org.eclipse.persistence.sessions.DatabaseSession
session, SchemaManager schemaManager) {
session.beginTransaction();
replaceTablesAndConstraints(schemaManager, session);
schemaManager.createSequences();
session.commitTransaction();
}
- Run
org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite
- Ensure your logging is at FINER or FINEST and look for log messages
like the following around the code that does DDL generation:
[EL Finer]:
ServerSession(16925102)--Connection(14004497)--Thread(Thread[main,5,main])--begin
transaction
<a whole lot of DDL here>
[EL Finer]:
ServerSession(16925102)--Connection(14004497)--Thread(Thread[main,5,main])--commit
transaction
- make sure there are no DDL statements outside of those boundries
- see if it makes any difference to your tests
Assuming we cannot solve the issue with transactions, the problem
really comes down to the session that is passed into the
constructors for SchemaManager. That is the session used to execute
DDL. Changing the API is likely the cleanest way to do that, but I
am a bit concerned about the number of files we will have to change
to achieve that. I'll have to give some thought to a solution that
combines a reasonable number of changes to test files with logical
API.
I am still not sure what is causing the hangs and lock errors, so if
you could first suggest some temporal changes to a subset of tests
that I can apply and try to see if that solves all issues, that would
be great.
We may be able to add a temporary solution by creating some kind
of static session that we use for DDL generation and using that
session instead of the ones passed into the SchemaManager
constructor. Then we can try logging it in and out as DDL calls are
made. I am a bit concerned about that effect that will have on how
long the tests take to run, but I'll try to do some experimentation.
How do sessions relate to the JDBC connections?
I am hoping that we can find a DB transaction related solution since a
solution like that will fit much better into the EclipseLink schema
creation architecture.
In JPA, an EntityManager holds a construct called a ClientSession. A
ClientSession communicates with a construct called a ServerSession to
make us of connections (an EntityManagerFactory holds the
ServerSession). A ServerSession holds a number of pools of
connections. (for reading, for writing, for sequences)
_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev