为了理解为什么要持久化子实体,下面是映射。
我有作者(id,姓名,书籍)和书籍(id,标题,作者)实体。他们的关系是很多的,因为任何作者可能有多个书,任何书可能有多个作者。此外,我有BookClient(id,名称,rentDate,books) - 与Book实体的关系是OneToMany,因为任何客户都可以向许多书籍租用零。
Author.java
@Table
public class Author {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "books_authors",
joinColumns = { @JoinColumn(name = "author_id") },
inverseJoinColumns = { @JoinColumn(name = "book_id") }
)
private Set<Book> books = new HashSet<>();
Book.java
@Entity
@Table
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, unique = true)
private Long id;
@Column(nullable = false)
private String title;
@ManyToMany(mappedBy = "books", fetch = FetchType.EAGER)
private Set<Author> authors = new HashSet<>();
@ManyToOne
@JoinColumn(name = "client_id")
private BookClient bookClient;
BookClient.java
@Entity
@Table
public class BookClient {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "client_id")
private Long id;
@Column(nullable = false)
private String name;
@OneToMany(mappedBy = "bookClient", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Book> books = new HashSet<>();
private LocalDate rentDate;
幕后的一些商业逻辑:有很多不同作者写的书,这些书都保留在一些图书馆的数据库中。这个图书馆向客户提供书籍。任何新客户都可以在图书馆注册,当他/她拿书。
使用实体管理器持久化图书客户端:
@Transactional
@Repository("bookClientDao")
public class BookClientDaoImpl implements BookClientDao {
@PersistenceContext
private EntityManager entityManager;
@Override
public void save(BookClient bookClient) {
entityManager.persist(bookClient);
}
@Override
public void saveOrUpdate(BookClient bookClient) {
if(bookClient.getId() == null) {
save(bookClient);
} else {
entityManager.merge(bookClient);
}
}
}
以下是代码中的示例:
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("META-INF/context.xml");
AuthorDao authorDao = (AuthorDao) appContext.getBean("authorDao");
BookClientDao bookClientDao = (BookClientDao) appContext.getBean("bookClientDao");
//Create a book and its author
Book book = new Book();
book.setTitle("John Doe Book the 1st");
Author author = new Author();
author.setName("John Doe");
author.getBooks().add(book);
authorDao.save(author);
//Registering new Book Client
BookClient bookClient = new BookClient();
bookClient.setName("First Client");
bookClient.getBooks().add(book);
bookClient.setRentDate(LocalDate.now());
book.setBookClient(bookClient);
//book is expected to be updated by cascade
bookClientDao.saveOrUpdate(bookClient); //'detached entity passed to persist' occurs here
}
运行此代码后,我将获得分离的实体传递给持久化
异常,因为 Book 实例之前已持久化。
Exception in thread "main" javax.persistence.PersistenceException:
org.hibernate.PersistentObjectException: detached entity passed to persist: entity.manager.example.entity.Book
...
Caused by: org.hibernate.PersistentObjectException:
detached entity passed to persist: entity.manager.example.entity.Book
若我将BookClient berforehand持久化,那个么BookClient和Book之间的连接设置正确,因为这两个实体都存在于数据库中。但在我看来,这是一种变通办法。
是否可以创建新对象,将已经持久化的实体连接到该对象,并通过级联更新其所有子对象来持久化该对象?
在您的示例中,作者和bookClient的保存操作在不同的持久性上下文中执行。至于main方法,首先你应该合并保存作者时分离的书籍(到saveOrUpdate方法中)。
是否可以创建新对象,将已经持久化的实体连接到该对象,并通过级联更新其所有子对象来持久化该对象?
这可能取决于您的应用程序要求和功能。在这个main()示例中,看起来您希望以事务方式保存所有这些实体。
这个网站上没有一个类似的问题能够解决我的问题。 错误:org.hibernate.persistentobjectexception:传递给persist:healthcheckapi.model.checks的分离实体 示例JSON健康对象: 请注意,这两个对象的ID都是自动生成的,我认为这是问题的一部分。
我正试图实现与hibernate的许多单向关系。问题是,当我试图向数据库中添加一些值时,我遇到了以下错误: 运行时发生异常。null:InvocationTargetException:未能执行ApplicationRunner:传递给persist:dnd35cg的分离实体。模型DND类;嵌套的异常是org。冬眠PersistentObjectException:传递给persist:dnd35
我有一个实体,它已经持久化,并希望将其添加到新生成的父实体(尚未持久化)。如果我尝试持久化父级,我会得到错误“分离的实体传递到持久化:model.child”。我想我必须以某种方式为孩子调用“EntityManager.merge()”,而不是“EntityManager.persisted()”。但是我没有显式调用persisted。这由“cascade=cascadetype.all”注释处理
问题内容: 我已经成功用hibernate写了我的第一个主要的孩子例子。几天后,我再次使用它并升级了一些库。不知道我做了什么,但是我再也无法使它运行了。有人可以帮助我找出返回以下错误消息的代码中的错误吗: hibernate映射: 编辑: InvoiceManager.java 发票.java InvoiceItem.java 编辑: 从客户端发送的JSON对象: 编辑: 一些详细信息: 我试图通
对于新学生和新课程的情况,它工作得很好,但是在新课程和现有学生的情况下,我会从数据库中抛出一个唯一的约束冲突。关系类似于下面。 在持久化之前,我尝试使用entitymanager查找一个学生,如果该学生存在,则使用该实例而不是新的学生实例。这也不起作用,它仍然尝试执行插入而不是更新
我有一个实体,它已经被持久化了,想把它添加到一个新生成的父实体(还没有持久化)。如果我尝试持久化父级,那么我会得到错误“Detached entity pass to persist:model.child”。我认为我必须以某种方式为孩子调用“EntityManager.merge()”,而不是“EntityManager.Persist()”。但我没有显式调用persist。这是由“Cascad