EntityManager fetching of attached entities

I have a DBServiceBean that is responsible for most of my DB access functions. I am doing this in order to make it easy to keep track of how many times various updates are being called and how long they take. I had the code working with DataManager but wanted to test EntityManager as I have many commits which would seem to benefit from being in managed transactions.

I call the DBServiceBean from both UIs and other Services and usually return the results of a database query. It works well for retrieving all of the local variables and increases the speed of the program ~25%. However, I am having a really weird problem with retrieving associated entities using views. Below is the DBServiceBean code that is behaving weird:


public List<ActShips> getFullShipList (){
        List<ActShips> ships = new ArrayList<>();
        try (Transaction txShipList = persistence.createTransaction()) {
            // get EntityManager for the current transaction
            EntityManager em = persistence.getEntityManager();
            // create and execute Query
            View view = new View(ActShips.class, "ships-view");
            Query query = em.createQuery(
                    "select e from fleetassessment$ActShips e")
                    .setView(view);

            ships = query.getResultList();
            stopClock();
            return ships;
        }
    }

When I debug, this code returns the exact result I want, including two sets of attached entities (EventList and RequirementsList) which are included in ‘ships-view’. The problem occurs in the data received back at the callling routine. In another service bean “SimServiceBean”, I call the function with the following code:


List<ActShips> ships = dbService.getFullShipList();

The return value from getFullShipList includes the local view of ActShips consistently but only sporadically gets the EventList and RequirementsList. When it works, all of the downstream code works great. When it fails, those fields show “Unable to evaluate the expression Method threw ‘java.lang.IllegalStateException’ exception.” and the code throws an exception the first time EventList or RequirementsList is called. When I manually step through the code in the IDE, it works more frequently and when I don’t put stop points, it never works. Sometimes 2 or 3 of the ships will include the attached entities and the other ships will have errors.

In a related question, is it possible to share a transaction between two services? I think I would like to keep the transactions managed as they are manipulated rather than have them detach and then merged.

What platform version are you using? We have recently fixed some bugs related to fetching nested collections in EclipseLink. Also, you can play with fetchMode attributes in views: if you set them to UNDEFINED, the collections will be fetched by separate selects and most probably always correctly.

Yes, it’s possible to span a transaction over multiple services or other middleware beans. So inside the transaction created in getFullShipList() you could invoke another bean and just use persistence.getEntityManager() in it - it will be the same persistence context.

I am using Cuba Studio 6.5 on a Windows 10 machine.

I set the fetchMode to UNDEFINED for all attributes in that view that support the attribute and didn’t have any success. One note, within getFullShipList(), the query is working perfectly. All attributes of all ships are always fetched. It is when the result (ships) is passed back to the calling function when things are getting stripped out.

FYI - the ActShips collection being set has a bunch of types of attributes. I list them below to show what is being passed successfully and what is not.

  • Datatypes: successfully passed
  • Embedded Entity: successfully passed
  • Many-to-One Association: successfully passed
  • One-to-Many Associations (EventList & RequirementsList): not passed

Sorry, I didn’t look carefully enough onto your code. What does this part mean?

View view = new View(ActShips.class, "ships-view");
Query query = em.createQuery(
        "select e from fleetassessment$ActShips e")
        .setView(view);

It seems that you create a new empty view and use it for the query, so no related objects are fetched by default.