【问题标题】:Hibernate | Spring Data JPA | @OneToOne休眠 | Spring Data JPA | @OneToOne
【发布时间】:2016-07-15 07:07:24
【问题描述】:

我的问题很简单..

  1. 假设有 2 个类 .. 书籍和作者
  2. 假设一本书只能由一位作者撰写。
  3. 一个作者可以写很多本书。
  4. 假设作者有唯一的名字。 [没有 2 位作者可以同名]

现在 .. 假设所有 hibernate\JPA 配置都已完成。

从主要方法 - 我保存名为“book1”和作者姓名“author1”的 Book book1

如果我将级联设置为 ALL .. 书籍和作者都会在保存书籍时保存。

问题

现在,如果我保存同一作者的另一本书 - 它会再次保存书籍和作者。这意味着我最终得到了 2 个相同的作者。

我做了什么

  1. 我已将级联 ALL 替换为 MERGE。
  2. 在为书指定作者之前 - 我正在检查数据库中的名称 -

一个。如果我收到回复 - 我将检索到的作者分配给该书并保存该书。

b.如果我没有得到任何结果 - 我将作者分配给这本书并保存作者和书籍。

这样我就可以解决我的问题了。

但这是正确的方法吗?

@Entity 
class Book{

    @Id
    private Long bookId;

    private String name;

    @OneToOne
    private Author author;

}

@Entity
class Author{

    @Id
    private Long authorId;
    private String name;

}

主代码

public static void main(String[] args) {
    ApplicationContext context = SpringApplication.run(BeanConfiguration.class, args);
    BookRepository bookRepo = context.getBean(BookRepository.class);
    AuthorRepository authorRepo = context.getBean(AuthorRepository.class);

    Book b1 = new Book();
    b1.setBookName("book1");

    Author a1 = new Author();
    a1.setAuthorName("author1");

    Author authorFromDatabase = authorRepo.findByAuthorName(a1.getAuthorName());
    if (authorFromDatabase == null) {
        b1.setAuthor(a1);
        authorRepo.save(a1);
    } else {
        b1.setAuthor(authorFromDatabase);
    }
    bookRepo.save(b1);
}

更新 不是那么简单..例如..请考虑..客户和地址之间的关联..客户可以有一个或多个地址..如果新客户与其他客户共享地址..那么不要使地址保持不变..只需将地址(id)分配给新客户。

我的问题是我在上面做了什么,即搜索现有作者(或上述情况下的地址)是正确的方法吗? .. 避免在作者(或地址表)中重复行

【问题讨论】:

  • 欢迎来到 Stack Overflow,请阅读How do I ask a good question?,特别是“写一个总结具体问题的标题”部分。
  • 添加将对象写入数据库的代码。我也怀疑这是你的实际对象,我缺少 getter/setter 和 equals/hashCode 实现。
  • 添加到主帖
  • 使用 saveOrUpdate 代替 save 没有帮助?
  • 请阅读“更新”部分.. saveOrUpdate 无济于事

标签: java hibernate jpa spring-data


【解决方案1】:

如果Author可以有多个Book则不是@OneToOne关联,而是@OneToMany关联。

@Entity 
class Book{

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    private Author author;

}

@Entity
class Author{

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "author")
    private List<Book> books = new ArrayList<Book>();

}

将书籍添加到Author的最简单方法

Author author = new Author();
save(author);

Book book = new Book();
book.setAuthor(author);
save(book);

Book goodBook = new Book();
goodBook.setAuthor(author);
save(goodBook);

Book 不是参考值(我的意思是目录、参考表),因此我们可以通过 Book 部分上的外键使用关联。

如果您需要使用 Customer 和 Address(参考)等参考值,则应使用连接表。

@Entity 
class Address {

    @Id
    @GeneratedValue
    private Long id;

}

@Entity
class Customer{

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany
    private List<Address> addresses = new ArrayList<Address>();

}

【讨论】:

  • 嗯..没那么简单..例如..客户和地址..客户可以有一个或多个地址..如果新客户与其他客户共享地址..那么不要坚持地址..只需将地址(id)分配给新客户。
  • 谢谢,但我的问题不同。 ..映射不会自动保存重复项..对吗?我们必须自己处理..首先在数据库中查找..就像我在主要方法中所做的那样..上面复制粘贴..请注意我的问题不是关于映射..它是关于避免“映射”实体中的重复。
  • @reverse 是的,你应该自己携带副本。
  • 在您的示例中..您知道作者对象(其内容)..现在想象作者详细信息来自某些 WS,并且您不知道它是否已经存在于数据库中..那么您将拥有进行查找以检查其存在..我的问题是..有更好的方法吗?或者我所做的是正确的..
  • @reverse 这是正确的:那么你必须做一个 find 来检查它的存在。
猜你喜欢
  • 2012-07-30
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 2014-08-14
  • 2019-01-27
  • 2016-05-03
  • 2021-07-14
相关资源
最近更新 更多