I had some .. hmm.. comparable issues.. I solved this with something
like this:
public interface SizedIterable<T> extends Iterable<T> {
long size();
}
so you can ask the iterable about the size..
mm:)
Am 07.05.2014 00:05, schrieb tetsuo:
Yeah, you're right. By reflex, I was thinking Hibernate Session (with open
session in view), not JDBC Connection, since I don't work directly with it
very often. And even if it was Hibernate, and the session was still open,
the connection would also be closed anyway.
What methods would the Page interface (with another name, since we already
have a Page class) have? iterator() and size()?
“The truth is rarely pure and never simple.” ― Oscar Wilde
On Tue, May 6, 2014 at 5:41 PM, Leszek Gawron <[email protected]> wrote:
I replied from wrong email, please excuse me if this reaches the list
twice.
On Tue, May 6, 2014 at 8:06 PM, tetsuo <[email protected]> wrote:
Since it's the same request, isn't (or couldn't be) the db connection the
same in size() and iterator() calls? If you created the temporary table
in
one, isn't it still available to the other (so you could avoid recreating
it)?
Well, the connection is being managed by spring transactional resource
management classes. A transaction is demarcated with
@Transactional(readOnly=true) on a particular method. All
transactional resources are bound to thread during transaction
execution and released when transaction finishes. One transactional
resource is of course a connection. I have extended this framework to
register temporary table names which are being automatically deleted
on transaction finish.
Each time you invoke a transactional method you perform following steps:
- acquire a connection from the pool
- bind connection to thread making all subsequent queries use same
connection
- start transaction
- do some work
- finish transaction (of course for read only there is nothing to be done)
- release transactional resources
- unbind connection from thread
- release connection to the pool.
using spring framework without spring managed transactions means you
end up using different connection for EVERY sql query.
My IDataProviders usually wrap spring bean with
@Transactional(readOnly=true) methods.
Unfortunatelly two method calls: size() and iterator() mean two
different transaction and two different connections. I am unable to
wrap any single point of entry with @Transactional - that probably
would have to be some generic Wicket method call. I cannot bind a
connection to current request thread preemptively because that would
mean a huge resource hog - I would have to obtain a connection from
pool for every request being made.
Temporary tables have connection scope so not deleting the table on
connection release means polluting the database server with lots of
temporary tables as long as connection stays in pool (which could be
indefinite).
The temporary tables would be probably stale all the time - any
ongoing transaction may probably alter what the temporary table should
contain.
Anyway any approach still feels like a hack and not resolving the
problem at source.
A single point of entry in IDataProvider:
- allows the user to manage resources more efficiently.
- gives user the option to resign from providing size() information -
do you really go from 1st to 15th page that often or do you usually
click "next results"?
- gives user the option to provide "has more results" information
without providing actual dataset size.
Having a single point of entry IDataSource means also you can do:
new IDataProviderSingleEntry<T( oldDataProvider ) {
public Page<T> getPage( long first, long count ) {
return new PageImpl<T>(
oldDataProvider.interator( first, count ), oldDataProvider.size()
);
}
}
This trivial decorator means IDataProviderSingleEntry and
IDataProvider may even coexist in wicket-core and wicket-extensions.
Some variation of this approach is actually used by inmethod-grid.
Maybe we could unify the way all pageables access resources.
--
Leszek Gawron