Writing database migration scripts is a time-consuming and error-prone task. JPA Buddy can save you a lot of time thanks to advanced database analysis and Flyway migrations generation. Watch the video and figure it out!
Estimated Reading Time: less than 10 mins
As your application's JPA data model evolves, so does the database. To manage database versioning, tools like Flyway come into play. JPA Buddy simplifies Flyway migration generation, provides control over changes that may cause problems, and manages Java-to-database type mappings.
In this guide, you will create a simple blog application, learn how to make JPA Data Model changes, and update your database accordingly using JPA Buddy and Flyway.
You will learn how to:
You can find the code of this application on github.
First, you will go through a few steps to set up a new project. In this section, you will:
Start by creating a Spring Boot application using Spring Initializr.
- Java 17 as the programming language
- Gradle - Groovy as the build tool
- The latest stable version of Spring Boot
- The application will be packaged as a JAR file
- Spring Data JPA enables us to use JPA and Data Repositories
- PostgreSQL Driver provides database access
- Flyway Migration manages database changes
These dependencies enable you to use JPA Buddy’s functionalities with Flyway and access a PostgresSQL database.
Here are the selected settings in Spring Initializr:
Download the created project and open it in IntelliJ IDEA by clicking on File → Open.
To manage script execution, enable Flyway’s commands in gradle. Add the following plugin id and your database’s details in your build.gradle
file:
plugins {
id 'org.flywaydb.flyway' version '9.21.1'
}
flyway {
url = 'jdbc:postgresql://localhost:5432/blog'
user = 'postgres'
password = 'password'
}
Click on the Load Gradle Changes icon to apply those changes to your project.
To connect your application to the database, you need to:
You can use JPA Buddy To set up a new connection through the JPA Structure tab:
Add a new connection by clicking on the + button and choose PostgreSQL.
Type the following information in the invoked window:
Note that your values may vary depending on your local environment.
To check if your database works as intended click on Test Connection, it should display Succeeded
if your database is properly configured and actively listening on its assigned port.
Click OK.
Next, provide the necessary datasource details to your application in the application.properties
file under the resources
folder:
application.properties
fileJPA Buddy automatically detects the existing datasource.
Hibernate will validate your schema with your entity mappings during startup, if you set the Hibernate DDL-auto property to validate
.
The Show/Format SQL options allow you to view formatted SQL logs on your terminal.
The mentioned settings generate the following properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/blog
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driverClassName=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
The blog application you will build consists of two tables:
user
: table for storing blog user informationpost
: table for storing blog postsThe relationship between post
and user
is OneToMany
, meaning that multiple posts can be associated with a single user.
Let’s create the User
entity using JPA Structure:
Type the name of your entity in the invoked window and add .entities
to the package name, choose the Id type and the desired Id generation method.
Click OK.
You can find your newly created entity in the entities
package in your project panel.
You can use JPA Designer to create your entity’s attributes:
User
source code from the project panelPick your attributes type, write its name, and JPA Buddy will automatically name your table’s column according to naming conventions.
Click OK.
These instructions will create a firstName
attribute with its getter and setter.
Using these tools, you can create the following entities.
User
entity:
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email")
private String email;
@Column(name = "fax")
private String fax;
}
Post
entity:
@Entity
@Table(name = "post")
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "title")
private String title;
@Column(name = "text", length = 10000)
private String text;
@Column(name = "published_at")
private Instant publishedAt;
// getters and setters have been omitted for brevity
}
You will need an author
attribute in your Post
entity to reference the User
entity:
Post
entity's source codeUser
as the attribute’s typeauthor
ManyToOne
cardinalityClick OK.
The generated author
attribute represents the linked User
entity and should look as follows:
@ManyToOne
@JoinColumn(name = "author_id")
private User author;
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
The @JoinColumn
annotation indicates that the author_id
column in the database is used as a foreign key.
To create tables within the connected database, you will need to generate an initial schema based on your entity model. In this section, you will:
JPA Buddy can generate an initialization script to define your database schema, based on your current entity model:
Check Model to generate a schema from your entity model, then select the corresponding SQL dialect. In this case, PostgreSQL.
Click OK.
In the following window, you can review and adjust the auto-generated init script. Rename your script to V1__baseline_migration
, JPA Buddy will include your migration script in the generated db/migration
folder as your default migration folder.
Click OK.
Now you need to run the script and implement the changes in the database, to do that:
You can view the newly created tables in the Database tab.
In this section, you will learn how to make the following changes to your existing JPA model:
Comment
entityLet’s start by modifying the email
attribute. Use JPA Designer to make it into a mandatory field:
User
source codeemail
in your codeThis will add a nullable = false
to your @Column
annotation.
JPA Buddy allows you to add an associated attribute and create its type in the same wizard. Let's create a Comment
entity and link it to the Post
entity with a OneToMany
relationship:
Post
source codeCreate a Comment
entity by clicking on the + button to invoke the New Entity wizard. Enter the entity’s name, and JPA Buddy will autofill the rest. Click OK to exit the wizard.
Set the attribute’s name and choose a OneToMany
relationship. JPA Buddy will suggest generating equals
and hashcode
methods for the new entity for better performance. Click on Generate equals() and hashcode() then hit OK.
Finally, add an inverse attribute for bidirectional navigation. Click the Mapped By field → select create inverse attribute. JPA Buddy auto-generates its name and column based on the Post
entity. Click OK to exit the Create Mapped Attribute window.
Once you've clicked OK again, these steps will create an attribute in your Post
entity to define a OneToMany
relationship with the Comment
entity:
@OneToMany(mappedBy = "post", orphanRemoval = true)
private Set<Comment> comment = new LinkedHashSet<>();
And a Comment
entity in the entities
package:
@Entity
@Table(name = "comment")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
// getters and setters have been omitted for brevity
}
Your comments should include text content, a creation date, and the user who authored them. Let's generate these attributes following the same steps defined in the Creating Entities section.
@Column(name = "data")
private Instant data;
@Column(name = "text")
private String text;
@ManyToOne
@JoinColumn(name = "commentator_id")
private User commentator;
Delete the fax
attribute in the User
entity to reflect it in the migration script later.
You made some changes to your entities and need to implement those changes in your database. In this section, you will:
To generate a flyway versioned migration, click on the + button in the JPA Structure → select Flyway Versioned Migration.
JPA Buddy sets the source to Model to propagate all modifications from the model to the database.
Click OK.
In the Flyway Versioned Migration Preview window, name your migration script. Notice that statements are color-coded: green for safe changes, yellow for potential failures requiring attention, and red for changes risking irreversible data loss.
JPA Buddy lets you assign a default value, like n/a
for all blank emails before setting a not-null restriction:
user#email Add Not Null Constraint
statementn/a
in the Set value fieldTo prevent accidental deletion of unmapped columns, add them to the ignore list. Drag user#fax Drop Column
’s changeset to the ignore list.
Click OK to reflect the model's changes in the migration script.
Execute these changes to implement them in the database as in the Generating an Init Script section using Flyway gradle commands.
Thus far, you've learned how to use JPA Buddy to manage your database schema changes using Flyway. This includes creating entities, establishing relationships, adding attributes, and generating migration scripts. With these skills, you're able to handle database versioning effectively.