Edits in JPAContainer don't go to DB

Hi,

I have the following setup: JPAContainer, that is the source for a table, and a form for editing the items.
Problem: Editing an entity updates the table, but not the DB!

What might be wrong here?


//declaration
JPAContainer container = JPAContainerFactory.makeJndi(Customer.class);
Table table = new Table();
table.setContainerDataSource(container);
BeanFieldGroup<Customer> binder = new BeanFieldGroup<Customer>(Customer.class);

//edit a table item:
BeanItem<Customer> beanItem = new BeanItem<Customer>(customer);
binder.setItemDataSource(beanItem);

//save edited item
binder.commit();
container.commit();
//here I can see the changes populated to the table, but NOT to the DB

//when I call refresh on the container, the table shows the content in db, thus the unchanged entity. WHY?
container.refresh();

If you edit a bean through a BeanItem, its data is NOT updated automatically to the entity nor the JPAContainer.

There’s two basic patterns:

[list=1]

[]
Get the item to edit from the JPAContainer (or the table bound to it) with getitem() and bind a FieldGroup to that. This works for editing items, but the problem is that if you want to edit a new item, you first need to add an empty item to the container and then edit it. On cancel, you can discard the addition to the container.
[
]
On add, create a BeanItem to edit and on commit add the bean to an entity which you add to the JPAContainer (or to the EM and call refresh() on the container). On edit, edit the EntityItem which you get with getItem() from the JPAContainer. See a bit old example
CarView.java
(for Vaadin 6 but the pattern is similar with Vaadin 7), especially the editFill() and how it’s called in case of new or old item.

[/list]Below is a more recent example of pattern #1:

// Let's have some data created with pure JPA
EntityManager em = JPAContainerFactory.
    createEntityManagerForPersistenceUnit("book-examples");
em.getTransaction().begin();
em.createQuery("DELETE FROM Person p").executeUpdate();
em.persist(new Person("Jeanne Calment", 122));
em.persist(new Person("Sarah Knauss", 119));
em.persist(new Person("Lucy Hannah", 117));
em.getTransaction().commit();

// Create a persistent person container
final JPAContainer<Person> persons =
    JPAContainerFactory.makeBatchable(Person.class, "book-examples");
persons.setBuffered(true);
persons.setAutoCommit(false);

// Bind it to a component
final Table personTable = new Table(null, persons);
personTable.setVisibleColumns(new String[]{"id","name","age"});

final Form editor = new Form();
editor.setFormFieldFactory(new FieldFactory());
editor.setBuffered(true);

final Panel editorPanel = new Panel("Editor");
editorPanel.setVisible(false);
editorPanel.setContent(editor);

final Button add = new Button("Add New");
add.addClickListener(new ClickListener() {
    @Override
    public void buttonClick(ClickEvent event) {
        persons.createEntityItem(new Person(null, 0));
        Object itemId = persons.addItem();
        add.setData(itemId);
        editor.setItemDataSource(persons.getItem(itemId));
        editorPanel.setVisible(true);
    }
});

Button save = new Button("Save");
save.addClickListener(new ClickListener() {
    @Override
    public void buttonClick(ClickEvent event) {
        editor.commit();
        persons.commit();
        editor.setItemDataSource(persons.getItem(add.getData()));
        // persons.refresh();
    }
});
editor.getFooter().addComponent(save);

Button cancel = new Button("Cancel");
cancel.addClickListener(new ClickListener() {
    @Override
    public void buttonClick(ClickEvent event) {
        editor.discard();
        persons.discard();
        editorPanel.setVisible(false);
    }
});
editor.getFooter().addComponent(cancel);

We have the same problem… calling the

commit()

does not updating the database… how is that ?

Hi,

I’d suggest not to use JPAContainer at all (or only use it for listing stuff from database). Instead I’d suggest to create DAO or some service class for which you’ll pass your entity form UI code when user has clicked save.

Check out e.g.
this example app
. If you are afraid of the small overhead of writing the JPA related code, check out tools like
Spring Data and DeltaSpike Data
, which will make it trivial to write simple repository classes.

cheers,
matti