Skip to content

Commit

Permalink
Fix schema generator when mapped entity contains property placeholder (
Browse files Browse the repository at this point in the history
…#3237)

* Fix schema generator when mapped entity contains property placeholder

* Fix tests

* Fix tests and move to jdbc-example-java

* Try to improve test coverage
  • Loading branch information
radovanradic authored Nov 25, 2024
1 parent b0216d0 commit fa9d9f7
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 6 deletions.
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();
}
}

0 comments on commit fa9d9f7

Please sign in to comment.