我希望在桌面应用程序更新后在嵌入式derby数据库上运行更改。为此,我尝试使用类似于此的alter query创建JPS存储库:
@Repository
public interface DatabaseUpdates {
@Modifying
@Query("alter table my_table add column my_column clob", nativeQuery = true)
void alterMyTableAddMyColumn();
}
并在像这样的更新程序类中使用它
@Component
public class DatabaseUpdater {
@Autowired
private DatabaseUpdates databaseUpdates;
private void alterMyTable() {
// some logic that checks it the update needs to happen is here
databaseUpdates.alterMyTableAddMyColumn();
}
}
这会引发NoSuchBeanDefinitionException: No qualifying bean of type DatabaseUpdates
例外。
我还尝试DatabaseUpdates
扩展org.springframework.data.repository.Repository
,但后来在使用什么作为域类型方面遇到了问题。
我正在使用spring-boot-starter-data-jpa
1.2.3.RELEASE。
编辑:这是为了支持旧应用,我正在寻找支持数据库更新的直接方法。数据库迁移工具很棒但不适合此修复。我一直希望这个项目已经使用一个月超过一个月了,并且很快就会将一个项目集成到下一个版本中。
答案 0 :(得分:1)
这听起来像个糟糕的主意。有一些框架,专门为您的用例开发,并受Spring Boot支持,如Flyway和Liquibase。然后,您可以在SQL或Java代码(对于Flyway)或XML,SQL,YAML或JSON文件(对于Liquibase)中指定更改。这些框架将检查哪些迁移是必要的,并且它们还跟踪执行迁移的时间。
答案 1 :(得分:1)
我不会把它放在Spring JPA中。如果你提到它是临时的,也许直接尝试一些JDBC并在数据库上运行查询。尝试记录您在表中所做的更改(类似于liquibase正在执行的操作),因此您不会多次运行查询。
也许在Spring构建DataSource
类DatabaseConfiguration
之前尝试运行它。
@Configuration
@EnableJpaRepositories("")
@EnableTransactionManagement
public class DatabaseConfiguration implements EnvironmentAware {
@Bean(destroyMethod = "close")
public DataSource dataSource(DataSourceProperties dataSourceProperties, ApplicationProperties applicationProperties)
throws SQLException {
LOG.debug("Configuring Datasource");
//some code
alterSchema();
return new HikariDataSource(config);
}
private void alterSchema() {
// JDBC connection and queries to alter the schema
}
}
答案 2 :(得分:0)
虽然不是最佳实践,但您可以暂时使用本机JDBC,从现有DataSource获取连接。如果只添加列,请确保检查对象(列)是否已存在。
答案 3 :(得分:0)
您的存储库可以执行transaction
并使用native query
构建EntityManager
,如以下代码所示
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
@Repository
public class DatabaseUpdates{
@PersistenceContext
private EntityManager entityManager;
//ALTER TABLE `my_table` ADD COLUMN `my_column` VARCHAR(100) AFTER `after_column`;
@Transactional
public void alterMyTableAddMyColumn(String tableName, String columnName,
String columnType, String afterColumnName) {
String query = "ALTER TABLE `" + tableName + "` ADD COLUMN `" + columnName + "` " +
columnType + " AFTER `" + afterColumnName + "`";
entityManager.createNativeQuery(query).executeUpdate();
}
}
您的更新程序类这样调用您的存储库
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
@Component
public class DatabaseUpdater {
@Autowired
private DatabaseUpdates databaseUpdates;
private void alterMyTable() {
// some logic that checks it the update needs to happen is here
String tableName = "my_table";
String columnName = "my_column";
String columnType = "VARCHAR(100)";
String afterColumnName = "after_column";
databaseUpdates.alterMyTableAddMyColumn(tableName, columnName,
columnType, afterColumnName);
}
}