You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Dirk Lattermann <dl...@alqualonde.de> on 2017/10/08 09:39:04 UTC

Controlling Cayennes JDBC connection usage

Hello,

is it possible to control which database connection is used when
committing an ObjectContext?

For example, when using an explicit transaction, the database
connection used in the thread starting the exception must always be the
same.

Now, I have a use case where I want to obtain a PostgresQL advisory
exclusive session lock and do some DDL to create a db schema. Then I
want to write something into that schema using Cayenne, and after that,
release the lock. That's to somewhat atomically initialize a db schema.

For normal schema usage, I want to obtain an advisory shared lock in the
db connection and use that connection with Cayenne.

That mechanism can also be used to manipulate portions of the database
that must be done without concurrent access.

It's how I solved the problem with Hibernate, where a Hibernate session
represents a JDBC Connection. It is bound to the current thread and
used for all Hibernate DB accesses during the session. That worked
quite well.

Would it be possible to do something similar with Cayenne?

Re: Controlling Cayennes JDBC connection usage

Posted by Dirk Lattermann <dl...@alqualonde.de>.
Hi Andrus,

thanks for your indications. I'll investigate if all that can lead to a
solution that does what I need. I already pondered if
Cayenne's transaction management and SchemaUpdateStrategies might work
out. Since my approach with Hibernate works even with several
transactions in a Session (thus a Connection), I was/am a bit in doubt.
But maybe the restriction to a single transaction is sufficient.

Further, I'll try and implement a SchemaUpdateStrategy based on
Liquibase.

I'll post my findings. Thanks again,

Dirk

Am Mon, 9 Oct 2017 09:29:22 +0300
schrieb Andrus Adamchik <an...@objectstyle.org>:

> Hi Dirk,
> 
> When using explicit transactions [1], the connection is always the
> same within the transaction. "runtime.performInTransaction(..)" [2]
> can also take TransactionListener as a second argument that you may
> implement to set connection properties. 
> 
> Unrelated to the above, specifically for schema generation purposes
> you can bind SchemaUpdateStrategyFactory [3] when you start your
> runtime, that creates SchemaUpdateStrategy (either one of the
> standard choices like CreateIfNoSchemaStrategy, or your custom
> version). Cayenne is guaranteed to invoke the strategy before any of
> the app code can access the DB.
> 
> Hopefully it will point you in the right direction.
> 
> Andrus
> 
> [1]
> http://cayenne.apache.org/docs/4.0/cayenne-guide/persistent-objects-objectcontext.html#transactions
> [2]
> https://cayenne.apache.org/docs/4.0/api/index.html?org/apache/cayenne/configuration/server/ServerRuntime.html
> [3]
> https://cayenne.apache.org/docs/4.0/api/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.html
> 
> 
> > On Oct 8, 2017, at 12:39 PM, Dirk Lattermann <dl...@alqualonde.de>
> > wrote:
> > 
> > Hello,
> > 
> > is it possible to control which database connection is used when
> > committing an ObjectContext?
> > 
> > For example, when using an explicit transaction, the database
> > connection used in the thread starting the exception must always be
> > the same.
> > 
> > Now, I have a use case where I want to obtain a PostgresQL advisory
> > exclusive session lock and do some DDL to create a db schema. Then I
> > want to write something into that schema using Cayenne, and after
> > that, release the lock. That's to somewhat atomically initialize a
> > db schema.
> > 
> > For normal schema usage, I want to obtain an advisory shared lock
> > in the db connection and use that connection with Cayenne.
> > 
> > That mechanism can also be used to manipulate portions of the
> > database that must be done without concurrent access.
> > 
> > It's how I solved the problem with Hibernate, where a Hibernate
> > session represents a JDBC Connection. It is bound to the current
> > thread and used for all Hibernate DB accesses during the session.
> > That worked quite well.
> > 
> > Would it be possible to do something similar with Cayenne?  
> 


Re: Controlling Cayennes JDBC connection usage

Posted by Andrus Adamchik <an...@objectstyle.org>.
>  but it seems to do that on every call to ObjectContext.commit()! 

We can clean up this code a bit to make sure custom strategies are not themselves responsible for synchronization of the call and ensuring a single invocation. Though if you extend from BaseSchemaUpdateStrategy or use one of the built-in strategies (like SchemaUpdateStrategyFactory) you shouldn't worry about this at all. Cayenne will do the right thing.

There's a small overhead in invoking this code in BaseSchemaUpdateStrategy:

  if (!run && (inProgress == null || !inProgress)) ...

But really not that much.

Andrus


> On Oct 12, 2017, at 9:38 PM, Dirk Lattermann <dl...@alqualonde.de> wrote:
> 
> I experimented a bit with the SchemaUpdateStrategyFactory to create a
> test SchemaUpdateStrategy. It is correct that Cayenne calls the
> strategy before any app code can access the DB, but it seems to do that
> on every call to ObjectContext.commit()! That's quite surprising to me
> because I think it would be sufficient to call it only before the first
> database access of a DataNode. If the Strategy is quite expensive (for
> example, using Liquibase), then that has quite a performance impact.
> 
> Is it possibly considered the task of the Factory to return a strategy
> only on the first call to the DataNode? That also would be quite
> surprising to me, but I did not find any documentation about that.
> 
> 
> Am Mon, 9 Oct 2017 09:29:22 +0300
> schrieb Andrus Adamchik <an...@objectstyle.org>:
> 
>> Hi Dirk,
>> 
>> When using explicit transactions [1], the connection is always the
>> same within the transaction. "runtime.performInTransaction(..)" [2]
>> can also take TransactionListener as a second argument that you may
>> implement to set connection properties. 
>> 
>> Unrelated to the above, specifically for schema generation purposes
>> you can bind SchemaUpdateStrategyFactory [3] when you start your
>> runtime, that creates SchemaUpdateStrategy (either one of the
>> standard choices like CreateIfNoSchemaStrategy, or your custom
>> version). Cayenne is guaranteed to invoke the strategy before any of
>> the app code can access the DB.
>> 
>> Hopefully it will point you in the right direction.
>> 
>> Andrus
>> 
>> [1]
>> http://cayenne.apache.org/docs/4.0/cayenne-guide/persistent-objects-objectcontext.html#transactions
>> [2]
>> https://cayenne.apache.org/docs/4.0/api/index.html?org/apache/cayenne/configuration/server/ServerRuntime.html
>> [3]
>> https://cayenne.apache.org/docs/4.0/api/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.html
>> 
>> 
>>> On Oct 8, 2017, at 12:39 PM, Dirk Lattermann <dl...@alqualonde.de>
>>> wrote:
>>> 
>>> Hello,
>>> 
>>> is it possible to control which database connection is used when
>>> committing an ObjectContext?
>>> 
>>> For example, when using an explicit transaction, the database
>>> connection used in the thread starting the exception must always be
>>> the same.
>>> 
>>> Now, I have a use case where I want to obtain a PostgresQL advisory
>>> exclusive session lock and do some DDL to create a db schema. Then I
>>> want to write something into that schema using Cayenne, and after
>>> that, release the lock. That's to somewhat atomically initialize a
>>> db schema.
>>> 
>>> For normal schema usage, I want to obtain an advisory shared lock
>>> in the db connection and use that connection with Cayenne.
>>> 
>>> That mechanism can also be used to manipulate portions of the
>>> database that must be done without concurrent access.
>>> 
>>> It's how I solved the problem with Hibernate, where a Hibernate
>>> session represents a JDBC Connection. It is bound to the current
>>> thread and used for all Hibernate DB accesses during the session.
>>> That worked quite well.
>>> 
>>> Would it be possible to do something similar with Cayenne?  
>> 
> 


Re: Controlling Cayennes JDBC connection usage

Posted by Dirk Lattermann <dl...@alqualonde.de>.
I experimented a bit with the SchemaUpdateStrategyFactory to create a
test SchemaUpdateStrategy. It is correct that Cayenne calls the
strategy before any app code can access the DB, but it seems to do that
on every call to ObjectContext.commit()! That's quite surprising to me
because I think it would be sufficient to call it only before the first
database access of a DataNode. If the Strategy is quite expensive (for
example, using Liquibase), then that has quite a performance impact.

Is it possibly considered the task of the Factory to return a strategy
only on the first call to the DataNode? That also would be quite
surprising to me, but I did not find any documentation about that.


Am Mon, 9 Oct 2017 09:29:22 +0300
schrieb Andrus Adamchik <an...@objectstyle.org>:

> Hi Dirk,
> 
> When using explicit transactions [1], the connection is always the
> same within the transaction. "runtime.performInTransaction(..)" [2]
> can also take TransactionListener as a second argument that you may
> implement to set connection properties. 
> 
> Unrelated to the above, specifically for schema generation purposes
> you can bind SchemaUpdateStrategyFactory [3] when you start your
> runtime, that creates SchemaUpdateStrategy (either one of the
> standard choices like CreateIfNoSchemaStrategy, or your custom
> version). Cayenne is guaranteed to invoke the strategy before any of
> the app code can access the DB.
> 
> Hopefully it will point you in the right direction.
> 
> Andrus
> 
> [1]
> http://cayenne.apache.org/docs/4.0/cayenne-guide/persistent-objects-objectcontext.html#transactions
> [2]
> https://cayenne.apache.org/docs/4.0/api/index.html?org/apache/cayenne/configuration/server/ServerRuntime.html
> [3]
> https://cayenne.apache.org/docs/4.0/api/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.html
> 
> 
> > On Oct 8, 2017, at 12:39 PM, Dirk Lattermann <dl...@alqualonde.de>
> > wrote:
> > 
> > Hello,
> > 
> > is it possible to control which database connection is used when
> > committing an ObjectContext?
> > 
> > For example, when using an explicit transaction, the database
> > connection used in the thread starting the exception must always be
> > the same.
> > 
> > Now, I have a use case where I want to obtain a PostgresQL advisory
> > exclusive session lock and do some DDL to create a db schema. Then I
> > want to write something into that schema using Cayenne, and after
> > that, release the lock. That's to somewhat atomically initialize a
> > db schema.
> > 
> > For normal schema usage, I want to obtain an advisory shared lock
> > in the db connection and use that connection with Cayenne.
> > 
> > That mechanism can also be used to manipulate portions of the
> > database that must be done without concurrent access.
> > 
> > It's how I solved the problem with Hibernate, where a Hibernate
> > session represents a JDBC Connection. It is bound to the current
> > thread and used for all Hibernate DB accesses during the session.
> > That worked quite well.
> > 
> > Would it be possible to do something similar with Cayenne?  
> 


Re: Controlling Cayennes JDBC connection usage

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi Dirk,

When using explicit transactions [1], the connection is always the same within the transaction. "runtime.performInTransaction(..)" [2] can also take TransactionListener as a second argument that you may implement to set connection properties. 

Unrelated to the above, specifically for schema generation purposes you can bind SchemaUpdateStrategyFactory [3] when you start your runtime, that creates SchemaUpdateStrategy (either one of the standard choices like CreateIfNoSchemaStrategy, or your custom version). Cayenne is guaranteed to invoke the strategy before any of the app code can access the DB.

Hopefully it will point you in the right direction.

Andrus

[1] http://cayenne.apache.org/docs/4.0/cayenne-guide/persistent-objects-objectcontext.html#transactions
[2] https://cayenne.apache.org/docs/4.0/api/index.html?org/apache/cayenne/configuration/server/ServerRuntime.html
[3] https://cayenne.apache.org/docs/4.0/api/org/apache/cayenne/access/dbsync/SchemaUpdateStrategyFactory.html


> On Oct 8, 2017, at 12:39 PM, Dirk Lattermann <dl...@alqualonde.de> wrote:
> 
> Hello,
> 
> is it possible to control which database connection is used when
> committing an ObjectContext?
> 
> For example, when using an explicit transaction, the database
> connection used in the thread starting the exception must always be the
> same.
> 
> Now, I have a use case where I want to obtain a PostgresQL advisory
> exclusive session lock and do some DDL to create a db schema. Then I
> want to write something into that schema using Cayenne, and after that,
> release the lock. That's to somewhat atomically initialize a db schema.
> 
> For normal schema usage, I want to obtain an advisory shared lock in the
> db connection and use that connection with Cayenne.
> 
> That mechanism can also be used to manipulate portions of the database
> that must be done without concurrent access.
> 
> It's how I solved the problem with Hibernate, where a Hibernate session
> represents a JDBC Connection. It is bound to the current thread and
> used for all Hibernate DB accesses during the session. That worked
> quite well.
> 
> Would it be possible to do something similar with Cayenne?