Vaadin 8 + spring-boot-starter-data-jpa + lazy loading

Dear all,

I’ve been looking through the documentations and forums, but couldn’t find an answer to the following question:

How can I make Vaadin always work under a Session (JPA) - I have some entities with lazy load attributes and, so far, the only way to work with them has been through forcing an eager loading of these properties. I’m using Spring’s CrudRepository for the backend.

Create a service for your CRUD entities (a service for each repository).
Annotate the service with @Transactional(readonly = true) to make every method capable of operating correctly on the database.
Annotate methods that write to the DB with @Transactional(readonly = false).
When you load an entity from you domain, store the data you’ll send to you users in a DTO (data transfer object). This is a non entity object with only part of the data contained in the entire entity. Give the DTO the entity id so you can trace back from how the DTO is from.
Load your lazy data when assembling the DTOs inside your service class.
win win win.

Hi Lucas, thanks for answering! My question is exactly to prevent this manual early load. Currently I’m early-loading the required objects in JPA, thus I don’t need the DTOs. My interest would be to load this data on demand, thus reducing the load on the database on a first moment and keeping the system code cleaner, without aditional classes such as DTOs.

Dear all,

just to register. Ended changing my persistence layer from Hibernate to EclipseLink, since it support lazy loading by automatically opening a session as needed (through Weaving).

Kind regards

You can use lazy loading with you UI components when you don’t need all the data. You can paginate your queries, you can create streaming providers… you can do lots of things.

I have, for example, a user combo box that searches all users in the database. It works by creating a custom CallbackDataProvider that provides UserDTOs (you can provide your entities here, though its a bad practice). The provider is quite simple to implement:

CallbackDataProvider<UserDto, String> provider = new CallbackDataProvider<>(
			q ->  {
				if(!q.getFilter().isPresent()) return userService.findAll().stream();
				List<UserDto> results = userService.findByEmailStartsWithIgnoreCase(q.getFilter().orElse(""));
			q -> {
				if(!q.getFilter().isPresent()) return (int) userService.count();

				return (int) userService.countByEmail(q.getFilter().orElse(""));

That find is filtered and implemented to load only a few hundred at a time.

Lazy loading for grid:

Paginated queries are something you’ll have to implement if using DTOs and Hibernate.

I know you switched to EclipseLink, but since this is a topic that I struggle A LOT with, I wanted to leave this answer here for future people that like me, searched the entire world and found nothing.

Good luck with your app! :wink: