The domain model

The following sections show how to implement CRUD views using two different designs: a Grid in editable mode, and modal windows. But first, we need to implement a domain model. We'll use JPA and repository classes, which we explained in the previous chapters. The domain model consists of simple classes to model a role-based schema: Userand Role. It also includes the corresponding UserRepository and RoleRepository classes.

Let's start with the simplest of the classes, Role. The following is the full implementation of this class:

@Entity
@Data
public class Role {

@Id
@GeneratedValue
private Long id;

private String name;

private Boolean module1Authorized;

private Boolean module2Authorized;

@Override
public String toString() {
return name;
}
}

Besides the usual JPA configuration stuff (such as the @Entity, @Id, and @GeneratedValue annotations), the most interesting thing in this class is that there are no getters and setters. Nevertheless, getters and setters for each Java field in the class exist! This is thanks to Project Lombok, a library that reduces the amount of boilerplate code needed in Java programs. Lombok generates code at the class level. In the previous class, we used the @Data annotation in order to tell Lombok to generate getters and setters, and toStringequals, and hashCode methods. Since the toString method generated by Lombok doesn't fit our requirements, we override it and provided a custom one.

In order to use Lombok, you need to install it in your IDE, and add the dependency to the pom.xml file:

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>

You can find installation instructions for IntelliJ IDEA, NetBeans, Eclipse, and other IDEs at: https://projectlombok.org. After installing Lombok, you'll be able to use autocomplete and any other features of your IDE in order to use the generated code, even when you don't see it in the Java class. For example, the following screenshot shows IntelliJ IDEA suggesting the generated getName method when using the autocomplete feature:

You can use your own implementations for the getters, setters, equals, and hashCode instead of using Lombok. Most IDEs, if not all of them have features to generate these methods at the source code level; however, Lombok source files become much shorter, making them easier to maintain in most cases. @Data is not the only useful annotation offered by Lombok. See the documentation at https://projectlombok.org for more information about its features.

The following is the implementation of the User class, which uses Lombok as well:

@Entity
@Data
public class User {

@Id
@GeneratedValue
private Long id;

private String firstName;

private String lastName;

private String email;

private String password;

private boolean blocked;

@ManyToMany(fetch = FetchType.EAGER)
private Set<Role> roles;

@ManyToOne
private Role mainRole;
}

Notice the @ManyToMany annotation in the roles field. What's the difference between @ManyToMany and @OneToMany? The -ToMany part means that every User can be associated with many Role objects. The @Many- part means that every Role can have many User instances. If @OneToMany was used, the @One- part would mean that every Role can be associated with only one User, which is clearly not what we want in this model.

Why does the @ManyToMany annotation specify FetchType.EAGER for the fetch strategy? Hibernate uses Fetch.LAZY by default, which might cause a LazyInitializationException. Lazy fetch can be useful if you want to load the data when it is actually needed. This, however, requires an open Hibernate session when the collection is accessed. In a web environment, the session is usually closed after the request is handled. Since we need to show Role data in the views, the best approach is to eagerly fetch the data. A common practice in many applications is to use the Open Session in View pattern; however, this might as well be considered an anti-pattern. Always consider using DTO projections instead of the Open Session in the View pattern. For a more detailed discussion about this topic, visit https://vladmihalcea.com/2016/05/30/the-open-session-in-view-anti-pattern.

The last part of the domain model is the repository classes. For the RoleRepository class, we only need a method to find all the Role objects, and another to save a new one, as shown in the following snippet of code:

public class RoleRepository {

public static List<Role> findAll() { ... }

public static Role save(Role role) { ... }
}

And for completeness, the following are the methods in the UserRepository class:

public class UserRepository {

public static List<User> findAll() { ... }

public static User findById(Long id) { ... }

private static User getById(Long id, EntityManager em) { ... }

public static User save(User user) { ... }

public static void delete(User user) { ... }
}
The actual implementation of the methods is omitted here for simplicity, but you can find the complete source code of this chapter's example in the Data-centric-Applications-with-Vaadin-8chapter-07 Maven project of the source code that accompanies this book.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset