Общее поле в составном первичном ключе для внешних ключей - PullRequest
0 голосов
/ 28 мая 2018

В моей базе данных есть 4 таблицы:

+-------------+
|Libraries    |
+-------------+ . . . . . _________
|P code       |                   |
+-------------+                   -
      .                           ^
      .                  +---------------+
      |                  |Persons        |
      |                  +---------------+
      -                  |P  name        |
      ^                  |FP library_code|
+-----------------+      +---------------+
|Books            |              .
+-----------------+              .
|P   title        |              |
|FP  library_code |              |
+-----------------+              -
      .                          ^
      .                 +----------------+  
      |                 |Borrows         |
      +_______________|<+----------------+
                        |FP person_name  |
                        |FP book_title   |
                        |FP library_code |
                        +----------------+

P - primary key
FP - foreign primary key

_
^ - foreign key is part of primary key

Для столбцов Persons и Books код_библиотеки в Borrows должен быть одинаковым (общий столбец)!

Мой код Java выглядит следующим образом:

@Entity
class Library {
    @Id
    private String code;
}

@Embeddable
class PersonId implements Serializable {
    private String name;
    private String library_code;
}

@Entity 
class Person {
    @EmbeddedId 
    private PersonId id;
}

@Embeddable
class BookId implements Serializable {
    private String title;
    private String library_code;
}

@Entity 
class Book {
    @EmbeddedId 
    private BookId id;
}

Можно ли реализовать подобную сущность Borrow с помощью общего столбца library_code для PersonId иBookId, как? :

@Embeddable
class BorrowId implements Serializable {
    private PersonId person;
    private BookId book;
}

@Entity 
class Borrow {
    @EmbeddedId 
    private BorrowId id;
}

Примечание: этот вопрос не о модели базы данных, модель уже предоставлена, и я не могу ее изменить, мне просто нужно найти лучший способ, какчтобы сопоставить его с моделью объекта.

1 Ответ

0 голосов
/ 29 мая 2018

Как уже упоминалось в моем комментарии, вы могли бы сначала использовать @AttributeOverride здесь

@Embeddable
public class BorrowId implements Serializable {
  private PersonId person;
  @AttributeOverride(
    name = "library_code",
    column = @Column(insertable=false, updatable=false) )
  private BookId book;
  // getter/setter(s) with proper equals/hashcode
}

Другой вариант, который вы могли бы рассмотреть, - вывести страницу из доменного дизайна:

@Embeddable
public class BorrowId implements Serializable {
  private String person;
  private String book;
  private String libraryCode;

  // Required by JPA
  // notice its package private
  BorrowId() {}

  public BorrowId(PersonId person, BookId book) {
    // validates you are pairing a person and book with same library codes
    assert person.getLibraryCode().equals( book.getLibraryCode() );
    this.person = person.getName();
    this.book = book.getTitle();
    this.libraryCode = person.getLibraryCode();
  }

  // expose all getters as public 
  // expose all setters as non-public 
  // implement proper equals/hashcode
}

Идея последнего решения здесь состоит в том, что мы используем управляемую доменом конструкцию, чтобы заставить единственный способ создать BorrowId - предоставить ему идентификаторы Person и Book, что логично, как *Объекты 1011 *, Book и Library должны существовать раньше.

Если вы действительно хотите продвинуться на один шаг дальше, конструктор может быть

public BorrowId(Person person, Book book, Library library) {
  assert library.getCode().equals( person.getId().getLibraryCode() );
  assert library.getCode().equals( book.getId().getLibraryCode() );
  this.person = person.getId().getName();
  this.book = book.getId().getTitle();
  this.library = library.getCode();
}

Hibernate позаботится о манипулировании кодом для правильного доступа к тому, что ему нужно из закрытых областей, так какнеобходимо, оставляя ограниченные области видимости, диктовать, как вы предполагаете использовать объект.

...