Quarkus 以及如何实现内存、实体和 DAO

问题描述

我目前正在将我的数据库层(实体和 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 取决于您。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...