129

I am having a hard time deciding if I should stick with Hibernate for a new project, or get my feet wet with JPA and the new Spring Data implementation.

Is the Spring Data framework intended for large projects or small projects with modest query requirements?

While I certainly see the advantage in code reduction by using the @Query annotation, what do you do for dynamic queries? What about when you want to implement a save() method that's quite complex?

The documentation says to make a Custom interface and implementation that your main repository implements, but what if you need to access any super methods on the crud repository itself? The crud repository implements the custom one - not the other way around. It seems like an odd design.

I am very uncertain whether this framework will meet the challenges of complex and large applications. I've never ran into many problems with Hibernate, and I'm considering sticking with the good old reliable rather than go with Spring Data JPA.

What should I do? What unforeseen complications and costs will I encounter if I go with Spring Data JPA?

Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
egervari
  • 22,372
  • 32
  • 121
  • 175
  • 1
    As far as I know, it makes little difference. Go with the one you're more comfortable with. Why the debate? – duffymo Oct 08 '12 at 23:26
  • 1
    I am obviously way more comfortable with Hibernate, but if I can do the same things and be more productive, I'd rather adopt the newer approaches. However, if Hibernate is still more powerful and I will encounter a lot less problems, then that's something I would like to know about. – egervari Oct 08 '12 at 23:27
  • 3
    JPA is a generalization of ORM that uses Hibernate as one of many implementations. What powers are you attributing to one over the other? JPA is a standard, but I see little difference between the two. In the interest of full disclosure, I'll say that I don't care for either one. Both generate SQL for you. I'd rather write it myself. ORM isn't for every problem and every user. – duffymo Oct 08 '12 at 23:29
  • I know that there's very little functional difference between the two as far as generating sql and mapping entities to the database tables. If you look at Spring Data JPA, you'll see that the amount of code one has to write is significantly less than going with Hibernate directly. I'd like to take advantage of these savings, but by the looks of it, it seems like with Spring Data, some things are going to be messy and maybe even not possible. I really want to know if that assessment is true or not. – egervari Oct 08 '12 at 23:35
  • It seems to me @duffymo is confusing JPA with Spring Data JPA which goes further. – madth3 Oct 09 '12 at 00:51
  • 1
    I agree. When it comes to JPA or Hibernate only, I'd pick Hibernate every time. I honestly don't like the JPA implementation that much on its own. The IDE support in IDEA is actually kind of bad still, and it will complain if the mappings are not correct when the application starts rather than let the unit tests run. There's a lot of other nitpicks I have with JPA. I actually kind of enjoy the old Hibernate XML mapping files. It has the advantage of making my objects look a lot less cluttered too. Spring Data JPA offers many new features, so I was finally wondering if its worth it to switch. – egervari Oct 09 '12 at 00:57
  • 3
    "Spring Data" is not an implementation of JPA, or anything. It simply takes an existing JPA implementation and simplifies what you provide to it. The JPA implementation still does all of the work under the covers – Neil Stockton Jan 26 '16 at 18:36

3 Answers3

107

So, spring-data does some extra magic that helps with complex queries. It is strange at first and you totally skip it in the docs but it is really powerful and useful.

It involves creating a custom Repository and a custom `RepositoryImpl' and telling Spring where to find it. Here is an example:

Configuration class - point to your still-needed xml config with annotation pointing to your repositories package (it looks for *Impl classes automatically now):

@Configuration
@EnableJpaRepositories(basePackages = {"com.examples.repositories"})
@EnableTransactionManagement
public class MyConfiguration {
}

jpa-repositories.xml - tell Spring where to find your repositories. Also tell Spring to look for custom repositories with the CustomImpl file name:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<jpa:repositories base-package="com.example.repositories" repository-impl-postfix="CustomImpl" />

</beans>

MyObjectRepository - this is where you can put annotated and unannotated query methods. Note how this repository interface extends the Custom one:

@Transactional
public interface MyObjectRepository extends JpaRepository<MyObject, Integer>, MyObjectRepositoryCustom {

    List<MyObject> findByName(String name);

    @Query("select * from my_object where name = ?0 or middle_name = ?0")
    List<MyObject> findByFirstNameOrMiddleName(String name);
}

MyObjectRepositoryCustom - repository methods that are more complex and cannot be handled with a simple query or an annotation:

public interface MyObjectRepositoryCustom {

    List<MyObject> findByNameWithWeirdOrdering(String name);
}

MyObjectRepositoryCustomImpl - where you actually implement those methods with an autowired EntityManager:

public class MyObjectRepositoryCustomImpl implements MyObjectRepositoryCustom {

    @Autowired
    private EntityManager entityManager;

    public final List<MyObject> findByNameWithWeirdOrdering(String name) {
        Query query = query(where("name").is(name));
        query.sort().on("whatever", Order.ASC);
        return entityManager.find(query, MyObject.class);
    }
}

Amazingly, this all comes together and methods from both interfaces (and the CRUD interface, you implement) all show up when you do:

myObjectRepository.

You will see:

myObjectRepository.save()
myObjectRepository.findAll()
myObjectRepository.findByName()
myObjectRepository.findByFirstNameOrMiddleName()
myObjectRepository.findByNameWithWeirdOrdering()

It really does work. And you get one interface for querying. spring-data really is ready for a large application. And the more queries you can push into simple or annotation only the better off you are.

All of this is documented at the Spring Data Jpa site.

starball
  • 20,030
  • 7
  • 43
  • 238
sbzoom
  • 3,273
  • 4
  • 29
  • 34
  • 5
    This is actually what I tried, and it works to some extent. The problem I had is what if you want to override save()? For example, imagine you are saving a blog, and you want to process/save the tags associated with it in the save() method since putting it in a service doesn't make the most sense. This is easy to do with raw Hibernate, but I don't see a good way to do with Spring JPA. I'm going to mark your answer as correct though because it's correct. That's basically what you can do with Spring Data JPA. I think I'll stick with Hibernate though. This answer will definitely help others. – egervari Oct 09 '12 at 23:09
  • 8
    You can implement your own `JpaRepository` -> `MyJpaRepository`. You have to also create a `MyJpaRepositoryFactoryBean` but if you set it all up correctly, you can override the .save() method. Here is the Spring Data JPA Docs: http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/#repositories.custom-behaviour-for-all-repositories Don't give up just yet! – sbzoom Oct 10 '12 at 13:57
  • @Picrochole how do you interpret 'lower tier of application'? Is service, which calls DAO lower in tier? – Rumid May 29 '17 at 15:41
12

I've used Spring Data JPA in small and large projects with simple query demands. The main advantage is from not even having to use the @Query annotation. There is nothing in Spring Data that prevents you from using it in large projects and the recent QueryDSLsupport might help you. This is an example of using QueryDSL to target Hibernate.

If you foresee complex queries and you feel comfortable using Hibernate objects without JPA I think an alternative combination could be to have the simple Spring Data Repositorys next to complex Hibernate-based ones with the specific methods you might need. It might be less cumbersome that twisting a Hibernate implementation into Spring Data JPA structure.

Timo Westkämper
  • 21,824
  • 5
  • 78
  • 111
madth3
  • 7,275
  • 12
  • 50
  • 74
  • 2
    I think I'd rather use the same consistent api for queries though rather than mixing and matching in the same project. I still haven't found a good solution for the complex spring data jpa stuff, and since there's quite a few nitpicks with jpa that I have in general, I think I may just be happier to accept hibernate as my orm. I will have a lot of complex queries, and I can't afford to have a 40/60 mixture. It's not worth it to me :( – egervari Oct 09 '12 at 03:22
  • 1
    You can also use Querydsl directly without Spring Data which gives you a single powerful query layer on top of JPA. – Timo Westkämper Oct 10 '12 at 07:53
5

Spring JPA will provide you a lot of abstraction from writing SQL and even some HQL using query method declaration. Spring JPA shines with its query generation but when you want a purely hibernate solution you can customize as needed as spring JPA is still based on hibernate. Check the docs http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html for more info.

F.O.O
  • 4,730
  • 4
  • 24
  • 34