I'm trying to wrap my head around JPA and have learned quite a bit. JPA is a java specification and providers implement this spec. I Understand that part.
What I don't understand is how Spring Data comes into the picture. Is Spring Data also a provider like Hibernate or OpenJPA? If not, what is it? How does Spring Data "make things easier"?
The Spring Data project in general is an umbrella project with the following mission statement:
… provide a familiar and consistent Spring-based programming model while retaining store-specific features and capabilities.
So we approach the persistence space in general not only relational data access through JPA. The important piece here is two fold:
Programming model instead of generic API
Support for store specific features
As the data access space is so diverse these days, trying to approach all of the stores with a single unifying API is doomed to fail. You'd end up with a least common denominator that hides away the store specific parts - in times where you selectively choose a particular store because of it's specifics. Abstracting those away totally subverts this. Especially trying to use JPA is wrong in our opinion as it's deeply tied to relational concepts (#Table, joins, transactions) by definition.
Still, you don't want to work with completely different APIs, don't wanna be lost in store differences if you work with multiple ones or switch from one project to another. Spring has traditionally helped in that regard by embracing a consistent programming model, that features abstractions that work the same way but are still specific to a particular technology. For example, JDBC and JMS are completely different technologies. Spring offers both a JdbcTemplate as well as a JmsTemplate that cover the same responsibilities (resource management and exception translation) and lower the learning curve when moving from working with JDBC to JMS or vice versa.
Spring Data picks up on that by exposing store-specific functionality through abstractions that Spring developers know. I already mentioned the template, but that also includes general configuration mechanisms (XML namespaces, using DI and AOP etc.).
Repositories
The very top layer of this programming model is the repository abstraction. In its core, it significantly simplifies the development of data access layers by letting you avoid to write more implementation code than strictly necessary. It provides CRUD functionality out of the box, pagination as well as declarative query methods.
Assume a Customer domain class. Enabling persistence for it is just a matter of declaring a repository interface like this:
interface CustomerRepository extends PagingAndSortingRepository<Customer, Long> {
List<Customer> findByLastnameContaining(String lastname);
}
Now it's a matter of configuration (and domain class mapping) to be able to create an instance of this interface and use it from a client. PagingAndSortingRepository includes basic CRUD functionality as well as stuff like Page<Customer> findAll(Pageable pageable) (so page-by-page access). As you can see, we also support a query derivation mechanism to avoid needing to write any implementation code for simply queries. For more complex ones, we allow the manual declaration (e.g. using #Query on the method) or even the manual implementation if necessary.
A neat side-effect here is, that by a flip-switch in the configuration you could use the same repository interface to persist Customer instances into a MongoDB. That doesn't mean we recommend to blindly move from one store to another as the stores usually require the data model to be adapted to work efficiently. However it allows developers to quickly switch between projects working with different stores as the repositories just work the same way (implementing the programming model over common API approach).
JPA specifics
Spring Data JPA is actually a thin layer implementing the repository abstraction plus a few other bells and whistles. So we're not replacing persistence providers but actually leverage them through the API, even mitigating some of the quirks and differences between individual JPA providers.
Think of Spring Data as a way to support JPA and many other persistence models in a manner that is transparent to your own code. Spring Data makes it easier for you to manipulate more types of data source systems in a unified interface. Without Spring Data, you would need to introduce more adapters in your code, each time you would have to deal with extra logic.
spring-data JPA is not a JPA provider. It is a library / framework that adds an extra layer of abstraction on the top of our JPA provider(Hibernate/TopLink). If you are using Spring Data in your project, you are not going to write most of the low level data access operations like writing SQL query, DAO classes etc.
But you must have a JPA-Provider (Hibernate, Toplink etc) to implement spring-data-jpa.
Related
I'm developing a web application with Spring MVC, Spring Data JPA and Hibernate, the data access part is taken care of by the repositories provided by Data JPA
However, I'm planning to have a generic service layer (atleast for the common operations), is it a good practise? Or is it advised to not generalise it?
If part of you application will consist of repeating same actions on different objects, it can make sense to have a generic abstract parent class for common operations.
You will have to decide if the gain in de-duplication of code is worth the complexity of the generic. There is no general rule ...
If your app is simple (mostly CRUD) operations then you can access your Repository classes directly.
If you have additional server-side business logic that needs to be applied to data or if you need to orchestrate multiple data access calls together then adding a Service layer would be appropriate.
Here is my problem. I am using Play2 Framework right now and it's providing me with Ebean as my default ORM product. I know Java fairly well and decide to write a website using Java, but I also want to learn Go, and ultimately change my websites' backend codes to Go (Go's framework Revel). I know my data will still be there, but I will have to use a different ORM product to rewrite all the models. Will this cause a problem even though I maintain the same exact database structure?
It depends on what's your definition of 'problem'.
ORM frameworks provides facility to map database information (relational data) into OOP object. Variation exists between ORM frameworks as to what DBMS they support, default naming rule when mapping table/column name to class/field, update cascading, transaction management, cache management, SQL translation etc.
You can keep your database schema and map it using different ORM, above is just some problem you might / not encounter along the way
I'm trying to find a good way to implement a generic search API in Java that will allow my users to search the backend repository without needing to know what that backend technology is, and so that if in the future we switch vendors I can reimplement the underlying logic without needing to recode the API. The repository underneath could be a relational database or a document store like SOLR, CouchDB, MongoDB, etc... It would need to support all the typical search requirements such as wildcards, ranges, bitwise operators, and so on.
Are there any standard ways of approaching this problem?
Would JPA be my best bet? Would it do everything I need it for, including non-relational databases?
Thanks in advance!
What you need is a ORM framework like Hibernate, if you go for JPA, you need to re-invent a lot of wheel.
using Hibernate you can write the business logic for searching the backend database or repository without vendor specific implementation, and if later you need to change the backend, you can do it without affecting your existing business code implementation.
I would advice you to check the hibernate documentation for further reference
The Spring Data umbrella of projects provides a nice DAO abstraction named CrudRepository. I believe most of the sub-projects (JPA, MongoDB, etc.) provide some implementations of it.
JPA would be one of a number of implementations you would use to map your relational database to objects. It would not protect you from database changes.
I think you're looking for the DAO Pattern. What I'm doing is as follows:
Create an interface for each DAO
Create a higher level DAO implementation that simply calls my actual database specific implementation
Wire the higher level DAO implementation to the database specific implementation with Spring.
This way, no code anywhere touches database specific implementation. The connections are formed only in XML.
JPA is designed around RDBMS ... only. Using it for other types of datastores makes little sense since things likes its query language leak SQL syntax. JDO is designed for datastore agnoticity, and provides persistence to many datastores using its implementations such as DataNucleus, though not all of those that you mention.
JPA is designed around RDBMS, Hibernate is also designed for RDBMS. There are few implementations of JPA which support no-sql. Similar projects are built around hibernate to support no-sql databases. However the API itself is tuned for RDBMS.
Implemeting a DAO patterns would require you to write your own query api. Later extend the implementation when ever your data store changes.
JDO and DataNucleus is ground up designed for heterogeneous data stores. Already has support for a dozen stores ,plus RDBMS. Beauty is that the query api remains constant across the stores. JDO allows you to work with domain model and leave the storage details to implementations like DataNucleus.
Hence I suggest JDO api with datanucleus.
The below link gives list data stores and f features already available in DataNucleus
http://www.datanucleus.org/products/accessplatform_3_0/datastore_features.html
I've been doing some reading lately and one thing that I've come across was this article about the Anaemic Domain Model from Martin Fowler. I know, it's old, but somehow very actual in Java world. So I'm trying to move towards a more domain-driven design. One option would be to go with the Active Record model. However, I don't really like the current implementation it has in Scala. It completely couples the domain objects with the persistence type (not so bad in most cases but I have a project where I need to store something both in a RDB and in Mongo). Then I ran across this article about Spring, Hibernate and Scala and though here too the domain object is coupled with the JPA trait, I noticed how he uses Spring to inject a Notification Service. Can't the same mechanism be used to inject a transparent DAO interface? Have you seen this used anywhere? Any thoughts on the idea?
You should have a look at Spring-Data, this project provides some kind of abstraction over different data storages.
I have a java web application built on Stuts2/Google Guice/JPA. It uses hibernate as the JPA vendor. I would like to add support so it can be used on Google's App Engine. Of course I'm running into issues with the queries and mappings. Such as Many-to-Many and joins not being supported.
I'm trying to come up with the best solution for keeping my app able to be standalone. For example sin a tomcat/jetty on any database the JPA vendor supports or Google App Engine with datanucleus as the vendor.
One solution I thought of would be to use JPA for my standalone implementations and JDO for Google's App Engine. Obviously this would require me to annotate my model objects with both JPA and JDO annotations and to write another implementation for the DAO layer.
Are there any other good solutions that others have tried?
I think your approach is a good one. I think a well design architecture is the best approach. You will most likely see a lot of variance in the DAO layer. A good design would see a DAO interface, then each specific model access would have its own implementation of that interface e.g. JpaMyObjectDAO, JpaGAEObjectDAO etc. Also like you siad, App Engine has some special requirements when it comes to declaring your entity classes. Perhaps you could have different versions of the entity classes (each that conforms to its storage scheme like App Engine or Hibernate), then have a common DTO representation for your higher layers to use.
You could relocate your queries to an XML configuration. This way you can have queries for a RDBMS in one configuration and your queries for BigTable in another configuration.
Another idea is that DataNucleus is a JPA vendor as well. You could probably ease your development by making it your primary JPA vendor on both GAE and your Servlet Container. JPA vendors often times have very slight differences between what they do with their metadata and this may save you some headaches.