【发布时间】:2021-09-22 03:37:54
【问题描述】:
我正在松散地遵循 springboot 教程来构建我的第一个 springboot API。
我在尝试运行存储库测试时遇到错误:
@Test
fun `savePattern - expect saved`() {
val name = "test pattern"
val chunkSize = 8
val rows = 8
val columns = 8
val frame = Frame(listOf(1, 0, 1))
val pattern = Pattern(name, rows, columns, chunkSize, setOf(frame))
entityManager.persist(pattern)
entityManager.flush()
val found = patternRepository.findByIdOrNull(pattern.id)
assertThat(pattern).isEqualTo(found)
}
使用仓库接口:
interface PatternRepository : CrudRepository<Pattern, Long> {
fun findByIdOrNull(id: Long?): Pattern?
}
还有我的实体模式:
@Entity
class Pattern(
var name: String,
var rows: Int,
var columns: Int,
var chunkSize: Int,
@OneToMany(targetEntity = Pattern::class) var frames: Set<Frame>,
@Id @GeneratedValue var id: Long? = null
)
及相关实体Frame:
@Entity
class Frame(
@ElementCollection
// @OrderColumn
var data: List<Int>,
@Id @GeneratedValue var id: Long? = null
)
当我尝试触发测试时,我收到错误:
无法为公共抽象 com.lightinspiration.matrixanimator.domain.Pattern com.lightinspiration.matrixanimator.repository.PatternRepository.findByIdOrNull(java.lang.Long) 创建查询!原因:无法为方法 public abstract com.lightinspiration.matrixanimator.domain.Pattern com.lightinspiration.matrixanimator.repository.PatternRepository.findByIdOrNull(java.lang.Long) 创建查询!没有找到类型 Pattern 的属性 null!;嵌套异常是 java.lang.IllegalArgumentException:无法为方法 public abstract com.lightinspiration.matrixanimator.domain.Pattern com.lightinspiration.matrixanimator.repository.PatternRepository.findByIdOrNull(java.lang.Long)创建查询!没有找到类型 Pattern 的属性 null!
我知道这个错误消息对于有 kotlin 和/或 java 经验的人来说可能非常清楚,但它让我陷入了一个循环。
这是说没有找到类型 Pattern! 的属性 null,但我不确定它所指的 null 属性是什么。另外,如果我定义了一个可以返回 null 的方法接口,为什么 spring 会寻找一个非 null 模式(即Pattern!,或者我误解了错误中的含义?)。我是否在我的代码中定义了错误(我假设我做了:|)
更新
对不起,如果我给人的印象是我没有先浏览文档。我意识到我在原始帖子中没有提供足够的信息。
为了提供更多上下文,我在 persistence with JPA 中关注的 Spring 指南显示了以下测试示例:
@DataJpaTest
class RepositoriesTests @Autowired constructor(
val entityManager: TestEntityManager,
val userRepository: UserRepository,
val articleRepository: ArticleRepository) {
@Test
fun `When findByIdOrNull then return Article`() {
val juergen = User("springjuergen", "Juergen", "Hoeller")
entityManager.persist(juergen)
val article = Article("Spring Framework 5.0 goes GA", "Dear Spring community ...", "Lorem ipsum", juergen)
entityManager.persist(article)
entityManager.flush()
// looking specifically at this line
val found = articleRepository.findByIdOrNull(article.id!!)
assertThat(found).isEqualTo(article)
}
@Test
fun `When findByLogin then return User`() {
val juergen = User("springjuergen", "Juergen", "Hoeller")
entityManager.persist(juergen)
entityManager.flush()
val user = userRepository.findByLogin(juergen.login)
assertThat(user).isEqualTo(juergen)
}
}
并指出:
我们在这里使用 Spring Data 默认提供的 CrudRepository.findByIdOrNull Kotlin 扩展,它是基于 Optional 的 CrudRepository.findById 的可空变体。阅读伟大的 Null 是您的朋友,而不是错误的博文了解更多详细信息。
当我查找底层扩展时,它看起来应该查找 id 或返回 null:
fun <T, ID> CrudRepository<T, ID>.findByIdOrNull(id: ID): T? = findById(id).orElse(null)
我的假设是,当我用CrudRepository 扩展我的PatternRepository 时,内置的findByIdOrNull 扩展将被添加到我的存储库中,并可用于查找ID。
这就是我对错误消息感到困惑的原因。我的存储库设置了正确的T 和ID 类型,我使用匹配ID 类型的ID 调用findByIdOrNull,所以我认为这会触发底层扩展方法。很高兴看到有关 JPA 如何构建查询的更多详细信息,但我不认为查询构建是我正在努力解决的问题。
【问题讨论】:
-
你的pattern.id是否为空...?
标签: spring-boot hibernate kotlin