26
Easy Data with Spring-Data JPA Miya W. Longwe, Tech Lead, Staples Inc. January 07, 2014 Java Meetup Group, Cambridge, MA , USA

Easy Data With Spring Data Jpa 140623104541 Phpapp01

Embed Size (px)

DESCRIPTION

Spring data

Citation preview

Project Status

Easy Data with Spring-Data JPA

Miya W. Longwe, Tech Lead, Staples Inc.

January 07, 2014

Java Meetup Group, Cambridge, MA , USA

Agenda

Java DB Access Ordeal

Enter Spring-Data

Spring-Data JPA Features

Code Demo

Q and A

Java DB AccessThe Developers Holy Pilgrim!

Application Domain

Domain driven design has become a ubiquitous approach to tackle complex problem domains and build a rich object model.

Implementing a data access layer of an application has been cumbersome for quite a while.

Too much boilerplate code has to be written.

Code to execute simple queries as well as perform pagination, auditing, etc

Java DB Access AccessorInterface

public interface CustomerService {

Customer findById(Long id);

Customer save(Customer customer);

List findAll();

List findAll(int page, int pageSize);

...

}

Java DB Access The Boilerplate Code

/**

* Plain JPA implementation of {@link CustomerService}.

*

* @author Miya W Longwe

*/

@Repository

@Transactional(readOnly = true)

public class CustomerServiceImpl implements CustomerService {

@PersistenceContext

private EntityManager em;

@Override

public Customer findById(Long id) {

return em.find(Customer.class, id);

}

@Override

public List findAll() {

return em.createQuery("select c from Customer c", Customer.class).getResultList();

}

}

Java DB Access The Story

JPA handles mechanics of ORM

The catch:

You are responsible for accessor boilerplate code

Using direct JDBC?

More boilerplate code (think DAO layer)

What about Spring support?

Makes things better (JdbcTemplate)

Spring-Data eases the pain further

Spring-Data to the Rescue!

Spring-Data

Uses the Repository abstraction for data access

Automation of data access boilerplate code

Reduces level of efforts for accessor code

Support for multiple data stores including JPA Key-Value, column, document, graph data stores(Redis, Mongo, Neo4j, HBase) Hadoop / HDFS Others

Spring-Data JPA Workflow

Define an Entity Class

Define a Repository interface with data accessor methods

Then see you gator!

Define Your Entity

/**

* An entity class which contains the information of a single person.

* @author Miya W. Longwe

*/

@Entity

@Table(name = "persons")

public class Person {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private Long id;

@Column(name = "creation_time", nullable = false)

private Date creationTime;

@Column(name = "first_name", nullable = false)

private String firstName;

@Column(name = "last_name", nullable = false)

private String lastName;

@Column(name = "modification_time", nullable = false)

private Date modificationTime;

...}

Define The Repository Interface

You provide a Java interface

Attach an entity type along with key type

CRUD/data accessor method signatures

Spring-Data can automatically derive proper JPQL

In simpler cases, no additional code required

Queries are derived from method signatures

Repository Interface

* Specifies methods used to obtain and modify person related information

* which is stored in the database.

* @author Miya W. Longwe

*/

public interface PersonRepository extends JpaRepository {

}

No More Boilerplate Code

It goes away (sort of) *

Spring-Data framework derives and attaches JPQL (or specified query) at load-time

Spring-Data Features

Provided Repositories

Spring-Data JPA provides two repositories

CrudRepository

Long list of standard CRUD operations provided

findOne(), findAll(), save(), delete(), exists(), etc

PagingAndSortingRepository

Derived from CrudRepository

Provides paginated repository access methods

Configure Spring Framework

Specify your repository locations for scanning

Spring will create proxy instances for repositories

Spring-Data Query Generation

Derived from method signatures

Parses method names for attributes and keywords

Uses method parameters as query params

public interface UserRepository extends CrudRepository {

List findByEmailAddressAndLastname(String emailAddress, String lastname);

}

Select c from Customer where c.emailAddress = ?1 and c.lastName = ?2

Spring-DataMethod Name-to-JPQL Mapping

Method NameGenerated JPQLfindByXxxAndYyy(aaa, bbb)... where t.xxx = ?1 and t.yyy = ?2findByXxxOrYyy(aaa, bbb)... where t.xxx = ?1 or t.yyy = ?2findByXxxStartingWith(aaa)('%' appended to param value)findByXxxNot(aaa)... where t.xxx ?1findByXxxIn(Collectionaaa)...where t.xxx in ?1

---and many more!

Spring-DataFurther Property Parsing Features

-Traversal can reach into nested properties

-Will do best effort using camelCase

-You can delineate properties using _

}

@Entity

public class User {

private ZiCode zicode;

--}

}

public interface UserRepository extends CrudRepository{

...

User findByAddress_ZipCode(ZipCode zipCode);

@Query Use Your Own Query

You don't like the derived query or want to do

something fancier?

Use @Query notation to provide your own

Support both JPQL or native SQL

Still provides automatic proxy implementation

public interface UserRepository extends CrudRepository{

...

@Query("select u from User u where u.firstname = ?1")

List findByFirstname(String firstname);

@Query(value="SELECT FROM USERS WHERE EMAIL_ADDRESS = ?1" nativeQuery=true)

User findByEmailAddress(String email);

...

@Query Named Params

Spring-Data JPA will use position for parameter binding

You can also use named params instead

interface UserRepository extends CrudRepository{

...

@Query("select u from User u where u.firstname = :name or u.lastname = :name")

List findByFirstnameOrLastname(@Param("name") String name);

...

}

Result Pagination

Seamlessly provides support for result set pagination via Pageable Interface

Define repository method with Pageable

Call method with PageRequest class (or define your own)

public interface ProductRepository extends CrudRepository{

...

Page findAll(Pageable pageable);

...

}

class ProductService {

Pageable pageable = new PageRequest(1, 20);

Page page = repository.findByDescriptionContaining(pageable);

}

Custom Repositories

When Spring-Data JPA derived queries are not

enough or you need additional logic

Provide your own repository implementation

A bean that lives in Spring Context

interface UserRepositoryCustom {

List myCustomBatchOperation();

}

class UserRepositoryImpl implements UserRepositoryCustom {

@PersistenceContext

private EntityManager em;

public List myCustomBatchOperation() {

CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery(User.class);

return em.createQuery(criteriaQuery).getResultList();

}

}

Transaction Support

Repository classes are transactional by default

Reads are made readOnly

Other methods are @Transactional by default

Ability to override by providing your own

@Transactional demarcation

public interface UserRepository extends CrudRepository{

...

@Transactional(timeout=10)

@Modifying

@Query("update User u set u.firstname = ?1 where u.lastname = ?2")

User fixFirstNameByLastName(String firstname, String lastname);

...

}

Code Demo