Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to populate Java (web) application with initial data using Spring/JPA/Hibernate

I want to setup my database with initial data programmatically. I want to populate my database for development runs, not for testing runs (it's easy). The product is built on top of Spring and JPA/Hibernate.

  • Developer checks out the project
  • Developer runs command/script to setup database with initial data
  • Developer starts application (server) and begins developing/testing

then:

  • Developer runs command/script to flush the database and set it up with new initial data because database structures or the initial data bundle were changed

What I want is to setup my environment by required parts in order to call my DAOs and insert new objects into database. I do not want to create initial data sets in raw SQL, XML, take dumps of database or whatever. I want to programmatically create objects and persist them in database as I would in normal application logic.

One way to accomplish this would be to start up my application normally and run a special servlet that does the initialization. But is that really the way to go? I would love to execute the initial data setup as Maven task and I don't know how to do that if I take the servlet approach.

There is somewhat similar question. I took a quick glance at the suggested DBUnit and Unitils. But they seem to be heavily focused in setting up testing environments, which is not what I want here. DBUnit does initial data population, but only using xml/csv fixtures, which is not what I'm after here. Then, Maven has SQL plugin, but I don't want to handle raw SQL. Maven also has Hibernate plugin, but it seems to help only in Hibernate configuration and table schema creation (not in populating db with data).

How to do this?

Partial solution 2010-03-19

Suggested alternatives are:

  • Using unit tests to populate the database #2423663
  • Using ServletContextListener to gain control on web context startup #2424943 and #2423874
  • Using Spring ApplicationListener and Spring's Standard and Custom Events #2423874

I implemented this using Spring's ApplicationListener:

Class:

public class ApplicationContextListener implements ApplicationListener {

    public void onApplicationEvent(ApplicationEvent event) {

        if (event instanceof ContextRefreshedEvent) {
            ...check if database is already populated, if not, populate it...
        }
    }
}

applicationContext.xml:

<bean id="applicationContextListener" class="my.namespaces.ApplicationContextListener" />

For some reason I couldn't get ContextStartedEvent launched, so I chose ContextRefreshedEvent which is launched in startup as well (haven't bumped into other situations, yet).

How do I flush the database? Currently, I simply remove HSQLDB artifacts and a new schema gets generated on startup by Hibernate. As the DB is then also empty.

like image 621
Tuukka Mustonen Avatar asked Mar 11 '10 08:03

Tuukka Mustonen


People also ask

Can we use spring data JPA and Hibernate together?

You cant actually use both of them in the same application. For backwards compatibility. We are expanding our application and want to start using Spring Data JPA, but still keep the old hibernate implementation. Its better you develop your new application as a separate microservice and use spring data jpa ..

What is spring DataSource initialization mode?

Spring Boot automatically creates the schema of an embedded DataSource . This behaviour can be customized by using the spring.datasource.initialization-mode property. For instance, if you want to always initialize the DataSource regardless of its type: spring.datasource.initialization-mode=always.

Does Spring Boot starter data JPA include Hibernate?

By default, Spring uses Hibernate as the default JPA vendor. you can see hibernate related dependency in dependency hierarchy under the pom. xml, this will resolve all dependencies of your project. Save this answer.


2 Answers

You can write a unit test to populate the database, using JPA and plain Java. This test would be called by Maven as part of the standard build lifecycle. As a result, you would get an fully initialized database, using Maven, JPA and Java as requested.

like image 139
Olivier Croisier Avatar answered Oct 07 '22 23:10

Olivier Croisier


The usual way to do this is to use a SQL script. Then you run a specific bash file that populate the db using your .sql
If you want to be able to programmatically set your DB during the WebApp StartUp you can use a Web Context Listener.
During the initialization of your webContext you can use a Servlet Context Listener to get access to your DAO (Service Layer.. whatever) create your entities and persist them as you use to do in your java code

p.s. as a reference Servlet Life Cycle

If you use Spring you should have a look at the Standard and Custom Events section of the Reference. That's a better way to implement a 'Spring Listener' that is aware of Spring's Context (in the case you need to retrieve your Services form it)

like image 45
mickthompson Avatar answered Oct 08 '22 01:10

mickthompson