Общий ключ Hibernate / JPA OneToOne без сгенерированного значения - PullRequest
0 голосов
/ 21 апреля 2020

Использование: 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>]

Book.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 сгенерированного значения, затем он будет работать и сохранять сущности.

Book.kt

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

Но я не хочу, чтобы Hibernate генерировал идентификатор, когда я проверяю в моей IDE я вижу, что все объекты установлены правильно (связь между Book <-> BookDetails кажется товаром)

Так почему же он работает с автоматически сгенерированным идентификатором, а не когда я сам устанавливаю идентификатор?

Код, используемый для постоянных сущностей:

 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)

1 Ответ

0 голосов
/ 21 апреля 2020

Во-первых, идентификатор не должен быть обнуляемым, так как это противоречило бы идее идентификатора.

Я думаю, что вам нужен встроенный идентификатор:

@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 объект и передавая его конструктору:

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

Не забудьте реализовать AttributeConverter для класса ID:

@Converter
class BookIdConverter : AttributeConverter<BookId, Long> {
  override fun convertToDatabaseColumn(bookId: BookId): Long = bookId.value
  override fun convertToEntityAttribute(dbId: Long) = BookId(dbId)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...