How to prevent duplicate query results using persistence API in Java SE?

I use Java SE and learn how to use persistence (toplink-essentials) API to manage objects in DB Derby. Note: this is a (distance learning) university work, but it is not a "homework", this question arises in the course materials.

I have two threads working with the same set of objects. My problem is that every way I tried, the objects in the query result set (query executed in a transaction) in one thread can be modified so that the result set no longer applies to the rest of the transaction.

eg. from one thread this operation is performed:

static void updatePrices(EntityManager manager, double percentage) {
    EntityTransaction transaction = manager.getTransaction();

    transaction.begin();
    Query query = manager.createQuery("SELECT i FROM Instrument i where i.sold = 'no'");
    List<Instrument> results = (List<Instrument>) query.getResultList();

    // force thread interruption here (testing non-repeatable read)
    try { Thread.sleep(2000); } catch (Exception e) { }

    for (Instrument i : results) {
        i.updatePrice(percentage);
    }
    transaction.commit();
    System.out.println("Price update commited");
}

:

private static void sellInstrument(EntityManager manager, int id)
{
    EntityTransaction transaction = manager.getTransaction();
    transaction.begin();
    Instrument instrument = manager.find(Instrument.class, id);
    System.out.println("Selling: " + instrument.toFullString());
    instrument.setSold(true);
    transaction.commit();
    System.out.println("Instrument sale commited");
}

, , updatePrices() , resultSet , , . ( , ). , EntityManager ( factory).

( - ) "" () ? , - , Java EE, , , - , Java SE.


:

Vineet Pascal: @Version ( ) (updatePrices()) OptimisticLockException. , . ( updatePrices()), , sellInstrument() ( )? . ( , , Toplink Essentials).

+3
2

, EntityManager. EntityManagerFactory ( ), EntityManager , EntityManager ( , ).

Concurrency

JPA 1.0 () ( Version) , EntityManager.lock() API. " " / 3.4 Concurrency JPA 1.0 .

PS: , JPA 1.0 ( ​​ JPA 2.0, ). , Toplink eclipselink.pessimistic-lock.


wiki Wiki, TopLink Essentials JPA 1.0 :

// eclipselink.pessimistic-lock
Query Query = em.createQuery("select f from Foo f where f.bar=:bar");
query.setParameter("bar", "foobar");
query.setHint("eclipselink.pessimistic-lock", "Lock");
query.getResultList();

TopLink, , . , SQL-, "FOR UPDATE".

+3

EntityManager.lock(), .

, , . , SELECT... FROM tbl FOR UPDATE.

+2

Source: https://habr.com/ru/post/1754707/


All Articles