What's the difference between Hibernate and Spring Data JPA - java

What are the main differences between Hibernate and Spring Data JPA?
When should we not use Hibernate or Spring Data JPA?
Also, when may Spring JDBC template perform better than Hibernate and Spring Data JPA?

Hibernate is a JPA implementation, while Spring Data JPA is a JPA data access abstraction. Spring Data JPA cannot work without a JPA provider.
Spring Data offers a solution to the DDD Repository pattern or the legacy GenericDao custom implementations. It can also generate JPA queries on your behalf through method name conventions.
With Spring Data, you may use Hibernate, EclipseLink, or any other JPA provider. A very interesting benefit of using Spring or Java EE is that you can control transaction boundaries declaratively using the #Transactional annotation.
Spring JDBC is much more lightweight, and it's intended for native querying, and if you only intend to use JDBC alone, then you are better off using Spring JDBC to deal with the JDBC verbosity.
Therefore, Hibernate and Spring Data are complementary rather than competitors.

There are 3 different things we are using here :
JPA : Java persistence api which provide specification for persisting, reading, managing data from your java object to relations in database.
Hibernate: There are various provider which implement jpa. Hibernate is one of them. So we have other provider as well. But if using jpa with spring it allows you to switch to different providers in future.
Spring Data JPA : This is another layer on top of jpa which spring provide to make your life easy.
So lets understand how spring data jpa and spring + hibernate works-
Spring Data JPA:
Let's say you are using spring + hibernate for your application. Now you need to have dao interface and implementation where you will be writing crud operation using SessionFactory of hibernate. Let say you are writing dao class for Employee class, tomorrow in your application you might need to write similiar crud operation for any other entity. So there is lot of boilerplate code we can see here.
Now Spring data jpa allow us to define dao interfaces by extending its repositories(crudrepository, jparepository) so it provide you dao implementation at runtime. You don't need to write dao implementation anymore.Thats how spring data jpa makes your life easy.

I disagree SpringJPA makes live easy. Yes, it provides some classes and you can make some simple DAO fast, but in fact, it's all you can do.
If you want to do something more than findById() or save, you must go through hell:
no EntityManager access in org.springframework.data.repository classes (this is basic JPA class!)
own transaction management (hibernate transactions disallowed)
huge problems with more than one datasources configuration
no datasource pooling (HikariCP must be in use as third party library)
Why own transaction management is an disadvantage? Since Java 1.8 allows default methods into interfaces, Spring annotation based transactions, simple doesn't work.
Unfortunately, SpringJPA is based on reflections, and sometimes you need to point a method name or entity package into annotations (!). That's why any refactoring makes big crash.
Sadly, #Transactional works for primary DS only :( So, if you have more than one DataSources, remember - transactions works just for primary one :)
What are the main differences between Hibernate and Spring Data JPA?
Hibernate is JPA compatibile, SpringJPA Spring compatibile. Your HibernateJPA DAO can be used with JavaEE or Hibernate Standalone, when SpringJPA can be used within Spring - SpringBoot for example
When should we not use Hibernate or Spring Data JPA? Also, when may Spring JDBC template perform better than Hibernate / Spring Data JPA?
Use Spring JDBC only when you need to use much Joins or when you need to use Spring having multiple datasource connections. Generally, avoid JPA for Joins.
But my general advice, use fresh solution—Daobab (http://www.daobab.io).
Daobab is my Java and any JPA engine integrator, and I believe it will help much in your tasks :)

Spring Data is a convenience library on top of JPA that abstracts away many things and brings Spring magic (like it or not) to the persistence store access. It is primarily used for working with relational databases. In short, it allows you to declare interfaces that have methods like findByNameOrderByAge(String name); that will be parsed in runtime and converted into appropriate JPA queries.
Its placement atop of JPA makes its use tempting for:
Rookie developers who don't know SQL or know it badly. This is a
recipe for disaster but they can get away with it if the project is trivial.
Experienced engineers who know what they do and want to spindle up things
fast. This might be a viable strategy (but read further).
From my experience with Spring Data, its magic is too much (this is applicable to Spring in general). I started to use it heavily in one project and eventually hit several corner cases where I couldn't get the library out of my way and ended up with ugly workarounds. Later I read other users' complaints and realized that these issues are typical for Spring Data. For example, check this issue that led to hours of investigation/swearing:
public TourAccommodationRate createTourAccommodationRate(
#RequestBody TourAccommodationRate tourAccommodationRate
) {
if (tourAccommodationRate.getId() != null) {
throw new BadRequestException("id MUST NOT be specified in a body during entry creation");
}
// This is an ugly hack required for the Room slim model to work. The problem stems from the fact that
// when we send a child entity having the many-to-many (M:N) relation to the containing entity, its
// information is not fetched. As a result, we get NPEs when trying to access all but its Id in the
// code creating the corresponding slim model. By detaching the entity from the persistence context we
// force the ORM to re-fetch it from the database instead of taking it from the cache
tourAccommodationRateRepository.save(tourAccommodationRate);
entityManager.detach(tourAccommodationRate);
return tourAccommodationRateRepository.findOne(tourAccommodationRate.getId());
}
I ended up going lower level and started using JDBI - a nice library with just enough "magic" to save you from the boilerplate. With it, you have complete control over SQL queries and almost never have to fight the library.

If you prefer simplicity and more control on SQL queries then I would suggest going with Spring Data/ Spring JDBC.
Its good amount of learning curve in JPA and sometimes difficult to debug issues.
On the other hand, while you have full control over SQL, it becomes much easier to optimize query and improve performance. You can easily share your SQL with DBA or someone who has a better understanding of Database.

Hibernate is implementation of "JPA" which is a specification for Java objects in Database.
I would recommend to use w.r.t JPA as you can switch between different ORMS.
When you use JDBC then you need to use SQL Queries, so if you are proficient in SQL then go for JDBC.

Related

Spring Boot - MySQL to Postgres migration

I have a spring boot application with mysql database. I'm planning to migrate this to postgres database. So, do I need to change anything in the entity classes(like datatypes) and JPA repositories?
I have never done this myself so I cannot speak from experience. The abstraction layer of JPA should be able to do this depending on how you used and extended the platform.
If you only used JPA (and additional Spring) annotations in your classes and kept your custom queries to JPQL then you should be good to go.
If you extended your code with Native Queries or if you extended the types to support MySQL only types, you might need to make changes. But again this depends on which libraries you used. One of the more common custom types such as JSON in hibernate would be supported in both if you used https://github.com/vladmihalcea/hibernate-types.
So there is no definitive answer, it really depends on your code-base.

How is spring-data-jdbc complimenting MyBatis?

I would like to understand why is spring-data-jdbc providing integration to MyBatis.
What problem is it solving?
How is spring-data-jdbc complimenting MyBatis.
Is it just a question of conforming the Mapper to Repository or it goes beyond that.
Why would I use in combination MyBatis with spring-data-jdbc when I can just use the Mappers.
In a nutshell spring-data-jdbc provides a Domain Driven Design Repository implementation for the store that provides a JDBC API. It tries to be very simple conceptually (especially if you compare it with JPA). And is similar to mybatis in the sense that it does not try to introduce abstractions that hide the complexity of the ORM.
Here's the quote from spring-data-jdbc documentation:
If you load an entity, SQL statements get executed. Once this is done, you have a completely loaded entity. No lazy loading or caching is done.
If you save an entity, it gets saved. If you do not, it does not. There is no dirty tracking and no session.
There is a simple model of how to map entities to tables. It probably only works for rather simple cases. If you do not like that, you should code your own strategy. Spring Data JDBC offers only very limited support for customizing the strategy with annotations.
spring-data-jdbc can be used without mybatis. The queries are either CRUD queries implemented by spring-data-jdbc itself or are custom queries specified using #Query annotation.
It does provide integration to mybatis and this allows to use the third way to specify queries namely using mybatis mapper with all features available in mybatis. This allows to create more complex mappings while still using automatic queries generation based on repository method name for simple queries.
Sometimes the necessity to create SQL queries even for simple CRUD operations is seen as a limitation or issue in mybatis. spring-data-jdbc allows to solve this by the price of introducing an additional abstraction layer (repositories) to the application. I say additional because it is possible to use mybatis mapper as a DDD repository.
An indeed if the application has a lot of CRUD operations the will be a lot of very similar code or some solutions to make generic CRUD similar to https://github.com/rickcr/mybatis-generic-crud will be introduced and used.
spring-data-jdbc allows to solve this problem rather elegantly with rather low price.

Spring Application JPA and JDBC

I am starting with a new project and currently evaluating whether to use JPA or JDBC. Our operations mostly are going to be an bulk-insert and bulk-read and very rarely single insert/read.
I checked a prototype with JPA and JDBC and realized that both has its own merits and limitations.
Considering the current use case that for a fact I will only have always a bulk read and bulk write, which one will be a better option to go with ?
Spring JPA Repository gives a simple method save(Collection) which can take a collection and save as well.
Also Validations are also not be considered here, as the payload will already be validated in the layers above and the database layer should just do the read/write operations.
Does the JPA save(Collection<>) method in turn uses the jdbc templates or is it entirely a different implementation ?
Thanks in advance !
We use both JPA and JDBC in one application wiht no problem. Preferably we use JPA/JPQL and fall back to JDBC if needed. For JPA we use Spring Data JPA and for JDBC Spring JDBC Template.

Migrating to ORM

Stepwise, what would be a good way of integrating Spring and Hibernate into an existing JSF application that doesn't use ORM?
1) You would need to design the domain model first and then map it to the database. You could use hibernate reverse engineering tools for this.
2) Other option is to manually map your current objects(DTO) to database tables. Since you use JSF, I assume you'd be having some objects currently.
3) Design the Service Layer around the objects.
Spring -
1) You could use Spring to provide hibernate template, provide common services through bean.
2) You can manage the transaction in Spring.
I would recommend first to write tests to check your code of your previous persistent mechanism. This code could be used to check the correct behavior of our ORM integration.
As mentioned by other answers, having a clear DAO defined by interface helps to bound the DAO code.
Map the domain objects first, then write your DAO, then your service objects (which take care of large atomic suite of operations by enclosing its in a transaction).
Use persistence mechanism which is vendor-agnostic (JPA is the good and only choice).
Start with one kind of database and stick with it during all the migration. In very uncommon cases, you can meet subtle differences between databases which could be very hard to solve, especially if you're a beginner.
When starting, use automatic generation of database (generateDdl for hibernate subsystem) and then, when things starts to be stabilized, force #Table and #Column annotations to fix name of each column. At this point, write a SQL script which generate the database with empty tables. The reason if to fix your architecture and be sure you're controlling the database organization.
If you're serious about ORM, please look at Java Persistence With Hibernate of Christian Bauer (Manning publications), this is "the bible" about hibernate and JPA on Java.
If you've written Spring properly, you should have DAO/repository interfaces. If that's the case, all you have to do is write a new implementation of that interface using Hibernate, test it, and change your Spring configuration to inject it.
ORM presumes that you have an object model in place to map to a relational schema. If you don't, I would advise against using ORM. Better to use iBatis or JDBC in that case.

JPA 1 is not good enough

Working in a medium size project during last 4 months - we
are using JPA and Spring - I'm quite sure that JPA is not
powerfull for projects that requires more than CRUD
screen... Query interface is poor, Hibernate doesn't
respect JPA spec all the time and lot of times I need to use
hibernate classes, annotations and config.
What do you guys think about JPA? Is it not good enough?
Well I think most of the time JPA is "good enough" but I miss the Criteria API a lot (only provided by Hibernate)
Hibernate has been a long time in the road. That's why it has many functions not avaiable in JPA yet. But with time JPA will catch up. Until then, use JPA and Hibernate specific settings where necessary. If you need to switch later, it'll be a lot easier.
Well I can't provide specific guidance without knowing more about your particular case. It seems like you're using Hibernate's JPA implementation. You might try other JPA implementations if there is something about Hibernate's you don't like. As far as the query interface, if JPA's queries aren't doing what you want, you always have the ability to get a plain old Connection and work with that. The genius of the framework is that -- at the very least -- you don't have to write all the CRUD code ever again. I would never claim JPA is perfect, but it's better than hand-writing SQL all the time to do trivial things.
We combine JPA 2.0, Hibernate Core, Hibernate Search and Hibernate Validator via our in-house wrapper framework. It does everything we throw at it :)
Combine that with Maven and we have a database built for us too! Add DBUnit into the mix and you've got everything you need.
Wickedly fast searches via Lucene, but using Hibernate Criteria/HQL queries are very cool. All this power behind a GWT suggest box is great.
My advice would be simply to use Hibernate. Hibernate coupled with JPA annotations + Hibernate annotations is pretty powerful. You can even configure an EntityManagerFactory to autodiscover Entities on the classpath but then call getSessionFactory() to leverage the native Hibernate APIs in your application. If you are using Spring it's very easy to do this with LocalContainerEntityManagerFactoryBean and HibernateJpaVendorAdapter.
Sure any ORM is better than hand-writting SQL for CRUD operations... the thing is: I'm think there is no reason to use JPA instead pure Hibernate because I'm mixing both a lot. If I'm not getting a hidden provider why use JPA anyway?
One of the nice things about using JPA vs Hibernate Annotations is the automatic configuration and discovery of persistent classes. Also, it depends on how much of the time you need to break from using the JPA API, if you are only doing it 10% of the time, it would still make switching providers a lot easier than if you were to use hibernate for 100% of your queries.

Categories

Resources