persistence@glassfish.java.net

multiple threads trying to modfiy an entity

From: Mauro Almeida <malmeida_at_localmatters.com>
Date: Wed, 15 Apr 2009 12:22:20 -0600

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