In this post I provide an example of creating a persistence layer using Apache’s OpenJPA implementation of the Java Persistence API(JPA). I created the example using a TDD approach and I have once again used Liquibase to version control the database. I have used a few more Liquibase parameters, than what I used in my previous post on Liquibase, primarily around managing the local test database and the test data that I needed to run the examples.
This is a very basic example of using JPA and I will be building on this over the next few weeks in order to provide a more concrete example. As always the full source for the project is available on GitHub and all dependencies are managed via Maven. To do a mvn install you will need to have access to a Oracle schema and simply change the database connection properties to point to your Oracle instance.
The source is available here https://github.com/craigew/JPAIntroduction.
First off, you need to add the following dependency to your POM to add OpenJPA to your project.[gist https://gist.github.com/craigew/6659242 /]
Next, because I am unit testing my code, I want to deploy this onto Tomcat, and it is not running in a JEE container I needed to add the following enhancer plugin to the POM. The enhancer adds code to your persistent classes at build time, adding the necessary fields and methods to implement the required persistence features. There are three approaches to enhancement:
- Build time (as per this example)
- On deployment
- Or at runtime
Further information on the enhancer is available on the OpenJPA site here.[gist https://gist.github.com/craigew/6659212 /]
Before moving onto the actual JPA code I want to explain some of the other configuration in the POM.
Lines 11 and 12 – When I am developing I want the tables to be dropped and recreated by liquibase. The “test” context maps to the liquibase change log and with the context set to “test” my test data is only executed in the test environment.
Line 39 – This is the converse to lines 11 and 12. Now that this is in the release profile, I do not want to drop and recreate all the tables. And because I have not got the “test” context set none of my unit testing data is created in the database.
Line 27 – I want to run my tests when running the dev profile.
Line 53 – I don’t want to run the test when running the release profile.[gist https://gist.github.com/craigew/6659255 /]
Finally, we can get to the actually code.
First off the unit tests. These provide you with an idea of the methods that I have created. I prefer using a TDD approach because it makes you do a little bit of thinking and planning up front, and you get the massive benefit of being able to confidently refactor your code. In this particular example, I started out with a solution I was not happy with and I was able to continuously refactor, knowing that my tests would tell me if I had broken anything.[gist https://gist.github.com/craigew/6659601 /]
As you can see the example is a very simple, create, select and update.
Now that we have got everything wired up, it is easy to create the first entity.[gist https://gist.github.com/craigew/6659621 /]
You will notice that it is extending a class called BaseEntity. I created this because I want all my entities to generate their unique id’s or primary keys in the same consistent manner. And I prefer my entities to be as simple as possible.
I am using an oracle sequence, that will be shared across all entities, to generate the unique identifier. As with the tables the Oracle sequence is generated via liquibase.[gist https://gist.github.com/craigew/6659643 /]
Now that we have created our entity class, we need to wire them up so that OpenJPA knows about them. Note the “persistence-unit”, this is used in the code to create the entity manager. You will see this implementation in the DataAccess class. In one of my next posts I would want to explore whether this persistence-unit would be a suitable technical match to what the Domain Driven Design guys call a Boundary.[gist https://gist.github.com/craigew/6659656]
Now when I am creating my service classes I don’t want my application polluted with scaffolding type code. So I created a class, using generics, to hide all the scaffolding from the service classes.[gist https://gist.github.com/craigew/6659684 /]
And the service class becomes extremely simple.[gist https://gist.github.com/craigew/6659695 /]
So this is a very simple first implementation of JPA, in some of my next posts I want to explore the relationships between entities and create a bigger domain model.
If you have found this useful then please give me a like. ;-).