Repository based database access.
| Name | Description |
|---|---|
| Repository | Annotated interface with methods named according to a specification; implementation is code generated |
| Provider | A persistence provider that provides a codegen to generate repository implementations, and runtime to handle methods |
| Data Source | A named service implementing a data source contract (such as javax.sql.DataSource) |
| Persistence unit | A named configurable component used by a Provider, such as JPA Persistence Unit |
Summary for SQL based:
- (1 - n) Databases (not part of Helidon code or configuration)
- (1 - n) Data Sources - each represents a connection (or connection pool) to a Database (m : n)
- (1 - n) Persistence Units - each represents an approach of invoking statements on the connection, and uses a Data Source (m : n)
- (1 - n) Entities - each represents a table in a Database (0 - 1 : 1) / there may be a table that does not have an entity
- (1 - n) Repository interfaces - each represents operations on an Entity (0 - 1 : 1) / there may be an entity that does not have a repository
- (1 - n) Repository implementations - for each persistence unit provider that is on codegen path
Each configured data source is available in ServiceRegistry under its configured name. There can be one data source that is
unnamed of each data source type (such as javax.sql.DataSource).
Data sources are expected to be used by Persistence units.
A Provider codegen module generates implementations of Repository interfaces.
For each repository, there is a named instance with the provider name (i.e. jakarta-persistence), and an unnamed instance
with the weight of provider.
Repository interface may have a Data.Provider annotation with the Provider name, to limit code generation only to that
provider.
User chooses at injection time which instance they desire (if there is more than one option). If an unnamed instance is injected,
the one with the highest weight will be used. They can also use @Service.Named("...") with the provider name to inject
the specific provider based instance.
Each provider may require additional configuration. This is achieved through a persistence unit, which is expected to
reference a Data Source to be used, and possible additional configuration (such as JPA properties).
Repository interface may have a Data.Pu annotation with the persistence unit name, to require a named PU at runtime.
Note that the PU must be of the same type as the Provider
There are following new nodes in the configuration:
data.sources.sql- a list of SQL data sources (implementjavax.sql.DataSource)data.persistence-units- a section for persistence unitsdata.persistence-units.jakarta- a list of Jakarta Persistence units configurations
An example of Helidon Data persistence unit with custom database connection.
data:
persistence-units:
jakarta:
- connection:
username: "user"
password: "changeit"
url: "jdbc:mysql://localhost:3306/pets"
jdbc-driver-class-name: "com.mysql.cj.jdbc.Driver"
init-script: "init.sql"
properties:
eclipselink.target-database: "MySQL"
eclipselink.target-server: "None"
jakarta.persistence.schema-generation.database.action: "drop-and-create"An example of Helidon Data persistence unit with DataSource. In this configuration, DataSource is defined in a separate node
and persistence unit references just the name of this DataSource. Configured DataSource is available in the ServiceRegistry
and also trough JNDI to be available for Jakarta Persistence provider, such as EclipseLink and Hibernate.
data:
sources:
sql:
- name: "example"
provider.hikari:
username: "user"
password: "changeit"
url: "jdbc:mysql://localhost:3306/pets"
jdbc-driver-class-name: "com.mysql.cj.jdbc.Driver"
persistence-units:
jakarta:
- data-source: "example"
init-script: "init.sql"
drop-script: "drop.sql"
properties:
jakarta.persistence.schema-generation.database.action: "drop-and-create"Always
- Repository instance annotated with
@Data.Repository, named with provider name, or unnamed
When helidon-data-sql-datasource is on classpath (and at least one provider of it, such as hikari or ucp)
javax.sql.DataSourcefor eachdata.sources.sqlconfiguration (named or unnamed)io.helidon.data.sql.datasource.DataSourceConfigFactory.SQL_DATA_SOURCES_CONFIG_KEY
When helidon-data-jakarta-persistence is on classpath
jakarta.persistence.EntityManagerFactoryfor eachpersistence-untis.jakartaconfiguration (named or unnamed)io.helidon.data.jakarta.persistence.PersistenceUnitFactory.JPA_PU_CONFIG_KEYjakarta.persistence.EntityManagerdtto., this should be injected as aSupplier<EntityManager>for cases that require it being closed; note that@PersistenceContextannotation is NOT supported in Helidon Data, only@Service.Inject
We need to support test containers running on random ports.
This will be supported by defining a single SQL data source, such as:
# this section is required for our testcontainer support
test.database:
username: "test"
password: "changeit"
url: "jdbc:mysql://localhost:3306/testdb"
# this section is the usual Helidon Data setup of data sources and persistence units
data:
sources:
sql:
- name: "test"
provider.hikari:
username: "${test.database.username}"
password: "${test.database.password}"
url: "${test.database.url}"
persistence-units:
jakarta:
- data-source: "test"This information will be read by io.helidon.data.sql.testing.SqlTestContainerConfig.configureContainer(io.helidon.config.Config, org.testcontainers.containers.JdbcDatabaseContainer<?>) and a container will be initialized with it.
The method returns a TestContainerHandler that can be used to start and stop the container, and to get the new mapped port. Its method setConfig() can be called to register the config instance with updated port numbers in ServiceRegistry