【问题标题】:Hibernate/JPA OneToOne shared key without generated value没有生成值的休眠/JPA OneToOne 共享密钥
【发布时间】:2020-08-03 12:30:22
【问题描述】:

使用:SpringBoot、Kotlin 和 Hibernate/JPA、MariaDB(认为没关系)

我对 Hibernate/JPA 感到好奇(但我希望 Hibernate 可以解决我的问题),以下代码不起作用,我收到了这个错误:

java.sql.SQLException: Column 'book_id' cannot be null
Query is: insert into book_detail (pages, book_id) values (?, ?), parameters [48,<null>]

书.kt

@Entity
data class Book(

  @Id
  val id: Int = 0,

  val name: String? = null

) : Serializable {

  @OneToOne(mappedBy = "book", cascade = [CascadeType.ALL])
  var details: BookDetail? = null

}

BookDetails.kt

@Entity
@Table(name = "book_detail")
data class BookDetail(

  @Column(name = "pages")
  var pages: Int? = null,

  @Id
  @OneToOne
  @JoinColumn(name = "book_id")
  var book: Book? = null

) : Serializable

但是,如果我在 Book.kt 的主键上添加一个 generatedValue,那么它将起作用并持久化实体。

书.kt

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 val id: Int = 0

但我不想让 Hibernate 生成 ID,当我在 IDE 中检查时,我可以看到所有实体都已正确设置(Book BookDetails 之间的链接似乎很好)

那么为什么它使用自动生成的 ID 而不是我自己设置的 ID?

用于持久化实体的代码:

 val id = 2
 val book = repo.findById(id).orElse(Book(id = id))
 book.name = "Book B"

 val details = BookDetail(48)
 details.book = book

 book.details = details

 repo.save(book)

【问题讨论】:

  • 为什么 id 首先可以为空?尝试将其更改为标准的不可为空的 Kotlin 类型。 ` @Id val id: Int,`
  • 是的,我第一次尝试时它不是 null,但它没有任何区别,仍然得到相同的错误。

标签: java hibernate spring-boot jpa kotlin


【解决方案1】:

首先,ID 不应为空,因为这与 ID 的概念相矛盾。

我认为您正在寻找的是嵌入式 ID:

@Embeddable
data class BookId(val value: Long) : Serializable

@Entity
data class Book(
  @EmbeddedId
  @AttributeOverride(name = "value", column = Column(name = "book_id"))
  val id: BookId(0),
  val name: String? = null
)

您通过创建BookId 对象并将其传递给构造函数来设置 ID:

val myBook = Book(BookId(42), "Moby Dick")

不要忘记为 ID 类实现 AttributeConverter

@Converter
class BookIdConverter : AttributeConverter<BookId, Long> {
  override fun convertToDatabaseColumn(bookId: BookId): Long = bookId.value
  override fun convertToEntityAttribute(dbId: Long) = BookId(dbId)
}

【讨论】:

  • 你能提供转换器的完整代码和用法吗?我现在很难使用 Long 设置 ID,因为类型现在是构造函数中的 BookId
  • 经过几次尝试,转换器似乎没有被调用。我在 EmbeddedId 的 ID 上添加了这一行:@Convert(attributeName = "value", converter = BookIdConverter::class) 但出现了一个新错误:MappingException: No type name
猜你喜欢
  • 2013-11-23
  • 2021-06-25
  • 2012-07-30
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 2017-10-28
  • 2019-01-27
相关资源
最近更新 更多