跳至主要内容

Spring Data: a new perspective of data operations


Spring Data: a new perspective of data operations

Spring Data is an umbrella project from SpringSource Community, which tries to provide a more generic abstraction of data operations for RDBMS, NoSQL and cloud based data and indexing service.

The status of Spring Data

Spring Data is evolved out of an open source project named Hades, which mainly provided a GenericDao interface for Hibernate/JPA. Spring Data extends the core concept to other domains and APIs.
According to the Spring data project page, currently the official Spring Data project provides the following sub modules.
  • JPA
  • REST
  • JDBC Extensions
  • Apache Hadoop
  • GemFire
  • Redis
  • MongoDB
  • Neo4j
  • Commons
Besides, there are some community based projects available.
  • Spring Data Solr , Spring Data repositories abstraction for Apache Solr
  • Spring Data Elasticsearch , Spring Data repositories abstraction for Elasticsearch
  • Spring Data Couchbase , Spring Data repositories abstraction for Couchbase
  • Spring Data FuzzyDB , Spring Data repositories abstraction for FuzzyDB
Spring Data Commons(Maven archetype id is spring-data-commons) is the base for other modules.

Overview of Spring Data Commons

The most attractive feature of Commons is it provides a genericRepository interface and two extended variants for CRUD operations(CurdRepository) and pagination(PagingAndSortingRepository) purposes which can be used in all other sub modules.
public interface Repository<T, ID extends Serializable> {

}
Repository is an empty interface which can accept a domain class and a serialable primary key as type parameters. CurdRepository extendsRepository and adds some common methods for CRUD operations,PagingAndSortingRepository extends CurdRepository and provides pagination and sort capability.
You can select any one of them to extend in your project. But in the real world project, you should extend the one in the certain sub module, which provides more features. For example, if you are using Spring Data JPA, it is better to create your Repository to extendJpaRepository which is extended from PagingAndSortingRepository.
When you use any sub modules, you must add Spring Data Commons as project dependency, and specify the package which includes the your Repository in Spring configuration. Spring Data will discover theRepository beans automatically.
For example, if you are using Spring Data JPA, you have to add the following configuration
<jpa:repositories base-package="com.hantsylabs.example.spring.jpa"></jpa:repositories>
or use @EanbleJpaRepositories via Spring java configuration
@EnableJpaRepositories(basePackages = { "com.hantsylabs.example.spring.jpa" })
to activate your own repositories.
NOTE: If you are using the Repository API in other data storage, such as MongoDB, you should include Spring Data Mongo dependency in project classpath and activate it via mongo namespace.
Up to now, you can not see any magic of the Repository API. Keep patient!

Query by convention

Assume there is a JPA entity class defined as:
@Entity
public class Conference {
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "id")
 private Long id;

 @Version
 @Column(name = "version")
 private Integer version;

 @NotNull
 private String name;

 @NotNull
 private String description;

 @NotNull
 @Temporal(TemporalType.TIMESTAMP)
 @DateTimeFormat(style = "M-")
 private Date startedDate;

 @NotNull
 @Temporal(TemporalType.TIMESTAMP)
 @DateTimeFormat(style = "M-")
 private Date endedDate;

 @NotNull
 private String slug;

 //getters and setters ...
} 
And declare an Repository interface for Conference class like this:
public interface ConferenceRepository extends 
  PagingAndSortingRepository<Conference, Long>{

 Conference findBySlug(String slug);

 Conference findByName(String name);

 Conference findByDescriptionLike(String desc);

 Conference findByStartedDateBetween(Date started, Date ended);

    //...
}
Now you can call them directly in your Services or Controllers, yes, you do not need to implement them at all, Spring Data prepare the query and get the results for you.
When you are using JPA, findBySlug are equivalent to the following JPQL.
from Conference where slug=?1
When you are using Mongo, you do not need the JPA entity declaration, and the method will be converted into Mongo specific expression.
In this example, the methods return a single object, in most of case, they should return a Collection of object.
Ideally, the above logic are available in all Spring Data sub modules, but the method naming convention maybe some difference among the specific data storage.

Common annotations

If you have used Spring Data in projects, you will find it try to provide a series of common annotations for all data storage. Such as, @Id, @Version, @Persistent, @Transient, @PersistenceConstructor, etc. Please explorer the package org.springframework.data.annotation for more details.
But currently they behaves a little different in the sub modules, they can not be exchanged with the ones in the existing API, such as JPA API.
Personally, I do not think this is a good idea. If you are keep an open on the world outside of Spring, you will find there are some better solutions.
EclipseLink and Hibernate are starting to support NoSQL in the new version, but base on JPA API(and some extension), DataNucleus is a mature solution for multi storage(RDBMS, NoSQL, even filesystem), but it supports standard JPA, JDO API, and it is also used in Google App Engine for Java developers. Obviously, if you select these solutions, the learning curve to switch between different storage will be decreased dramatically.

Audit API

Commons provides some interfaces(such as Auditable, Persistable,AuditorAware) and annotations(@CreatedDate, @CreatedBy,@LastModifidedBy, @LastModifiedDate) to developers to add some simple audit capabilities for your domain classes.

Pagination capability

Pagination is a basic feature for web application, some APIs in Commons are ready for this purpose.
The PagingAndSortingRepository provides some methods which can accept a Pageable object as parameter and return a Page object.
Pageable interface which will be passed in includes the essential data for pagination, such page size, offset, sort field and direction. There is a default implementation class PageRequest provided in Commons.
Page class wraps all information of the pagination query result, the collection of result data, the count of all data, etc.
Commons provides some pagination integration with Spring MVC.
We will discuss these in details in future post.

评论

此博客中的热门博文

AngularJS CakePHP Sample codes

Introduction This sample is a Blog application which has the same features with the official CakePHP Blog tutorial, the difference is AngularJS was used as frontend solution, and CakePHP was only use for building backend RESR API. Technologies AngularJS   is a popular JS framework in these days, brought by Google. In this example application, AngularJS and Bootstrap are used to implement the frontend pages. CakePHP   is one of the most popular PHP frameworks in the world. CakePHP is used as the backend REST API producer. MySQL   is used as the database in this sample application. A PHP runtime environment is also required, I was using   WAMP   under Windows system. Post links I assume you have some experience of PHP and CakePHP before, and know well about Apache server. Else you could read the official PHP introduction( php.net ) and browse the official CakePHP Blog tutorial to have basic knowledge about CakePHP. In these posts, I tried to follow the steps describ

JPA 2.1: Attribute Converter

JPA 2.1: Attribute Converter If you are using Hibernate, and want a customized type is supported in your Entity class, you could have to write a custom Hibernate Type. JPA 2.1 brings a new feature named attribute converter, which can help you convert your custom class type to JPA supported type. Create an Entity Reuse the   Post   entity class as example. @Entity @Table(name="POSTS") public class Post implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="ID") private Long id; @Column(name="TITLE") private String title; @Column(name="BODY") private String body; @Temporal(javax.persistence.TemporalType.DATE) @Column(name="CREATED") private Date created; @Column(name="TAGS") private List<String> tags=new ArrayList<>(); } Create an attribute convert

Auditing with Hibernate Envers

Auditing with Hibernate Envers The approaches provided in JPA lifecyle hook and Spring Data auditing only track the creation and last modification info of an Entity, but all the modification history are not tracked. Hibernate Envers fills the blank table. Since Hibernate 3.5, Envers is part of Hibernate core project. Configuration Configure Hibernate Envers in your project is very simple, just need to add   hibernate-envers   as project dependency. <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-envers</artifactId> </dependency> Done. No need extra Event listeners configuration as the early version. Basic Usage Hibernate Envers provides a simple   @Audited   annotation, you can place it on an Entity class or property of an Entity. @Audited private String description; If   @Audited   annotation is placed on a property, this property can be tracked. @Entity @Audited public class Signup implements Serializa