How to load initial data (or seed data) using Java JPA?

14,038

Solution 1

I feel your pain, I have gone wanting in a Java project for all of the perks Rails has.

That being said, there is no reason to use straight SQL. That approach is just asking for trouble. As your database schema changes during development, all the brittle SQL breaks. It is easier to manage data if it is mapped to JPA Models, which will abstract the SQL interaction with the database.

What you should do is use your JPA models to seed your data. Create a component that can execute the creation of models you require and persist them. In my current project, we use Snake YAML to serialize our Models as Yaml. To seed our database we deserialize the yaml to JPA models and persist.

If the models change (variable types change, remove columns, etc), you have to make sure that the serialize data will still be able to correctly deserialize into the JPA models. Using the human readable format of Yaml makes it easy to update the serialized models.

To actually run your seed data, bootstrap your system however you can. As @GeoorgeMcDowd said, you can use a Servlet. I personally prefer to create a command line tool by creating a uberjar with Class.main. Then you just need to create a script to setup your classpath and call the Class.main to run the seed.

Personally, I love Maven as project meta data but find it difficult as a build tool. The following can be used to exec a java class:

mvn exec:java -Dexec.mainClass="com.package.Main"

Solution 2

Just create a class and method that creates the objects and persists the data. When you fire up your application, run the method that you created in a servlet init.You can load your servlet up with the following web.xml config.

<servlet>
   <servlet-name>MyServlet1</servlet-name>
   <servlet-class>com.example.MyServlet1</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>

Edit: Format web.xml to be more reader friendly.

Solution 3

You could model your project with Maven and write a simple test to initialize the seed data, so the only thing you will need to do is to run "mvn test".

Share:
14,038
Filipe Giusti
Author by

Filipe Giusti

I've been working mainly with Ruby for the last 8 years in startups.

Updated on June 13, 2022

Comments

  • Filipe Giusti
    Filipe Giusti almost 2 years

    I have a JPA project and I would like to insert some initial data just on development, so I can check if everything is running smoothly easy.

    My research lead me to find only solution with direct SQL script, but that isn't right. If I'm using a framework to abstract database details why would I create script for an specific database?

    In the ruby on rails world we have the command "rake db:seed" that simple executes a file named seed.rb that has the function to add the initial data on the database calling the abstraction layer. Is there something like that on java?

    The ideal solution I can think of would be to execute a maven goal that would execute a java class, is there an easy way or a maven plugin to do it?

  • Guido
    Guido about 12 years
    Why do you need to serialize/deserialize your model to YAML?
  • mguymon
    mguymon about 12 years
    Does not necessarily need to be YAML, any way to serialize the models to a file will do. Then you can use the files as seed data for the database. Yaml just has the benefit of being easy to work with for reading and editing.
  • Dave
    Dave over 11 years
    I've done this and while it works, the resulting XML is just as brittle as the SQL the OP was trying to avoid in the first place.
  • Dave
    Dave over 11 years
    Alternatively you can do this from a Spring bean and thus it can be done without a servlet container for integration testing.
  • nansen
    nansen over 11 years
    You can reduce some of the brittleness and manual rework by including a db migration tool, like liquibase, in your production as well as test data management.