JPAContainer - refresh() produces tons of selects

Hi,
I was sitting the whole night on this problem, and still couldnt solve it.
In my application i have a table set up with JPAContainer. I need to update this table at least every half minute. The polling i ve solved with the Refresher Addon. But with JPAContainer update I have stucked because of its performance. To minimize the range of possible problem indicators, i ve took the most simple entity class and populated 1 entry of it in the database. My Entity looks as following:

@RooJavaBean
@RooToString
@RooEntity
@RooSerializable
public class Locale {

	@Size(max = 6)
    private String localeKey;
}

My extended Table component:

public class TestTable extends Table {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -421902620415105156L;

	private JPAContainer<Locale> ticketsContainer;

	private final static String[] visibleColumns = { "localeKey"};
	
	public TestTable() {
		super();

		EntityManager entityManager = EntityProviderUtil.getInstance()
				.getEntityManager();

		ticketsContainer = JPAContainerFactory.makeReadOnly(Locale.class,
				entityManager);


		setContainerDataSource(ticketsContainer);
		
		
		setWidth("100%");

		setSelectable(true);
		setImmediate(true);

		setSortContainerPropertyId("localeKey");
		setSortAscending(false);
		setVisibleColumns(visibleColumns);

		setColumnHeaders(new String[] { "localeKey" });


	}
	
	public void update() {
		ticketsContainer.refresh();
	}

}

My Application init():

@Override
	@Transactional
	public void init() {
		LOG.debug("start initializing the vaadin application");
		Window window = new Window("test table");
		Locale locale = new Locale();
		locale.setLocaleKey("de_DE");
		locale.persist();
		final TestTable table = new TestTable();
		window.addComponent(table);
		Refresher refresher = new Refresher();
		refresher.setRefreshInterval(10000);
		refresher.addListener(new RefreshListener() {

			@Override
			public void refresh(Refresher source) {
				table.update();
			}
			
		});
		window.addComponent(refresher);
		super.setMainWindow(window);
		
	}

And now the sql preparedstatement log.
The funny thing is, the first log isnt so awesome like the following request logs.
This is the first request log:

[EL Fine]
: 2012-01-28 10:33:11.097--ServerSession(1097828000)--Connection(1924646449)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:33:11.109--ServerSession(1097828000)--Connection(1538527370)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT COUNT(id) FROM LOCALE
[EL Fine]
: 2012-01-28 10:33:11.114--ServerSession(1097828000)--Connection(921720151)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id AS a1 FROM LOCALE ORDER BY LOCALEKEY DESC, id ASC LIMIT ? OFFSET ?
	bind => [150, 0]

This request happened 2 minuteslater:

[EL Fine]
: 2012-01-28 10:35:11.097--ServerSession(1097828000)--Connection(380750143)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.105--ServerSession(1097828000)--Connection(1025036841)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.109--ServerSession(1097828000)--Connection(1783266943)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.111--ServerSession(1097828000)--Connection(753864924)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.114--ServerSession(1097828000)--Connection(1420938648)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.117--ServerSession(1097828000)--Connection(1814754830)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.12--ServerSession(1097828000)--Connection(773797778)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.122--ServerSession(1097828000)--Connection(404192466)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.125--ServerSession(1097828000)--Connection(2065389480)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.128--ServerSession(1097828000)--Connection(1832585859)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.132--ServerSession(1097828000)--Connection(1020708261)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id, LOCALEKEY, version FROM LOCALE WHERE (id = ?)
	bind => [1]

[EL Fine]
: 2012-01-28 10:35:11.134--ServerSession(1097828000)--Connection(659105842)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT COUNT(id) FROM LOCALE
[EL Fine]
: 2012-01-28 10:35:11.136--ServerSession(1097828000)--Connection(1751455376)--Thread(Thread["http-bio-9090"-exec-9,5,main]
)--SELECT id AS a1 FROM LOCALE ORDER BY LOCALEKEY DESC, id ASC LIMIT ? OFFSET ?
	bind => [150, 0]

And this is all because of the call of the refresh method!
My database table still contains only 1 Locale entry.
I ve tried to use JPAContainer with Hibernate and EclipseLink (2.2.0). The result is the same.
DBMS is PostGreSQL
I use Spring Roo in my Application.
My EntityManager I get over the @PersistenceContext. I ve never had problems with that before.
Vaadin 6,7,4
JPAContainer 2.0.0

Is there maybe any other possibility to synchronize my table with the database?

PS. This was a very simple example.
Can you imagine how many selects it generates if I use more complex entities and multiple entries (for example 10)?
One request with the first refresh() call took 0,8 seconds for its job and generated nearly ~100 selects :smiley:

It seems, that the refresh() Method of the JPAContainer was not designed for this purpose. What is it good for then? For a new Vaadin Developer it can be a sneaky trap if he sees this method with auto-completion.
The solution for my problem i ve found on:
https://vaadin.com/forum/-/message_boards/view_message/548481

with kind regards

Vlad

Vladislav,

Well then, for what is the refresh() method designed for? I have tables that contain appr. 1000 rows each. When calling container.refresh() or even container.refreshItem() it triggers numerous selects and takes seconds before completing, just like you described :slight_smile:

Analysing the JPAContainer code I see that these numerous selects (all for the same entity) are coming because every call to container.getItem() returns a NEW instance which is stored as a “weakreference” in the container. It seems that getItem() always fetches the entity through the entityprovider (entityPrrovider.getEntity()) and returns it as a new JPAContainerItem. Even though I have a caching entity provider, every call to entityPrrovider.getEntity() seems to generate a select statement on the database. So in short, calling container.getItem x times in a row results in x weak references.

Following this explenation, when “refreshing” an item from the container (using container.refreshItem()) one select is triggered for each weak reference, hence the numerous selects!

Can somebody please explain to me why container.getItem cannot work with only one instance which is constantly being updated with the result from entityProvider.getEntity()? Or am i doing something else wrong since I would expect that entityProvider.getEntity() should not go to the db every time since I am using a cached entity provider!

I hope anybody can shed some light on this problem! Any comments are welcome!

Regards,

Kim

PS. for people looking to “just” refresh their jpacontainer bound table, f.e. on a button click, look at my solution that I described in a different topic:
https://vaadin.com/forum/#!/thread/542450/7571184

Kim,

I have the same problem, a big table with JPAContainer, at this table, I can delete records but when I use refreshItem() to refresh the item that has been deleted, take a lot of time to do the operation. if I debug this operation, I can see tons of operations that are equals to the previous, so what is the solution?

I hope as Kim anybody can help us to fix this,

Regards,

Xavi.

Hi, the solution is to
stop using JPAContainer
. Seriously, you’ll be better off if you’d create a simple service class via you just access your JPA entities as lists of objects. This way you have complete control on you queries and better transaction handling. JPAContainer is handy for very simple cases to list stuff from database, but for any non-trivial application I’d suggest to have a different approach. And once you have your service layer set up (which is super efficient with
Spring Data
or
DeltaSpike Data
), using them is actually easier than using the JPAContainer.

cheers,
matti

Hi,

I can confirm this. Spring Data rules!

Regards,

Kim

Hi,

And SQLContainer is a nice option?

Regards,

Xavi.

No, don’t think about Container’s at all is the best thing you can do for your applicaiton. Created a service class via you do your DB access (with JPA or whatever you use). Then just use lists of those objects in your application. For example something like this:
https://github.com/mstahv/jpa-invoicer/blob/master/src/main/java/org/example/backend/service/ContactFacade.java

That is also using DeltaSpike Data, but you can use raw JPA as wall. Having the service class there is the most essential thing. Then you are in control what happens at persistency layer.

cheers,
matti