users@glassfish.java.net

PLS HELP - Problem with merge()

From: Dibyendu Majumdar <dibyendu_at_mazumdar.demon.co.uk>
Date: Wed, 22 Feb 2006 23:25:47 +0000

Hi,

I posted a query on the discussion form but haven't had a reply yet so I
am posting this again. The original post is at:

http://forums.java.net/jive/thread.jspa?threadID=13292&tstart=0

To illustrate the problem, I am reproducing below similar situation
using a client program.

1. Extract from client program:

        try {
            InitialContext ctx = new InitialContext();
            WarehouseService ws = (WarehouseService)
ctx.lookup(WarehouseService.class.getName());
            Warehouse w = new Warehouse();
            w.setCity("LONDON");
            List list = ws.find(w);
            for (Object o : list) {
                System.err.println("Updating warehouse " + o.toString());
                w = (Warehouse) o;
                w.setStreet1("TESTING");
                ws.updateWarehouse(w);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

2. Extract from Session bean:

    public void updateWarehouse(Warehouse wh) {
        System.out.println("Updating " + wh);
        entityManager.merge(wh);
    }

3. Error message:

[#|2006-02-22T22:44:31.937+0000|INFO|sun-appserver-pe9.0|javax.enterprise.system.stream.out|_ThreadID=17;_ThreadName=p:
thread-pool-1; w: 3;|
[TopLink Warning]: 2006.02.22
10:44:31.937--UnitOfWork(31965176)--Exception [TOPLINK-4002] (Oracle
TopLink Essentials - 10g release 4 (10.1.4.0.0) (Build 060104Dev)):
oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.apache.derby.client.am.SqlException: The
statement was aborted because it would have caused a duplicate key value
in a unique or primary key constraint or unique index identified by
'SQL060218003812601' defined on 'WAREHOUSE'.Error Code: -1
Call:INSERT INTO TPCC.WAREHOUSE (W_YTD, W_ZIP, W_STREET_1, W_NAME,
W_TAX, W_STREET_2, W_STATE, W_CITY, W_VERSION) VALUES (0, NULL,
'TESTING', 'LONDON WAREHOUSE', 2, NULL, NULL, 'LONDON', 1)
Query:InsertObjectQuery(Warehouse(id=1, version=1, name=LONDON
WAREHOUSE, city=LONDON))
|#]

---------

My view is that this is a serious problem with the specification of
merge(). I think that merge() should be specified to always perform an
UPDATE, and persist() should be specified to always perform an INSERT.
At present, merge() attempts to do an INSERT if the entity is not
"managed" - however, this is non-intuitive as the example above shows.

In any case, I strongly recommend that the behaviour of persist and
merge be spelled out CLEARLY in terms of SQL operations. The
specification is too vague at present, and will result in
implementations behaving differently.

I also would like to some guidance on common use cases. For instance, I
believe a common use case is to query an entity, update it and then save
it.

Regards

Dibyendu