我想知道在应用程序启动之前加载初始数据库数据的最佳方法是什么?我正在寻找的东西将使我的H2数据库充满数据.
例如,我有一个域模型"用户"我可以通过转到/ users来访问用户,但最初在数据库中不会有任何用户,所以我必须创建它们.反正有没有自动填充数据库?
目前我有一个容器实例化的Bean,并为我创建用户.
例:
@Component
public class DataLoader {
private UserRepository userRepository;
@Autowired
public DataLoader(UserRepository userRepository) {
this.userRepository = userRepository;
LoadUsers();
}
private void LoadUsers() {
userRepository.save(new User("lala", "lala", "lala"));
}
}
Run Code Online (Sandbox Code Playgroud)
但我非常怀疑这是最好的方法.或者是吗?
我正在使用带有使用 Spring Boot 的文件的 H2 数据库。
在我的 application.properties 中,我有这个条目:
spring.datasource.url=jdbc:h2:file:c:/Testprojekte/spring-boot-h2-db
但是现在我希望能够在运行应用程序时查看数据库,目前这是不可能的,因为我需要让数据库在服务器模式下运行才能这样做。在文档中,我发现我必须将 AUTO_SERVER=TRUE 添加到 URL 中,但这并不能解决问题。
那么,我需要更改什么才能同时从不同的进程连接到该数据库?
谢谢你的帮助!托尔斯滕
我试过谷歌搜索,但几乎所有这类问题的解决方案是添加;DB_CLOSE_DELAY=-1
,但它并没有为我解决任何问题.
这是我的测试课
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Main.class})
public class Testas {
@Autowired
@Qualifier("managerImplementation")
private ClassifierManager manager;
@Test
public void testManager(){
ClassifierGroupEntity cge = new ClassifierGroupEntity();
manager.saveClassifierGroup(cge);
}
}
Run Code Online (Sandbox Code Playgroud)
经理班
@Service("managerImplementation")
public class ClassifierManagerImpl implements ClassifierManager{
@Autowired
private ClassifierGroupEntityRepository groupEntityRepository;
@Autowired
private ClassifierEntityRepository entityRepository;
@Autowired
private ClassifierValueEntityRepository valueEntityRepository;
@Override
public ClassifierGroupEntity getClassifierGroup(long id) {
return groupEntityRepository.findOne(id);
}
@Override
public ClassifierGroupEntity getClassifierGroup(String code) {
return groupEntityRepository.findByCode(code);
}
@Override
public ClassifierGroupEntity saveClassifierGroup(ClassifierGroupEntity entity) {
return groupEntityRepository.save(entity);
}
@Override
public void deleteClassifierGroup(long id) …
Run Code Online (Sandbox Code Playgroud) 按照Exposed提供的示例,我无法在创建它的事务之外读取创建的表/数据.我正在使用h2-in-memory数据库.
例外是:
Exception in thread "main" org.h2.jdbc.JdbcSQLException: Table "CITIES" not found; SQL statement:
Run Code Online (Sandbox Code Playgroud)
我已经添加了一个提交调用,但这没有帮助.如果我在创建数据的事务中读取数据,就像在github链接上的示例一样,它可以正常工作.这是它的简化版本:
fun main(args: Array<String>) {
Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")
transaction {
create(Cities)
City.new {
name = "St. Petersburg"
}
println("Cities: ${City.all().joinToString { it.name }}")
//I have added this commit here
commit()
}
//I want to read the data outside the transaction, but it does not work
transaction {
println("Cities: ${City.all().joinToString { it.name }}")
}
}
Run Code Online (Sandbox Code Playgroud)
我该如何保存数据?
添加logger.addLogger(StdOutSqlLogger)
提供以下输出:
SQL: CREATE TABLE IF NOT EXISTS …
Run Code Online (Sandbox Code Playgroud) 我知道 H2 有一个名为 的布尔属性/设置DATABASE_TO_UPPER
,您至少可以在连接 URL 中设置它,如下所示:;DATABASE_TO_UPPER=false
我想将其设置为 false,但在我的 Spring Boot 应用程序中,我没有在任何地方明确拥有 H2 连接 URL。不过,正如我在日志中看到的那样,确实有一个连接 URL:
o.s.j.d.e.EmbeddedDatabaseFactory: Shutting down embedded database:
url='jdbc:h2:mem:2fb4805b-f927-49b3-a786-2a2cac440f44;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false'
Run Code Online (Sandbox Code Playgroud)
所以问题是,DATABASE_TO_UPPER
在这种情况下告诉 H2 禁用的最简单方法是什么?在使用EmbeddedDatabaseBuilder
(见下文)创建 H2 数据源时,我可以在代码中执行此操作吗?或者在application properties
也许?
这是在代码中显式初始化 H2 数据库的方式:
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScripts("db/init.sql", "db/schema.sql", "db/test_data.sql")
.build();
}
}
Run Code Online (Sandbox Code Playgroud)
另外,我告诉 JPA/Hibernate 不要自动生成嵌入式数据库(没有这个,就会出现两个内存数据库启动的问题):
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
Run Code Online (Sandbox Code Playgroud) 我经常遇到同样的问题:我想使用内存数据库对我的 DAO 执行单元测试。我正在使用 H2,但我相信问题与 HSQLDB 几乎相同。我的单元测试涉及三个步骤:
在非常简单的情况下,可以对所有三个步骤使用完全相同的连接,但是一旦事情变得稍微复杂一点(例如,当使用查询数据库的框架而不是使用直接的PreparedStatements时),每个步骤一个连接需要执行步骤。
问题:一旦连接关闭,数据库似乎就会被删除。怎么解决呢?
我有一些简短的单元测试,但失败了:
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement
::
Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
::
Caused by: org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-197]
Run Code Online (Sandbox Code Playgroud)
来源是我的Spring Data AuditProvider,特别是以下行:
user = entityManager.createNamedQuery("findUserByUsernameAndTenant", User.class)
.setParameter("tenant", TenantService.DEFAULT_TENANT_ID)
.setParameter("username", UserService.USER_SYSTEM).getSingleResult();
Run Code Online (Sandbox Code Playgroud)
仅在执行整个测试套件时才发生错误,而仅在运行此测试类时才发生。
这是我正在使用的TestRunner等:
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@Rollback
public class MyTest {
Run Code Online (Sandbox Code Playgroud)
那是我的数据源URL:
spring.datasource.url: 'jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'
Run Code Online (Sandbox Code Playgroud)
因此,看来“ DB_CLOSE_ON_EXIT”不能解决问题,知道这是怎么回事吗?
更新:
我刚刚意识到,只有在Eclipse中运行测试时才会发生这种情况,但是它们是在命令行中运行的。虽然我偶尔会得到:
o.s.b.f.support.DisposableBeanAdapter : Invocation of destroy method failed on bean with …
Run Code Online (Sandbox Code Playgroud) h2 ×5
java ×4
spring ×4
spring-boot ×4
jdbc ×2
junit ×1
kotlin ×1
spring-data ×1
transactions ×1
unit-testing ×1