Load Hibernate ORM schemas into an Atlas project.
- Declarative migrations - use a Terraform-like
atlas schema apply
to apply your Hibernate schema to the database. - Automatic migration planning - use
atlas migrate diff
to automatically plan a migration from
the current database version to the schema declared by the code.
Install Atlas from macOS or Linux by running:
curl -sSf https://atlasgo.sh | sh
See atlasgo.io for more installation options.
Add the provider to your Gradle project:
plugins {
id("io.atlasgo.hibernate-provider-gradle-plugin") version "0.1"
}
This plugin adds a task named schema
to the project. Running this task will print the schema generated by
Hibernate using entities and configurations taken from the runtime classpath.
The task implements the JavaExec
task and the plugin does not make any configuration or dependency changes to the project.
Let's check that the task works by running the following command:
./gradlew -q schema
To add the provider to your project, you need to add the hibernate-provider-maven-plugin
plugin to the pluginManagement
section in your pom.xml
:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>io.atlasgo</groupId>
<artifactId>hibernate-provider-maven-plugin</artifactId>
<version>0.3.8</version>
</plugin>
</plugins>
</pluginManagement>
</build>
A complete example can be seen in the examples folder.
The plugin adds a MOJO with a goal named 'schema' to your project.
You should add the plugin to
pluginManagement
as it is not meant to be running in any specific phase of the build process.
Let's check that the goal is installed correctly by running:
mvn help:describe -Dplugin=hibernate-provider -Dgoal=schema
By default, the task is configured to scan the entire runtimeClasspath
configuration and look for Jakarta (JPA) entities.
The task does not require a database connection, but it does need to configure Hibernate with a specific database dialect.
There are several flags and hooks you can use to configure how Hibernate is being initialized inside the task, we will explore these later.
In your project directory, create a new file named atlas.hcl
with the following contents:
data "external_schema" "hibernate" {
program = [
"./gradlew",
"-q",
"schema"
]
}
env "hibernate" {
src = data.external_schema.hibernate.url
dev = "docker://mysql/8/dev"
migration {
dir = "file://migrations"
}
format {
migrate {
diff = "{{ sql . \" \" }}"
}
}
}
For Maven, change the program field to use mvn
instead of gradlew
:
data "external_schema" "hibernate" {
program = [
"mvn",
"compile",
"-q",
"hibernate-provider:schema"
]
}
The above configuration uses a dev database that is configured to use MySQL.
The SchemaTask
is initializing Hibernate which typically uses the file hibernate.properties
from your project to
determine which dialect it should be using.
If needed, you can override the dialect specification using the --properties
flag.
For example, for PostgreSQL:
- define
jakarta.persistence.database-product-name=PostgreSQL
inhibernate.properties
- define
docker://postgres/15/dev?search_path=public
as atlas dev database inatlas.hcl
Now we can check that the configuration is working by inspecting the schema:
atlas schema inspect -w --env hibernate --url env://src
Both the Gradle and Maven plugins support the following flags:
packages
- List of package names (for exampleorg.example.myservice.model
). If specified, only classes inside these packages will be considered during the entity scan. Given packages must be part of the classpathclasses
- List of classes that will be added to the entity scan explicitly. Ignores thepackages
argument.properties
- Name of a properties file used to override the default properties read by Hibernate.registry-builder
- FQDN of a class that implementsjava.util.Function.Function<java.util.Properties, org.hibernate.service.ServiceRegistry>
. Used when you need to override the defaultServiceRegistry
initialized by the task. Useful if you have a custom initialization process for Hibernate. The properties parameter is the default settings used by the plugin, including ones read from theproperties
parameter.metadata-builder
- FQDN of a class that implementsjava.util.Function.Function<org.hibernate.service.ServiceRegistry, org.hibernate.boot.Metadata>
. Used when you need to override the defaultMetadata
used by the task. mutually exclusive withpackages
andclasses
arguments.enable-table-generators
- Atlas does not currently support generated fields that require data initialization such asGenerationType.SEQUENCE
,GenerationType.TABLE
, andGeneration.AUTO
. By default, the provider will throw an exception if it finds unsupported statements. By enabling this flag, the provider will print the unsupported SQL statements.- Make sure to apply the ignored statements (using
atlas migrate --env hibernate diff --edit
) See more information on manual migrations here
- Make sure to apply the ignored statements (using
You can configure these flags by adding arguments in the external_schema
block in atlas.hcl
:
data "external_schema" "hibernate" {
program = [
"./gradlew",
"--properties", "other.properties"
"--classes", "org.example.model.Person"
"-q",
"schema"
]
}
Or, if you are using Maven:
data "external_schema" "hibernate" {
program = [
"mvn",
"compile",
"-Dproperties", "other.properties"
"-Dclasses", "org.example.model.Person"
"-q",
"hibernate-provider:schema"
]
}
Note: The '-q' flag is important, without it, Gradle/Maven will add additional output
Alternatively, you can define a new Gradle task:
import io.atlasgo.SchemaTask
tasks.register<SchemaTask>("my_schema") {
classes = listOf("org.example.model.Person")
}
And refer to this task in atlas.hcl
:
data "external_schema" "hibernate" {
program = [
"./gradlew",
"-q",
"my_schema"
]
}
Once you have the provider installed, you can use it to apply your Hibernate schema to the database:
You can use the atlas schema apply
command to plan and apply a migration of your database to
your current Hibernate schema. This works by inspecting the target database and comparing it to the
Hibernate schema and creating a migration plan. Atlas will prompt you to confirm the migration plan
before applying it to the database.
atlas schema apply --env hibernate -u "mysql://root:password@localhost:3306/mydb"
Where the -u
flag accepts the URL to the
target database.
Atlas supports a versioned migration
workflow, where each change to the database is versioned and recorded in a migration file. You can use the
atlas migrate diff
command to automatically generate a migration file that will migrate the database
from its latest revision to the current Hibernate schema.
run atlas migrate diff --env hibernate
command and observe the migrations
directory.
If you are using Spring in your project, you will need to import the hibernate-provider
and create a new empty spring application, for example:
@SpringBootApplication
@PropertySource(value = {"classpath:schema-export.properties"})
public class Main {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(Main.class);
}
}
A complete example project is provided here
Try running the example by running:
atlas schema inspect -w --env hibernate --url env://src
inside the project directory.
We need to configure the spring application so that it will print the schema to stdout. Spring is often configured to load Hibernate during startup, by adding the configuration below, we instruct Spring to generate the schema during initialization and print it to stdout:
spring.jpa.properties.jakarta.persistence.schema-generation.database.action=create
spring.jpa.properties.hibernate.schema_management_tool=io.atlasgo.ConsoleSchemaManagementTool
Configuring the driver with dialect and version can be done either via the same configuration file or via a dedicated Bean. For example, in the example project, this configuration is used for MySQL 8:
spring.jpa.properties.jakarta.persistence.database-product-name=MySQL
spring.jpa.properties.jakarta.persistence.database-major-version=8
In your atlas.hcl
file you will need to invoke the Spring application instead of the Gradle/Maven plugin.
This project is licensed under the Apache License 2.0.