Внешний ключ в hibernate, зачем создавать объекты, как обновить запись в ссылочной сущности - PullRequest
0 голосов
/ 07 ноября 2018

Я новичок в среде Hibernate. У меня есть основной вопрос, и я все еще пытаюсь понять, почему люди выбирают Hibernate вместо SQL.

У меня есть две таблицы, допустим, одна - пользователь, другая - книга.

У пользователя может быть много книг, но у книги может быть только один владелец.

Если я использовал SQL, я пытаюсь написать на

Table User, 
  int uid
  PRIMARY KEY (uid)

Table Book,
    int bid
    int oid //ownerid
    PRIMARY KEY (bid)
    FOREIGN KEY (oid) REFERENCES User(uid) 

Я не мог сделать это в Hibernate. Я пробовал следующее:

Сгенерировал пользовательскую таблицу без какого-либо отношения, только аннотация @Id для uid.

@Entity
@Table(name="USER")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "uid")
    private Long uid;

    public Long getUid()
    { return uid;}
}

Сформировал таблицу книг, но я не могу понять этот момент. Все в интернете говорит, что мне нужно использовать @ManyToOne и @JoinColumns. Если я использую их, мне нужен объект:

@Entity
@Table(name = "BOOK")
public class Book{

    @ManyToOne
    @JoinColumn(name="uid",
       referencedColumnName = "What should I write here?")
    @Column(name ="oid") //owner id
    private User user;
}

1- Зачем мне нужно создавать пользовательский объект для моего uid в таблице книг? Я просто хочу сохранить идентификатор пользователя в своей таблице книг с ограничением внешнего ключа (если пользователь не существует, книга также не может существовать)

2- Также, если я хочу получить ID пользователя владельца, должен ли я использовать это:

public Long getOwnerId()
{
 return user.getUid();
}

3- Что мне делать, если я хочу сменить владельца книги? Поскольку в моем объекте книги есть целый пользователь, как я могу обновить только идентификатор владельца в таблице книг?

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

В объекте ManyToOne вам просто нужно указать имя вашего внешнего ключа внутри аннотации @JoinColumn, например:

@Entity
@Table(name = "BOOK")
public class Book{
   //private Long bid;

   @ManyToOne
   @JoinColumn(name="oid")
   private User user;
}

Параметр referencedColumnName наиболее часто используется для отношений ManyToMany.

0 голосов
/ 07 ноября 2018

Hibernate - это объектно-реляционный картограф, представляющий структуру данных на основе таблиц реляционной базы данных обычным объектно-ориентированным способом, не более и не менее.

Вам не нужно использовать аннотации, такие как @ManyToOne, @OneToMany и т. Д. Вы можете просто сделать это:

@Entity
@Table(name="USER")
public class User {
    @Id
    @Column(name = "uid")
    private Long uid;

    // setters and getters
}

@Entity
@Table(name = "BOOK")
public class Book {

    @Id
    @Column(name = "bid")
    private Long bid;

    @Column(name = "oid")
    private Long oid;

    // setters and getters
}

EntityManager em;
Long uid = em.createQuery("SELECT u.uid FROM User u WHERE ....", Long.class).getSingleResult();
book.setUid(uid);

Большинство разработчиков не хотят иметь дело с таким количеством идентификаторов, доступом к базе данных и т. Д. Они просто хотят получить доступ к своей бизнес-модели естественным образом, ориентированным на объект, и наступает спящий режим или JPA:

EntityManager em;
User user1 = em.find(User.class, 1L);
Book book1 = new Book();
book1.setUser(user1);    
  1. Вам не нужно создавать экземпляр User для каждого отдельного экземпляра Book. Просто используйте существующий экземпляр пользователя.

В вашем примере я бы сделал следующее:

@Entity
@Table(name="USER")
public class User {
    // ...
    @OneToMany(mappedBy = "user")
    private Collection<Book> books = new ArrayList<>();

    public void add(Book book) {
        book.setUser(this);
        books.add(book);
    }

    public void remove(Book book) {
        book.setUser(null);
        books.remove(book);
    }
}

@Entity
@Table(name = "BOOK")
public class Book {
    // ...
    @ManyToOne
    @JoinColumn(name="oid", referencedColumnName = "uid")
    private User user;
}

EntityManager em;
User user1 = em.find(User.class, 1L);
Book book1 = new Book();
Book book2 = new Book();
user1.addBook(book1);
user1.addBook(book2);

book1.getUser(); // user1
book2.getUser(); // user1    
  1. Да, если вы хотите работать с голыми идентификаторами

  2. Установить другого пользователя через сеттер. Соответствующий uid в таблице book будет обновлен.

    book1.setUser (user2);

приведет к выписке

update BOOK set oid = 2 where bid = 1;
0 голосов
/ 07 ноября 2018

Зачем мне нужно создавать пользовательский объект для моего uid в таблице книг?

Вам не нужно ничего менять в таблице базы данных. Hibernate прочитает oid из таблицы book и заполнит поле Book.user объектом типа User, идентифицированным этим oid.

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

display(book.getUser().getName());

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

если я хочу получить ID пользователя владельца, должен ли я использовать это:

да. Или вы не рекламируете какой-либо метод, потому что любой абонент может сделать book.getUser().getUid() сам по себе.

Если я хочу сменить владельца книги, что мне делать?

Если у вас есть идентификатор нового владельца, вы бы идентифицировали пользователя по этому идентификатору и указали в книге:

User newOwner = entityManager.find(User.class, newOwnerId);
// or User newOwner = entityManager.getReference(User.class, newOwnerId);
// depending on what you prefer
book.setUser(newOwner);

Относительно вашего отображения ManyToOne, это неправильно. Вам нужно прочитать руководство по Hibernate и javadoc, а не пробовать что-то случайное. Это должно быть просто

@ManyToOne
@JoinColumn(name = "oid")
private User user;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...