The previous blog post went in-depth on Java JPA, discussing the underlying classes and interfaces that make JPA work. This post is just about the contents of the video tutorials and therefore gives more idea about what to expect on the test.

Video 1 - Spring Data JPA

Enabling JPA

In pom.xml you add Spring JPA in the following way:

<dependencies>
 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
 </dependency>
</dependencies>

It resolves a lot of packages that together make JPA work. If JPA is found on the classpath, Spring will autoconfigure the following objects:

  • DataSource
  • EntityManagerFactoryBean
  • JpaTransactionManager

Using @EntityScan

By default, Spring scans for domain objects (“entities”) in the package where @EnableAutoConfiguration sits plus its subpackages. This is identical to the search for repositories. If you want Spring to scan at other locations, do @EntityScan("other.package")

Settings in application.properties

Many thing go automatically but there are some settings in application.properties that you might need. The following are discussed:

#application.properties

# With default, Hibernate will try to determine it. Recommended approach.
spring.jpa.database=default  

# How to deal with database and its schema. Default is:
#   Embedded database: create-drop
#   Non-embedded: none (do nothing)
# For production, do not set it at all (none)
# Options: validate | update | create | create-drop
spring.jpa.hibernate.ddl-auto=update 

# Show SQL being run in log, well-formatted
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format-sql=true

# Set Hibernate property 'xxx':
spring.jpa.properties.hibernate.xxx=???

Video 2 - Create Repositories

Two steps

To set it up, you need two things:

  • Create domain classes and annotate them with JPA annotations like @Entity, @Id, @Table etc
  • Create repositories by extending Repository interface or its children

Annotate a domain class

Example from video (btw this is a JPA, not a Spring thing):

@Entity  // makes class a persistent class
@Table(..)  // use if you want to have a name for the db table other han the class name
public class Customer {

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;  // key must be Long type
  private Date orderDate;
  private String email;

  // getters and setters
}

These annotations come from JPA and Spring utilizes them. As Spring Data works also with systems other than JPA that do not have their own annotations, like MongoDB, Neo4J or Gemfire, Spring has introduced custom annotations for them as well. They are not part of the course, but it illustrates the universal character of Spring Data.

Choose a Repository to extend

To create a repository, extend Repository<T, ID> or any of its children (might even be multiple of them). No annotations needed, Spring will create a proxy bean from it that can even be injected into another bean.

Repository is a marker interface, CrudRepository has crud methods included, PagingAndSortingRepository extends CrudRepository and has methods like Iterable, Page, findAll(Sort), findAll(Pageable), and JpaRepository extends PagingAndSortingRepository.

Sample repository

Here some valid code. Note that you never have to provide the method implementations. Also note that the names of methods follow a convention and will be translated to sql statements under the hood.

public interface CustomerRepository extends CrudRepository<Customer, Long> {  // Long is type of Id

   public Customer findFirstByEmail(String someEmail); 
   public List<Customer> findByOrderDateLessThan(Date someDate);
   public List<Customer> findByOrderDateBetween(Date d1, Date d2);

   Customer findFirstByEmailIgnoreCase(String email);  // case insensitive search

   @Query("SELECT c FROM Customer c WHERE c.email NOT LIKE '%@%'")
   public List<Customer> findInvalidEmails();

   @Query("select u from Customer u where u.emailAddress=?1")
   Customer findByEmail(String email);  // ?1 is replaced by method parameter.
}

The names of methods have elements like “findFirstBy”, “findBy”, “LessThan”, “Between” etc. To write your own query, use @Query and use the query language of the underlying product. The example here uses JPQL. You can use placeholders for the arguments of the method. Mainly used for more complex queries that would result in very long method names.

Find repositories

Spring Boot scans for repositories (all interfaces extending Repository or a child of it) in the package where @SpringBootApplication sits plus its subpackages.

If you want Spring Data to scan in other packages as well, do this:

@Configuration
@EnableJpaRepositories(basePackages="com.jan.repository")
public class CustomConfig{ ... }

Injecting repository as bean

As a proxy class bean is generated of the interface, and as this bean is available from the start, you can inject it in other beans, preferably in their constructor in the @Configuration class. This doesn’t require an extra annotation. Example:

 @Bean
 public CustomerService customerService(CustomerRepository repo){
     return new CustomerService(repo);
 }

<
Previous Post
JPA under the hood
>
Next Post
Spring Boot web application