跳至主要内容

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.

评论

此博客中的热门博文

Build a Reactive application with Angular 5 and Spring Boot 2.0

I have created a post to describe Reactive programming supports in Spring 5 and its subprojects, all codes of this article are updated the latest Spring 5 RELEASE, check spring-reactive-sample under my Github account.
In this post, I will create a simple blog system, including:
A user can sign in and sign out.An authenticated user can create a post.An authenticated user can update a post.Only the user who has ADMIN role can delete a post.All users(including anonymous users) can view post list and post details.An authenticated user can add his comments to a certain post. The backend will be built with the latest Spring 5 reactive stack, including:
Spring Boot 2.0, at the moment the latest version is 2.0.0.M7Spring Data MongoDB supports reactive operations for MongoDBSpring Session adds reactive support for WebSessionSpring Security 5 aligns with Spring 5 reactive stack The frontend is an Angular based SPA and it will be generated by Angular CLI.
The source code is hosted on Github, …

Activating CDI in JSF 2.3

Activating CDI in JSF 2.3 When I upgraed my Java EE 7 sample to the newest Java EE 8, the first thing confused me is the CDI beans are not recoganized in Facelects template in a JSF 2.3 based web applicaiton, which is working in the development version, but in the final release version, they are always resolved as null. I filed an issue on Mojarra and discussed it with the developers from communities and the JSF experts.
According to the content of README, In a JSF 2.3 application, to activate CDI support, declaring a 2.3 versioned faces-config.xml and adding javax.faces.ENABLE_CDI_RESOLVER_CHAIN in web.xml is not enough, you have to declare @FacesConfig annotated class to enable CDI.
Here is the steps I created a workable JSF 2.3 applicatoin in Java EE 8.
Create a Java web application, this can be done easily by NetBeans IDE, or generated by Maven archetype, for exmaple.
$ mvn archetype:generate -DgroupId=com.example -DartifactId=demo -DarchetypeArtifactId=maven-archetype-w…

JSF 2.3:Websocket support

Websocket support One of the most attractive features is JSF 2.3 added native websocket support, it means you can write real-time applications with JSF and no need extra effort.
To enable websocket support, you have to add javax.faces.ENABLE_WEBSOCKET_ENDPOINT in web.xml.
<context-param> <param-name>javax.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name> <param-value>true</param-value> </context-param> Hello Websocket Let's start with a simple example.
@ViewScoped@Named("helloBean") publicclassHelloBeanimplementsSerializable { privatestaticfinalLoggerLOG=Logger.getLogger(HelloBean.class.getName()); @Inject@PushPushContext helloChannel; String message; publicvoidsendMessage() { LOG.log(Level.INFO, "send push message"); this.sendPushMessage("hello"); } privatevoidsendPushMessage(Objectmessage) { helloChannel.send(""+ message +" at &…