Upload
pablo-sene
View
236
Download
1
Tags:
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