问题描述
我目前正在将我的数据库层(实体和 DAO)从 JavaEE 迁移到 Quarkus(或者好吧,从 wls 迁移到 OpenShift)并且无法完全理解一些细节:
目前我有当前的结构:
- 信息类RegisteredTime.java
- 定义列名等的实体类,RegisteredTimeEntity.java,以及匹配的persistence.xml
- MapStruct 映射器类,用于在 RegisteredTime.java 和 RegisteredTimeEntity.java 之间进行映射
- DAO 类使数据库访问更容易,RegisteredTimeDAO.java
- structure.ddl 定义数据库结构
- 扩展 JdbcDaoSupport(springframework)并使用 Derby 的内存类 TestDB.java
我的测试类 RegisteredTimeDAOTest 使用 TestDB 进行内存中:
class RegisteredTimeDAOTest extends Specification {
private RegisteredTimeId registeredTimeId;
private RegisteredTimeData registeredTimeData;
private long userId;
private int userVersion;
private RegisteredTime registeredTime;
private Long userNumber;
private LocalDate startDate,endDate
private Boolean registration
private Boolean registrationApproved
private String registration
private String timeType
private LocalDate incomingDate
@Shared
private EntityManager entityManager
@Shared
private EntityManagerFactory entityManagerFactory
@Shared
private TestDB db
static SingleConnectionDataSource dataSource
private RedovisadTidEntity registeredTimeEntity
private RegisteredTimeDAO instance
private Gson gson
def setupSpec() {
db = new TestDB("test")
db.start()
dataSource = new SingleConnectionDataSource(db.getJDBCUrl(),true)
entityManagerFactory = Persistence.createEntityManagerFactory("EKN-Persistence-Test")
entityManager = entityManagerFactory.createEntityManager()
}
def cleanupSpec() {
if (entityManager != null) {
entityManager.close()
}
if (entityManagerFactory != null) {
entityManagerFactory.close()
}
db.shutdown()
}
def setup() {
userId = 1
userVersion = 1
userNumber = 1991010101011L
startDate = LocalDate.of(2020,01,01)
endDate = LocalDate.of(2020,31)
registration = false
registrationApproved = false
registration = null
timeType = TimeType.STANDARD_TIME;
incomingDate = LocalDate.of(2020,02,03)
registeredTimeId = new RegisteredTimeId(userId,userVersion)
registeredTimeData = RegisteredTimeData.newRegisteredTimeDataBuilder()
.userNumber(userNumber)
.startDate(startDate)
.endDate(endDate)
.registration(registration)
.registrationApproved(registrationApproved)
.timeType(timeType)
.incomingDate(incomingDate)
.build()
registeredTime = new RegisteredTime().newRedovisadTidBuilder()
.registeredTimeId(registeredTimeId)
.registeredTimeData(registeredTimeData)
.build()
registeredTimeEntity = RegisteredTimeMapper.INSTANCE.toRegisteredTimeEntity(registeredTime)
instance = new RegisteredTimeDAO(entityManager)
}
def cleanup() {
instance = null
}
def "Save RegisteredTime"() {
given:
Statement statement = dataSource.getConnection().createStatement()
statement.executeQuery("SELECT * FROM registeredtime")
ResultSet rs = statement.getResultSet()
gson = new Gson()
when:
entityManager.getTransaction().begin()
instance.save(registeredTime)
entityManager.getTransaction().commit()
then:
while (rs.next()) {
assert rs.getInt(2) == userVersion
assert rs.getLong(3) == userNumber
assert gson.fromJson(rs.getString(4),RegisteredTimeData.class).equals(registeredTimeData)
assert rs.getTime(5) != null
}
}
def "Get RegisteredTime"() {
when:
entityManager.getTransaction().begin()
RegisteredTime registeredTimeGet = instance.get(1000,userVersion)
entityManager.getTransaction().commit()
then:
assert registeredTimeGet.getRegisteredTimeId().getAnsokanId() == userId
assert registeredTimeGet.getRegisteredTimeId().getAnsokanVersion() == userVersion
assert registeredTimeGet.getRegisteredTimeData().getKundId() == userNumber
assert registeredTimeGet.getRegisteredTimeData().getFromdatum() == startDate
assert registeredTimeGet.getRegisteredTimeData().getTomdatum() == endDate
assert registeredTimeGet.getRegisteredTimeData().getAnmalanAF() == registration
assert registeredTimeGet.getRegisteredTimeData().getFranvarogodkandAF() == registrationApproved
assert registeredTimeGet.getRegisteredTimeData().getTimeType() == timeType
assert registeredTimeGet.getRegisteredTimeData().getAngavsviddatum() == incomingDate
}
}
我一直潜伏在 quarkus.io 并阅读以下内容:
https://quarkus.io/guides/datasource
https://quarkus.io/guides/hibernate-orm(可能是最重要的)
https://quarkus.io/guides/getting-started (ofc)
https://quarkus.io/guides/gradle-tooling(使用 gradle)
-
我是否必须重写我的 TestDB 或者是否有“开箱即用”的解决方案?我查看了零配置设置(DevServices),但这不允许我配置数据库。我不想再扩展 springframework。
-
如果我在没有 Panache 的情况下使用 Hibernate,我需要 DAO 吗?
解决方法
我假设您使用 Spock 进行测试。
Quarkus 仅支持 JUnit5,因此您应该尝试使用基于 JUnit5 的 Spock 2.0-M5,并在可能的情况下通过其 quarkus-junit5
扩展使用 Quarkus JUnit5 支持。
Quarkus and Spock support 有问题,您可以观看。
请注意,Quarkus 不支持 Groovy 或 Spock。
作为替代,你也可以尝试this Quarkus Spock extension,不知道它的状态是什么,我只是通过谷歌搜索找到的。
关于您的问题:
实体类仍然是必需的,但 EntityManagerFactory 正在 小心,数据源和实体管理器可以被注入, 对吗?
如果您使用的是 Quarkus Hibernate ORM 扩展,则它是常规的 Hibernate 集成,因此是 JPA 实现,因此您需要定义 JPA 实体类。然后你可以注入一个 EntityManager
。您也可以注入 Datasource
,但最好使用 EntityManager
,因为它提供更高级别的集成。
我是否必须重写我的 TestDB 或者是否有“开箱即用” 解决方案?我查看了零配置设置(DevServices),但这 不允许我配置数据库。我不想延长 不再使用 springframework。
如果您可以使用 @QuarkusTest
支持,它将启动您的应用程序,以便您可以使用诸如 H2 或 Derby 之类的内存数据库。有通过 Quarkus 测试资源自动启动 H2 数据库的测试支持,请参阅 Quarkus 测试指南的 Starting services before the Quarkus application starts 部分,该部分解释了如何通过 io.quarkus.test.h2.H2DatabaseTestResource
启动 H2 数据库。
Devservices 也是一个很好的方法,它会在 docker 容器内运行一个真实的数据库,所以如果你没有配置任何数据源而是使用 Quarkus JDBC 扩展之一(例如 quarkus-jdbc-postgresql
),它将在开发和测试中为该数据库运行一个 docker 容器。
另外两件事可以帮助您实现您想要的:Quarkus 支持 flyway 或 liquibase 来管理数据库迁移,并且您可以通过 %test
配置文件拥有特定的测试属性(例如运行专用的 sql 导入测试文件)。
如果我在没有 Panache 的情况下使用 Hibernate,我需要 DAO 吗?
好吧,如果您需要 DAO,我建议将 Hibernate 与 Panache 结合使用,这是一个很好的扩展,可以在您的实体之上轻松实现 DAO。但这取决于您希望如何设计您的应用程序。是否使用 DAO 以及是否为 DAO 使用 Hibernate 和 Panache 取决于您。