Solutions to IT problems

Solutions I found when learning new IT stuff

Spring Data JPA: My first steps

leave a comment »


Introduction

In my previous article I showed my first experience with Spring using Hibernate as JPA Provider. After that article I heard about Spring Data and was immediately convinced that it is ideal for my hobby! project. In contrast to my previous article this will not be a tutorial but a short review of my experience with Spring Data. For an introduction of Spring Data please see the Spring Data Reference Guide.

The Good

It works. It is pretty great and I’m sure it can greatly reduce development time for certain types of applications.

CRUD in < 5 minutes

In Spring Data JPA you extend provided repository interfaces. Depending on which interface you extend it comes with different methods, like for CRUD. You don’t have to specify or implement any CRUD methods. You just extend a provided interface and Spring Data JPA will automatically generate implementations at runtime!

Custom Queries

If you need more specific query methods not offered by the repository interfaces you can create your own query methods. There are several version to do so. You can to it by “implicit path”. Meaning you create methods starting with “findBy” and then follow the entities properties along which every path you like. Simple example:

public interface PersonRepository extends Repository<User, Long> {

List<User> findByLastnameStartingWith(String lastname);
}

This assumes User entity has a property named lastname. Above example is very simple but you can also create such query methods that travel over relationship mappings.

public interface PersonRepository extends Repository<User, Long> {

List<User> findByRolesRoleName(String roleName);
}

This assumes entity User has a OneToMany mapping to Role entity and Role has a property roleName.

Another option is to specify a JPQL query yourself by annotating it with @Query.

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")
  User findByEmailAddress(String emailAddress);
}

@Query also supports native queries!

There are even more possibilities . See the Spring Data JPA Reference for further information.

QueryDSL Integration

Spring Data JPA can be easily integrated with QueryDSL.

Querydsl is a framework which enables the construction of type-safe SQL-like queries for multiple back-ends including JPA, JDO and SQL in Java.

This is also very useful.

The Bad

I’m still a novice at both Spring and JPA (Hibernate). So not everything that I mentioned in this section is directly related to Spring Data and can happen when only using Spring or hibernate.

Simplistic Examples

All examples and tutorials I found are mostly based on a simplistic domain model and are for a fixed, well defined, not extendable application. I’m creating a “framework” for applications that need chemical structure search and hence it must be expandable by whomever uses it. So what I’m saying is it works great for very basic, simple usage scenarios but if you have anything half-complex in terms of inheritance and relationships between entities be prepared for issues or the need for adjusting your design to be suitable for your JPA provider, Spring and Spring Data. It’s safe to say I wasted at least 10x times more time searching for solutions to my issues than actual coding.

StackTrace hell

In case of exception you get confronted with a huge stacktrace. While that might not be a bad thing (better than none at all), the actual exception thrown is often not helpful at all at helping you to fix it. This almost drove me crazy.

As example I have a OneToMany relationship between 2 abstract entity classes. In my tests i created 2 different implementations to check if it my framework can deal with that in the way I expect. I had entity C1 and C2 on the “One-side” and A and B on the “Many-side”. The relationship only allows C1 containing As and C2 containing Bs. In my test when loading a B-entity, I would get an exception that C2 does not containing property C1.regNumber. Of course that was true, only C1 has that property. The real issue was, why is hibernate trying to load that property for a C2 entity? It made no sense to me at all. I went on an insane debugging spree through spring and hibernate. I saw that Spring Data had it all right, requested C2 entity. Somewhere deep in hibernate suddenly it changed to a C1. After several hours it dawned on me. The issue was I forgot to add targetEntity = AbstractC to the “Many-side” of the relation, it was on the “one-side”. It appears that hibernate then just chose that targetEntity is C1 instead of throwing an exception the targetEntity property is missing.

Version hell

Due to above issue I tried it with never version of Spring and hibernate and ran into other issues (“Could not load application context”). The context was identical. It turned out some configuration which was not correct worked in earlier version but not in never. And if you have a big XML and exactly one simple property of 1 bean causes this, it is not at all easy to detect. So be prepared for everything to fall over even when doing a minor upgrade.

Configuration hell

This is simple to explain. Use the exact same configuration for your connection pooling and data source. Don’t omit the connection pool in test configuration. Your tests can pass without it and fail with one enabled, especially in my cause were the used version of the connection pool was incompatible with spring 3. You waste a ton of time again to figure that out. I also suggest to use the same database if you have a fixed target. If you application is portable I would still suggest to run at least some integration tests on a different database and probably a “real-one”, meaning not one of the in-memory kinds.

Conclusion

Suitable for beginners?

Spring Data JPA is great but it includes multiple technologies and you need to know each of them especially their quirks.: Spring (ie dependency-injection), JPA and the JPA Provider you use, Spring Data itself, in my case also QueryDSL and the connection pool and its configuration. I was a beginner at all of these technologies and at times it was just too much. So if you are in the same boat as me, you need to be really, really patient and willing to learn. You need to be an expert at using google and at asking questions in forums (stackoverflow) so that readers can easily understand. You must be persistent, have a clear goal and the will to reach it. Else it will be difficult.

However if you already experienced in Spring and the JPA Provider of your choice, I can only recommend you to try it out.

web-applications with spring-data?

Possible. But I have played with Grails and Grails offers most of the above mentioned querying stuff too and more, namely the actually web-part. Spring Data offers nothing in that regard and for an average web-application your better of just using Grails (or other web frameworks). That leaves the question for what you can actually use spring data? I can’t really answer that. I had a unique use-case, create a framework for a special type of database search (chemical structure search) and despite my issues it is very suitable for that. As another option i see is for replacing an existing Data access layer in an existing legacy application, make it more maintainable. Maybe for SOA, eg. Data access layer that has a lot of different clients, web, rich and “automated” ones. Sure there are other possibilities but the conclusion is that Spring Data is for the rapid creation of a maintainable, easy-to use and extensible Data Access Layer and not to create a full application.

About these ads

Written by kienerj

February 20, 2013 at 14:11

Posted in Database, Java, Programming

Tagged with ,

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: