休眠中的外键,为什么创建对象,如何更新引用实体中的记录

我是 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 中执行此操作。我尝试了以下方法:


生成了一个没有任何关系的用户表,只有@Iduid 的注解。


@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 创建一个用户对象?我只想用外键约束在我的书籍表中存储一个用户 ID(如果用户不存在,那么这本书也不能存在)


2-另外,如果我想访问所有者的用户 ID,我应该使用这个:


public Long getOwnerId()

{

 return user.getUid();

}

3- 如果我想更改书的所有者,我该怎么做?由于我的 book 对象中有一个完整的用户成员,我如何只更新我的 book 表中的 ownerid?


凤凰求蛊
浏览 164回答 3
3回答

30秒到达战场

在 ManyToOne 实体中,您只需要在 @JoinColumn 注释中指定外键的名称,如下所示:@Entity@Table(name = "BOOK")public class Book{   //private Long bid;   @ManyToOne   @JoinColumn(name="oid")   private User user;}参数referencedColumnName最常用于多对多关系。

繁星淼淼

Hibernate 是一个对象关系映射器,以通常的面向对象的方式表示关系数据库的基于表的数据结构,仅此而已。您不必使用@ManyToOne、@OneToMany 等注释。您可以这样做:@Entity@Table(name="USER")public class User {&nbsp; &nbsp; @Id&nbsp; &nbsp; @Column(name = "uid")&nbsp; &nbsp; private Long uid;&nbsp; &nbsp; // setters and getters}@Entity@Table(name = "BOOK")public class Book {&nbsp; &nbsp; @Id&nbsp; &nbsp; @Column(name = "bid")&nbsp; &nbsp; private Long bid;&nbsp; &nbsp; @Column(name = "oid")&nbsp; &nbsp; private Long oid;&nbsp; &nbsp; // setters and getters}EntityManager em;Long uid = em.createQuery("SELECT u.uid FROM User u WHERE ....", Long.class).getSingleResult();book.setUid(uid);大多数开发人员不想处理那么多的 ID 和数据库访问等。他们只想以一种自然的面向对象的方式访问他们的业务模型,然后 hibernate 或 JPA 进来了:EntityManager em;User user1 = em.find(User.class, 1L);Book book1 = new Book();book1.setUser(user1);&nbsp; &nbsp;&nbsp;您不必为每个 Book 实例创建一个 User 实例。只需重用现有的 User 实例。在您的示例中,我将执行以下操作:@Entity@Table(name="USER")public class User {&nbsp; &nbsp; // ...&nbsp; &nbsp; @OneToMany(mappedBy = "user")&nbsp; &nbsp; private Collection<Book> books = new ArrayList<>();&nbsp; &nbsp; public void add(Book book) {&nbsp; &nbsp; &nbsp; &nbsp; book.setUser(this);&nbsp; &nbsp; &nbsp; &nbsp; books.add(book);&nbsp; &nbsp; }&nbsp; &nbsp; public void remove(Book book) {&nbsp; &nbsp; &nbsp; &nbsp; book.setUser(null);&nbsp; &nbsp; &nbsp; &nbsp; books.remove(book);&nbsp; &nbsp; }}@Entity@Table(name = "BOOK")public class Book {&nbsp; &nbsp; // ...&nbsp; &nbsp; @ManyToOne&nbsp; &nbsp; @JoinColumn(name="oid", referencedColumnName = "uid")&nbsp; &nbsp; 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(); // user1book2.getUser(); // user1&nbsp; &nbsp;&nbsp;是的,如果你想处理裸 ID通过 setter 设置另一个用户。book表中对应的uid会被更新。book1.setUser(user2);将导致声明update BOOK set oid = 2 where bid = 1;

Smart猫小萌

为什么我需要在 book 表中为我的 uid 创建一个用户对象?您无需对数据库表进行任何更改。Hibernate 将从 book 表中读取 oid,并将Book.user使用此 oid 标识的 User 类型的对象填充该字段。这样,例如,当您在应用程序中显示有关一本书的信息时,并且希望显示所有者的姓名时,您需要做的就是display(book.getUser().getName());不必获取用户的 ID,然后执行第二个数据库查询来获取用户。如果我想访问所有者的用户 ID,我应该使用这个:是的。或者您不添加任何方法,因为任何调用者都可以book.getUser().getUid()自己完成。如果我想更改书的所有者,我应该怎么做?假设您拥有新所有者的 uid,您将获得由此 ID 标识的用户,并在书上设置:User newOwner = entityManager.find(User.class, newOwnerId);// or User newOwner = entityManager.getReference(User.class, newOwnerId);// depending on what you preferbook.setUser(newOwner);关于您对多对一的映射,这是错误的。您需要阅读 Hibernate 手册和 javadoc,而不是随意尝试。它应该只是@ManyToOne@JoinColumn(name = "oid")private User user;
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java