From: carmelo on
Hello everybody,
I developed a CRUD application using TopLink Essentials as persistence
provider. I've got the following problem:

I have to save data according to the master-details scheme, but I can
not read that unless restarting the application, even if they are
already physically on the database before restarting.

In practice, I read master/details of an offer and transform them into
master/details of an order, storing them on db.

Since these data are generated within another transaction, I created
another EntityManager called entityManager2.

This is the code I'm using:

org.jdesktop.application.ResourceMap resourceMap =
org.jdesktop.application.Application.getInstance(desktopapplication_db_advanced.DesktopApplication_db_advanced.class).getContext().getResourceMap(OffertaEditor.class);
EntityManager entityManager2 =
javax.persistence.Persistence.createEntityManagerFactory(resourceMap.getString("entityManager.persistenceUnit")).createEntityManager();
try {
entityManager2.getTransaction().begin();
int numOrdine = 0;
Object res = entityManager2.createQuery("SELECT
MAX(o.numOrdine) FROM Ordini o WHERE o.anno
= :anno").setParameter("anno", anno).getSingleResult();
entityManager2.getTransaction().commit();
if (res != null) {
numOrdine = (Integer) res;
}
numOrdine++;
numOrdineField.setText(String.valueOf(numOrdine));

//create order from offer

entityManager2.getTransaction().begin();

//master order
int index = masterTable.getSelectedRow();
offerta.Offerte of =
list.get(masterTable.convertRowIndexToModel(index));
ordine.Ordini ord = new ordine.Ordini();

ord.setCodiceCliente(Integer.parseInt(clienteField.getText()));
ord.setNumOfferta(of.getNumOfferta());
ord.setNumOrdine(numOrdine);
entityManager2.persist(ord);
//details order
Collection<offerta.Dettofferte> ds = of.getDettofferteList();
Iterator<offerta.Dettofferte> iter = ds.iterator();
int rows = detailTable.getRowCount();
for (int idx = 0; idx < rows; idx++) {
offerta.Dettofferte dettoff = iter.next();
ordine.Dettordini dettord = new Dettordini();
dettord.setCodiceArticolo(dettoff.getCodiceArticolo());
dettord.setDescrizione(dettoff.getDescrizione());
dettord.setNumOrdine(numOrdine);
dettord.setPrezzo(dettoff.getPrezzo());
dettord.setQuantita(dettoff.getQuantita());
dettord.setTotale(dettoff.getTotale());

entityManager2.persist(dettord);
dettord.setCodiceOrdine(ord);
}

entityManager2.getTransaction().commit();
entityManager2.close();

} catch (RollbackException rex) {
rex.printStackTrace();
entityManager2.getTransaction().rollback();
entityManager2.close();
}


Would you have any advice?

I hope you can help me. Thank you very much in advance!
From: Robert Klemme on
On 05/13/2010 12:49 PM, carmelo wrote:
> Hello everybody,
> I developed a CRUD application using TopLink Essentials as persistence
> provider. I've got the following problem:
>
> I have to save data according to the master-details scheme, but I can
> not read that unless restarting the application, even if they are
> already physically on the database before restarting.
>
> In practice, I read master/details of an offer and transform them into
> master/details of an order, storing them on db.
>
> Since these data are generated within another transaction, I created
> another EntityManager called entityManager2.

Without knowing Toplink myself I believe having a second EM for the
*same* schema is a bad idea. Typically an EM assumes that you access a
particular set of data only through it - so consequently (because of its
caching and remembering of persistent state) it won't see changes made
through another EM. The fact that two TX are involved does not create
necessity to have two EM. Only if you need to access different data
sources you would need more than one EM.

> This is the code I'm using:

I see only one EM in that code. It seems this does not give the whole
picture.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
From: carmelo on
Thank you for your reply Robert.

I try to describe the whole picture:

I have 2 JFrame
- one is for CRUD operations on Offer (and for transforming master/
details offer into master/details order), lets call it frmOfferEditor
- one is for searching Order created by frmOfferEditor, lets call it
frmOrderSearch

/* frmOfferEditor */

//transform
The code I posted before it's the code I'm using on frmEditor when I
need transforming master/details offer into master/details order.

//CRUD
The code I use for CRUD operations uses an EM called entityManager.
Here is the code:

//CRUD - Create
try {
entityManager.getTransaction().rollback();
entityManager.getTransaction().begin();
offerta = new offerta.Offerte();
numOfferta = 0;
Object res = entityManager.createQuery("SELECT MAX(o.numOfferta) FROM
Offerte o WHERE o.anno = :anno").setParameter("anno",
anno).getSingleResult();
if (res != null) {
numOfferta = (Integer) res;
}
numOfferta++;
offerta.setNumOfferta(numOfferta);
entityManager.persist(offerta);
} catch (Exception ex) {
ex.printStackTrace();
}

// CRUD - Save
try {
entityManager.getTransaction().commit();
entityManager.getTransaction().begin();
} catch (RollbackException rex) {
rex.printStackTrace();
entityManager.getTransaction().begin();
List<offerta.Offerte> merged = new
ArrayList<offerta.Offerte>(list.size());
for (offerta.Offerte o : list) {
merged.add(entityManager.merge(o));
}
list.clear();
list.addAll(merged);
}


/* frmOrderSearch */
try {
entityManager.getTransaction().rollback();
entityManager.getTransaction().begin();
String query = ....
Query q = entityManager.createQuery(query).setParameter(.....)
java.util.Collection data = q.getResultList();
list.clear();
list.addAll(data);
} catch (Exception ex) {
ex.printStackTrace();
}


I hope that now it's clear
From: Robert Klemme on
On 13.05.2010 13:34, carmelo wrote:
> Thank you for your reply Robert.
>
> I try to describe the whole picture:
>
> I have 2 JFrame
> - one is for CRUD operations on Offer (and for transforming master/
> details offer into master/details order), lets call it frmOfferEditor
> - one is for searching Order created by frmOfferEditor, lets call it
> frmOrderSearch

> I hope that now it's clear

I still fail to see why you think you need two EM. If the data is
sitting in the same location (same schema in the same DB server accessed
through the same user), then you only need one. Also, with a clean MVP
separation you would not bother how many UI elements access the data.
To me it seems you have an application design issue.

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
From: Lew on
carmelo wrote:
> I developed a CRUD application using TopLink Essentials as persistence
> provider. I've got the following problem:

These days "[a]s of Oracle TopLink 11g, TopLink Essentials has been replaced
with EclipseLink JPA. EclipseLink JPA implements JPA 1.0 and is responsible
for delivering the persistence framework."
<http://www.oracle.com/technology/products/ias/toplink/jpa/index.html>

> I have to save data according to the master-details scheme, but I can
> not read that unless restarting the application, even if they are
> already physically on the database before restarting.
>
> In practice, I read master/details of an offer and transform them into
> master/details of an order, storing them on db.
>
> Since these data are generated within another transaction, I created
> another EntityManager called entityManager2.

Robert addressed this point.

> This is the code I'm using:
>
> org.jdesktop.application.ResourceMap resourceMap =
> org.jdesktop.application.Application.getInstance(desktopapplication_db_advanced.DesktopApplication_db_advanced.class).getContext().getResourceMap(OffertaEditor.class);
> EntityManager entityManager2 =

That package name does not conform to the naming conventions.

You're not providing an SSCCE, and you should.

Use imports to make your code more readable.

> javax.persistence.Persistence.createEntityManagerFactory(resourceMap.getString("entityManager.persistenceUnit")).createEntityManager();
> try {
> entityManager2.getTransaction().begin();
> int numOrdine = 0;
> Object res = entityManager2.createQuery("SELECT
> MAX(o.numOrdine) FROM Ordini o WHERE o.anno
> = :anno").setParameter("anno", anno).getSingleResult();
> entityManager2.getTransaction().commit();

A transaction for a SELECT??

And you declared the variable 'Object'. Tsk, tsk.

> if (res != null) {
> numOrdine = (Integer) res;
> }
> numOrdine++;
> numOrdineField.setText(String.valueOf(numOrdine));

As Robert said, lack of MVC separation here shows that you have a messed-up
design.

>
> //create order from offer
>
> entityManager2.getTransaction().begin();
>
> //master order
> int index = masterTable.getSelectedRow();

Huh? 'masterTable'? What's that?

> offerta.Offerte of =
> list.get(masterTable.convertRowIndexToModel(index));

Huh? 'list'? What's that?

> ordine.Ordini ord = new ordine.Ordini();
>
> ord.setCodiceCliente(Integer.parseInt(clienteField.getText()));
> ord.setNumOfferta(of.getNumOfferta());
> ord.setNumOrdine(numOrdine);
> entityManager2.persist(ord);
> //details order
> Collection<offerta.Dettofferte> ds = of.getDettofferteList();
> Iterator<offerta.Dettofferte> iter = ds.iterator();
> int rows = detailTable.getRowCount();

Huh? 'detailTable'? What's that?

> for (int idx = 0; idx< rows; idx++) {
> offerta.Dettofferte dettoff = iter.next();
> ordine.Dettordini dettord = new Dettordini();
> dettord.setCodiceArticolo(dettoff.getCodiceArticolo());
> dettord.setDescrizione(dettoff.getDescrizione());
> dettord.setNumOrdine(numOrdine);
> dettord.setPrezzo(dettoff.getPrezzo());
> dettord.setQuantita(dettoff.getQuantita());
> dettord.setTotale(dettoff.getTotale());
>
> entityManager2.persist(dettord);
> dettord.setCodiceOrdine(ord);
> }
>
> entityManager2.getTransaction().commit();
> entityManager2.close();

'close()' should be in a 'finally' block.

>
> } catch (RollbackException rex) {
> rex.printStackTrace();
> entityManager2.getTransaction().rollback();
> entityManager2.close();
> }
>
>
> Would you have any advice?
>
> I hope you can help me. Thank you very much in advance!

The point of JPA is to give the application an object model of data. I don't
see that here.

--
Lew