[EMAIL PROTECTED] wrote:
>
> I understand that ejbLoad will occur but Oracle will doesn't lock the row
> when reading. Also are you saying that the container obtains a read lock
> in an ejbLoad? How does it do that?
Container only obtains a lock in CMP, in BMP you have to do it youself.
In CMP that would happen through SELECT ... FOR UPDATE (Oracle) or
SELECT ... HOLDLOCK or SERIALIZABLE (Sybase). You can do the same in BMP
if you need to synchronize access.
Alternatively, you might want to open up a cursor in BMP with ejbLoad
and use it for ejbStore. (Not that I would recommend that with the
current state of EJB containers and JDBC drivers :-) )
The guidelines for BMP would be:
* If only one entity can access the data at a given time then:
ejbLoad must do a FOR UPDATE (or anything equivalent)
The server guarantees to do ejbLoad at least once in the transaction
and ejbStore when the transaction commits (not before)
* Or, if the server is smarter, you might declare the entity bean as
exclusive access and the EJB server will serialize method calls across
transactions
* If you want two entity beans to access the data at a given time, then:
Your business methods must do UPDATE, not count on the information
you loaded in ejbLoad
Or, your ejbStore must do the UPDATE smartly
* One possibility is to have:
int getBalance() but not setBalance()
have a field called increment which is not persistence, so
setIncrement() getIncremenet()
in ejbStore you would do an UPDATE balance += incremenet;
arkin
>
> dan
>
>
> Assaf Arkin
> <arkin@exoffic To: dan benanav
><[EMAIL PROTECTED]>
> e.com> cc: [EMAIL PROTECTED],
>[EMAIL PROTECTED]
> Sent by: Subject: Re: [EJB-INT] This should be
>easy an obvious, but it's
> [EMAIL PROTECTED] not.
> office.com
>
>
> 02/09/00 03:15
> PM
>
>
>
> > I dont think that is correct. Oracle provides for row level
> > locking. There is no update in ejbLoad so no locking occurs.
> > Locking only occurs when you update a row. See the following from the
> > Oracle site:
>
> You do need ejbLoad to occur. If it doesn't then someone else might
> update the database from outside the server, and your problem will not
> be just two beans racing to get the update first. So by definition, you
> need to synchronize first, which means an ejbLoad, which means you get a
> read lock on the row, which means serializable access.
>
> Excatly how you get that done is up to the EJB container.
>
> >
> > Row-Level Locking
>
> <snip>
> I know, I wrote code like that for the CMP engine.
> </snip>
>
> arkin
>
> > >
> > >
> > > But, if you opened a connection from a session bean with read
> > > committed,
> > > then ran the entity bean from it, you're still in read committed, so
> > > the
> > > serializable doesn't work for you.
> > >
> > > This is where the EJB server should allow you to mark the entity
> > > bean as
> > > exclusive access and maintain a lock, blocking B until A finishes
> > > the
> > > transaction. I'm working on code that does just that right now, and
> > > it's
> > > not that hard.
> > >
> > > Once again, lock contention.
> > >
> > > If you're looking for performance (and scalability and everything
> > > else)
> > > you should consider either:
> > >
> > > 1. Doing no 2) (in UPDATE from the entity bean), or
> > >
> > > 2. Using a stateless session bean (my favorite)
> > >
> > > You must always assume the EJB entity bean mantra of
> > > load-modify-commit,
> > > which either gets you into trouble if you don't pay attention to
> > > locking, or slows down your application if you do too much locking.
> > >
> > > arkin
> > >
> > > dan benanav wrote:
> > > >
> > > > I have a question about how to implement something using EJB. I
> > > am sure
> > > > that this problem is very common and that it has come up in
> > > discussions
> > > > in various forms on this list, but I don't think the right
> > > approach has
> > > > been clarified. This is surprising since the spec should be able
> > > to
> > > > handle such a situation rather easily. It appears to me that many
> > >
> > > > people have a misunderstanding about EJB that leads to an
> > > incorrect way
> > > > to solve this problem. Including in that misunderstanding is the
> > > Sun
> > > > BluePrints guide. In the following I will assume we are talking
> > > EJB 1.1
> > > > spec and I am interested in a solution that conforms to that spec.
> > >
> > > >
> > > > Problem: Suppose you have an Account class that is the remote
> > > interface
> > > > to an Account bean. AccountBean is the entity bean implementation
> > >
> > > > class. You want to write a method increment(int x) that adds x to
> > > the
> > > > balance on the account represented by the Account instance. There
> > > are 2
> > > > approaches that come to mind about how to do this. The first is
> > > the
> > > > most obvious but I believe there are problems with it.
> > > >
> > > > 1) public void increment(int x) {balance += x;};
> > > >
> > > > 2) public void increment(int x) { //use jdbc to increment the
> > > balance in
> > > > the db using sql like "updateaccount_table set balance = balance +
> > > ?
> > > > where account_key = ?". The first question mark is set to x and
> > > the
> > > > second question mark is set to the primary key of the bean.}
> > > >
> > > > Why isn't 1) good? Containers are free to use multiple bean
> > > instances
> > > > to handle concurrent calls to an entity object as long as those
> > > calls
> > > > are occurring under a different transaction. This means that you
> > > can
> > > > have bean instance A and bean instance B both handling calls to
> > > > increment x, where both A and B represent the same entity object
> > > (same
> > > > primary key). Some containers my choose not to do this, however
> > > there
> > > > is no guarantee that the container provider won't change their
> > > approach
> > > > in the future. Furthermore if you rely on the container not doing
> > > that
> > > > your code will not work on any EJB server. This would make it
> > > difficult
> > > > for EJB bean providers (like the Theory Center) for providing
> > > server or
> > > > container independent beans. So if you agree now that your code
> > > should
> > > > work if the Container provider uses multiple bean instances then I
> > > think
> > > > there is a problem. Suppose that in two separate threads calls
> > > are
> > > > made to an entity object. One thread calls increment(1) and the
> > > other
> > > > increment(2). These calls occur concurrently. Assume also that
> > > the
> > > > initial balance before the calls is 3. After the call the new
> > > balance
> > > > should be 6. Here is what can occur:
> > > >
> > > > T1:Container calls ejbLoad on Bean A: Balance gets set to 3.
> > > > T2:Container calls ejbLoad on Bean B: Balance still is 3.
> > > (This
> > > > happens in a separate thread and separate transaction context).
> > > > T3:Container calls increment(1) on Bean A: Balance gets set to 4
> > > in Bean
> > > > A.
> > > > T4:Container calls increment(2) on Bean B: Balance gets set to 5
> > > in Bean
> > > > B.
> > > > T5:Container calls ejbStore on Bean A: balance in database is
> > > updates to
> > > > 4.
> > > > T6:Container calls ejbStore on Bean B: what happens??
> > > >
> > > > What happens may depend on what the Transaction isolation level is
> > > and
> > > > perhaps on the underlying database. If you use Oracle and the
> > > default
> > > > transaction isolation level (read committed) then the balance gets
> > > set
> > > > to 5 in the database. (The wrong answer!). If you use
> > > serializable
> > > > transaction isolation level then an exception is thrown and the
> > > client
> > > > will have to react appropriately to the exception. So it would
> > > appear
> > > > that the only way 1) could possibly work (in some sense) is to
> > > use
> > > > transaction level serializable. So 1) with transaction
> > > serializable is
> > > > an approach but it is incompletely specified since we haven't said
> > > how
> > > > the client should handle this. I imagine there are ways to handle
> > > it.
> > > > (Catch the exception and try again for example). Furthermore I
> > > have
> > > > been told by WLS not to use transaction serializable due to a bug
> > > in
> > > > Oracle so 1) does not currently work for Oracle. Even if this
> > > would
> > > > work it seems like it would be better to just force the container
> > > or to
> > > > specify in the deployment descriptor that calls to increment
> > > should be
> > > > serialized. Currently there is no way to do that in the spec.
> > > >
> > > > The second solution would work however there are also problems
> > > with it.
> > > > You need to be careful to make sure that when ejbStore is called
> > > the
> > > > correct value is stored in the database. For example, you cannot
> > > just
> > > > increment the value in the db. You would also need to set balance
> > > in the
> > > > bean appropriately.
> > > >
> > > >
> > > > dan
> > > >
> > > >
> > >
> ===========================================================================
> > >
> > > > To unsubscribe, send email to [EMAIL PROTECTED] and include in
> > > the body
> > > > of the message "signoff EJB-INTEREST". For general help, send
> > > email to
> > > > [EMAIL PROTECTED] and include in the body of the message
> > > "help".
> > >
> > > --
> > > --
> > > -------------------------------------------------------------------
> > > Assaf Arkin
> > > www.exoffice.com
> > > CTO, Exoffice Technologies, Inc.
> > > www.exolab.org
>
> --
> ----------------------------------------------------------------------
> Assaf Arkin www.exoffice.com
> CTO, Exoffice Technologies, Inc. www.exolab.org
--
----------------------------------------------------------------------
Assaf Arkin www.exoffice.com
CTO, Exoffice Technologies, Inc. www.exolab.org
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".