persistence@glassfish.java.net

Re: multiple threads trying to modfiy an entity

From: Gordon Yorke <gordon.yorke_at_oracle.com>
Date: Thu, 16 Apr 2009 09:53:28 -0300

Stateless session beans can be used by more than one client. The best
practise is to inject an EntityManagerFactory and then for each
invocation create an EntityManager within the method. Otherwise
multiple threads may be using the same EM.
--Gordon

Mauro Almeida wrote:
>
> Hi,
>
>
>
> I have the following problem.
>
>
>
> I have a facade (a stateless bean, CMT) that has an entity Manager and
> a method where several threads can call to have for an entry updated..
>
>
>
> What is happening is that the database is not updated properly.
> Sometimes the counter is not incremented, which seems to me something
> related to the attachment of the entity with the DB. Also, when the
> table is initially empty and all N updates come at the same to the
> same row, it tells me it has a duplicate key.
>
>
>
> I'm using sailfing build 60g. The DB is a JavaDB database
>
>
>
> The façade looks like:
>
> @Stateless
>
> @TransactionManagement(TransactionManagermentType.CONTAINER)
>
> public class MyFacade implements IMyFacade ()
>
>
>
> @PersistenceContext(unitName="myunit")
>
> private EntityManager em;
>
>
>
> @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
>
> public void updateEntry (StatsType type, int id)
> {
>
> try {
>
> Stats s = em.find(Stats.class, id);
>
> // if could not find entry in the DB, create it
>
> if (s == null) {
>
> Stats s =
> createStat(id);
>
> // Now increment the proper count, based on the
> type o msg received
>
> switch (type) {
>
> case TOTAL:
>
> s1.setTotal(s1.getTotal()+1);
>
> break;
>
> case PARTIAL:
>
> s1.setPartial(s1.getPartial()+1);
>
> break;
>
> }
>
> em.persist(s1);
>
> em.flush();
>
> } else {
>
> switch (type) {
>
> case TOTAL:
>
> s.setTotal(s.getTotal()+1);
>
> break;
>
> case PARTIAL:
>
> s.setPartial(s.getPartial()+1);
>
> break;
>
> }
>
> em.merge(s);
>
> em.flush();
>
> }
>
> } catch (Exception ex) {
>
> ex.printStackTrace();
>
> }
>
> }
>
>
>
> The transactionManagement, the em.flush and TransactionAttributes
> annotation I've put then after my original attempts failed.
>
>
>
> persistence.xml looks like:
>
> <?xml version="1.0" encoding="UTF-8"?>
>
> <persistence version="1.0"
> xmlns="http://java.sun.com/xml/ns/persistence"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
> http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
>
> <persistence-unit name="myunit" transaction-type="JTA">
>
> <jta-data-source>jdbc/castats</jta-data-source>
>
> <properties>
>
> <property name="toplink.jdbc.user" value="username"/>
>
> <property name="toplink.jdbc.password" value="passed"/>
>
> <!-- <property name="toplink.cache.type.default"
> value="NONE"/> -->
>
> </properties>
>
> </persistence-unit>
>
> </persistence>
>
>
>
>
>
> Can someone point in the right direction? Why Do I have this race
> condition?
>
>
>
>
>
>
>
> Mauro Almeida
>
>
>