Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix schema generator when mapped entity contains property placeholder #3237

Merged
merged 5 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import io.micronaut.context.BeanLocator;
import io.micronaut.context.annotation.Context;
import io.micronaut.context.env.Environment;
import io.micronaut.context.env.PropertyPlaceholderResolver;
import io.micronaut.context.exceptions.ConfigurationException;
import io.micronaut.context.exceptions.NoSuchBeanException;
import io.micronaut.core.annotation.Internal;
Expand Down Expand Up @@ -61,16 +63,21 @@ public class SchemaGenerator {

private final List<DataJdbcConfiguration> configurations;
private final JdbcSchemaHandler schemaHandler;
private final PropertyPlaceholderResolver propertyPlaceholderResolver;

/**
* Constructors a schema generator for the given configurations.
*
* @param configurations The configurations
* @param schemaHandler The schema handler
* @param environment The environment
*/
public SchemaGenerator(List<DataJdbcConfiguration> configurations, JdbcSchemaHandler schemaHandler) {
public SchemaGenerator(List<DataJdbcConfiguration> configurations,
JdbcSchemaHandler schemaHandler,
Environment environment) {
this.configurations = configurations == null ? Collections.emptyList() : configurations;
this.schemaHandler = schemaHandler;
this.propertyPlaceholderResolver = environment.getPlaceholderResolver();
}

/**
Expand Down Expand Up @@ -115,14 +122,14 @@ public void createSchema(BeanLocator beanLocator) {
for (String schemaName : configuration.getSchemaGenerateNames()) {
schemaHandler.createSchema(connection, dialect, schemaName);
schemaHandler.useSchema(connection, dialect, schemaName);
generate(connection, configuration, entities);
generate(connection, configuration, propertyPlaceholderResolver, entities);
}
} else {
if (configuration.getSchemaGenerateName() != null) {
schemaHandler.createSchema(connection, dialect, configuration.getSchemaGenerateName());
schemaHandler.useSchema(connection, dialect, configuration.getSchemaGenerateName());
}
generate(connection, configuration, entities);
generate(connection, configuration, propertyPlaceholderResolver, entities);
}
} catch (SQLException e) {
throw new DataAccessException("Unable to create database schema: " + e.getMessage(), e);
Expand All @@ -136,14 +143,15 @@ public void createSchema(BeanLocator beanLocator) {

private static void generate(Connection connection,
DataJdbcConfiguration configuration,
PropertyPlaceholderResolver propertyPlaceholderResolver,
PersistentEntity[] entities) throws SQLException {
Dialect dialect = configuration.getDialect();
SqlQueryBuilder2 builder = new SqlQueryBuilder2(dialect);
if (dialect.allowBatch() && configuration.isBatchGenerate()) {
switch (configuration.getSchemaGenerate()) {
case CREATE_DROP:
try {
String sql = builder.buildBatchDropTableStatement(entities);
String sql = resolveSql(propertyPlaceholderResolver, builder.buildBatchDropTableStatement(entities));
if (DataSettings.QUERY_LOG.isDebugEnabled()) {
DataSettings.QUERY_LOG.debug("Dropping Tables: \n{}", sql);
}
Expand All @@ -156,7 +164,7 @@ private static void generate(Connection connection,
}
}
case CREATE:
String sql = builder.buildBatchCreateTableStatement(entities);
String sql = resolveSql(propertyPlaceholderResolver, builder.buildBatchCreateTableStatement(entities));
if (DataSettings.QUERY_LOG.isDebugEnabled()) {
DataSettings.QUERY_LOG.debug("Creating Tables: \n{}", sql);
}
Expand All @@ -174,6 +182,7 @@ private static void generate(Connection connection,
try {
String[] statements = builder.buildDropTableStatements(entity);
for (String sql : statements) {
sql = resolveSql(propertyPlaceholderResolver, sql);
if (DataSettings.QUERY_LOG.isDebugEnabled()) {
DataSettings.QUERY_LOG.debug("Dropping Table: \n{}", sql);
}
Expand All @@ -192,6 +201,7 @@ private static void generate(Connection connection,

String[] sql = builder.buildCreateTableStatements(entity);
for (String stmt : sql) {
stmt = resolveSql(propertyPlaceholderResolver, stmt);
if (DataSettings.QUERY_LOG.isDebugEnabled()) {
DataSettings.QUERY_LOG.debug("Executing CREATE statement: \n{}", stmt);
}
Expand All @@ -215,4 +225,18 @@ private static void generate(Connection connection,
}
}
}

/**
* Resolves property placeholder values if there are any.
*
* @param propertyPlaceholderResolver The property placeholder resolver
* @param sql The SQL to resolve placeholder properties if there are any
* @return The resulting SQL with resolved properties if there were any
*/
private static String resolveSql(PropertyPlaceholderResolver propertyPlaceholderResolver, String sql) {
if (sql.contains(propertyPlaceholderResolver.getPrefix())) {
return propertyPlaceholderResolver.resolveRequiredPlaceholders(sql);
}
return sql;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ trait H2TestPropertyProvider implements TestPropertyProvider {
}

Map<String, String> getProperties() {
return shouldAddDefaultDbProperties()? getH2DataSourceProperties("default") : [:]
return shouldAddDefaultDbProperties() ? getH2DataSourceProperties("default") : [:]
}

Map<String, String> getH2DataSourceProperties(String dataSourceName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package io.micronaut.data.jdbc.h2.identity

import io.micronaut.context.annotation.Property
import io.micronaut.data.jdbc.h2.H2DBProperties
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.Specification

@H2DBProperties
@Property(name = "datasources.default.packages", value = "io.micronaut.data.jdbc.h2.identity")
@Property(name = "datasources.default.batch-generate", value = "true")
@MicronautTest
class SameIdentityRepositorySpec extends Specification {
@Inject
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package example;

import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;

@MappedEntity("${entity.prefix}entity")
public record CustomEntity(
@Id
@GeneratedValue
Long id,
String name) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package example;

import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;

@JdbcRepository(dialect = Dialect.H2)
public interface CustomEntityRepository extends CrudRepository<CustomEntity, Long> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ datasources:
password: ''
schema-generate: CREATE_DROP
dialect: H2
entity:
prefix: demo_
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package example;

import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

@MicronautTest
class CustomEntityRepositorySpec {

@Inject
CustomEntityRepository repository;

@Test
void testSaveAndFind() {
CustomEntity entity = repository.save(new CustomEntity(null, "Entity1"));
CustomEntity found = repository.findById(entity.id()).orElse(null);
Assertions.assertNotNull(found);
Assertions.assertEquals(entity.name(), found.name());
Assertions.assertEquals(1, repository.count());
Assertions.assertFalse(repository.findAll().isEmpty());
repository.deleteAll();
}
}
Loading