Implement UserRepository

As mentioned earlier, we will use Hibernate to save data into a MySQL database. The JPA implementation of the Spring Data JPA is based on Hibernate.

The special part of the Spring Data JPA is that it significantly reduces the effort to write the repository by only requiring the developers to write repository interfaces, and it will generate the implementation automatically for us, which sounds perfect and very productive.

To use this autogeneration of the implementation feature that Spring Data JPA provides, we will need to change the UserRepository interface to the following:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
User findByEmailAddress(String emailAddress);
}

As you can see, we will need to apply the @Repository annotation to the interface and make it extend from Spring's JpaRepository or CurdRepository. We don't need the save() method in the original interface anymore because JpaRepository already has one. Besides the save() method, we also inherit a bunch of other methods, for example, saveAll(), getOne(), and findAll().

If we need to find users who registered yesterday, we can declare an API in the UserRepository interface like the following:

List<User> findByCreatedDateBetween(Date, Date);

Or, we can create the following method to find users by last name and sort by first name in descending order:

List<User> findByLastNameOrderByFirstNameDesc(String lastName);

The Spring Data JPA also supports pagination out of the box, for example, the following methods can find users by last name and return the paginated result:

List<User> findByLastName(String lastName, Pageable pageable);

The Spring Data JPA provides a list of query keywords that you can put into the method names. Other than that, you can apply the @Query annotation to a method to create a custom query, like the following:

@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);

Or, use a native query, like the following:


@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);

If this still cannot meet your requirements, you can create a custom repository interface with a custom implementation.

But, is this really a good approach? The answer to this question depends on how you want the Repository interfaces to look like. If you're comfortable with narrowing your method naming options to those keywords, using @Query to specify the query in the interface, or creating another Repository interface for custom queries, the autogeneration of the implementation can be quite productive. And you don't need to worry about doing a unit test of Repository interfaces, because Spring Data JPA provides a nice solution for that.

On the other hand, if you want your Repository interfaces to be clean and implementation neutral so that you can keep the freedom of switching to other implementations from Hibernate, such as MyBatis or Spring JDBC, you probably don't want to use Spring Data JPA the way described previously.

In TaskAgile, we want to keep the Repository interfaces clean and keep infrastructure related implementation out of our domain model. So, here is what we will do:

  • Keep the UserRespository interface as it is
  • Create a HibernateUserRepository implementation in the com.taskagile.infrastructure.repository package
  • Let the Spring Data JPA create the DataSource instance and the EntityManager instance for us, as well as setting up the connection pool; from there, we will implement those methods ourselves

Let's get started.

..................Content has been hidden....................

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