如果@OneToOne关系本身通过JPA删除@OneToOne对象,我得到一个例外(#34;聚合对象不能独立于其所有者编写/删除/查询。#34;)和Eclipelink 2.5.2在嵌入对象中。这类似于: Using @OneToOne with Cascade.DELETE in embedded type
完整示例:
@Entity
public class Book {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
protected int id;
public String title = "foo";
// @OneToMany(cascade={CascadeType.ALL})
// public List<Page> pages = new ArrayList<Page>(); // if pages are directly inside the book (instead of in the embedded BookContext), this example works fine
@Embedded
public BookContent bookContent;
public Book() {
bookContent = new BookContent();
// pages.add(new Page()); // if this is used instead of bookContent, then it works
}
public static void main(String[] args) {
try {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Book");
EntityManager em = emf.createEntityManager();
Book book = new Book();
em.getTransaction().begin();
em.persist(book);
em.getTransaction().commit();
em.getTransaction().begin();
Query query = em.createQuery("Select g from Book g"); // of course in this example the query would not be necessary
List<Book> results = query.getResultList();
for (Book bookToRemove : results){
em.remove(bookToRemove);
}
em.getTransaction().commit();
em.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
@Embeddable
public class BookContent {
@OneToOne(cascade={CascadeType.ALL})
public Page page;
public String bookdContentID = "1";
public BookContent() {
page = new Page();
}
}
@Entity
public class Page {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
protected int id;
public String text = "test";
}
当我运行此操作时,我收到以下错误(&#34;无法独立于其所有者编写/删除/查询聚合对象。&#34;)
[EL Fine]: sql: 2014-07-31 14:51:41.157--ClientSession(907509627)--Connection(2114173229)--Thread(Thread[main,5,main])--DELETE FROM BOOK_PAGE WHERE (Book_ID = ?)
bind => [1]
[EL Finest]: query: 2014-07-31 14:51:41.159--UnitOfWork(811619113)--Thread(Thread[main,5,main])--Execute query DeleteObjectQuery(Page@577a863d)
[EL Finest]: query: 2014-07-31 14:51:41.159--UnitOfWork(811619113)--Thread(Thread[main,5,main])--Execute query DeleteObjectQuery(BookContent@4b9f8b6c)
[EL Warning]: 2014-07-31 14:51:41.164--UnitOfWork(811619113)--Thread(Thread[main,5,main])--Local Exception Stack:
Exception [EclipseLink-6002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: Aggregated objects cannot be written/deleted/queried independently from their owners.
Descriptor: [RelationalDescriptor(BookContent --> [])]
Query: DeleteObjectQuery(BookContent@4b9f8b6c)
at org.eclipse.persistence.exceptions.QueryException.aggregateObjectCannotBeDeletedOrWritten(QueryException.java:250)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.prepare(ObjectLevelModifyQuery.java:205)
at org.eclipse.persistence.queries.DeleteObjectQuery.prepare(DeleteObjectQuery.java:327)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:661)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:613)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:867)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:119)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeDatabaseQuery(DeleteObjectQuery.java:194)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:119)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:336)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:290)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1444)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
at Book.main(Book.java:53)
[EL Finer]: transaction: 2014-07-31 14:51:41.165--ClientSession(907509627)--Connection(2114173229)--Thread(Thread[main,5,main])--rollback transaction
[EL Finest]: connection: 2014-07-31 14:51:41.166--ServerSession(228859333)--Connection(2114173229)--Thread(Thread[main,5,main])--Connection released to connection pool [default].
[EL Finer]: transaction: 2014-07-31 14:51:41.166--UnitOfWork(811619113)--Thread(Thread[main,5,main])--release unit of work
[EL Finer]: connection: 2014-07-31 14:51:41.166--ClientSession(907509627)--Thread(Thread[main,5,main])--client released
javax.persistence.RollbackException: Exception [EclipseLink-6002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: Aggregated objects cannot be written/deleted/queried independently from their owners.
Descriptor: [RelationalDescriptor(BookContent --> [])]
Query: DeleteObjectQuery(BookContent@4b9f8b6c)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
at Book.main(Book.java:53)
Caused by: Exception [EclipseLink-6002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: Aggregated objects cannot be written/deleted/queried independently from their owners.
Descriptor: [RelationalDescriptor(BookContent --> [])]
Query: DeleteObjectQuery(BookContent@4b9f8b6c)
at org.eclipse.persistence.exceptions.QueryException.aggregateObjectCannotBeDeletedOrWritten(QueryException.java:250)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.prepare(ObjectLevelModifyQuery.java:205)
at org.eclipse.persistence.queries.DeleteObjectQuery.prepare(DeleteObjectQuery.java:327)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:661)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:613)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:867)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:119)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeDatabaseQuery(DeleteObjectQuery.java:194)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:119)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:336)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:290)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1444)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
... 1 more
如果我改为删除&#34; Bookcontent&#34;,并包含&#34; Page&#34;直接在Book对象中对象,然后一切正常:
[EL Fine]: sql: 2014-07-31 15:10:45.241--ClientSession(1901887672)--Connection(2055970986)--Thread(Thread[main,5,main])--DELETE FROM BOOK_PAGE WHERE (Book_ID = ?)
bind => [1]
[EL Finest]: query: 2014-07-31 15:10:45.242--UnitOfWork(404057375)--Thread(Thread[main,5,main])--Execute query DeleteObjectQuery(Page@7a9a042)
[EL Fine]: sql: 2014-07-31 15:10:45.243--ClientSession(1901887672)--Connection(2055970986)--Thread(Thread[main,5,main])--DELETE FROM PAGE WHERE (ID = ?)
bind => [1]
[EL Finest]: query: 2014-07-31 15:10:45.245--UnitOfWork(404057375)--Thread(Thread[main,5,main])--Execute query DeleteObjectQuery(Book@26af1a93)
[EL Fine]: sql: 2014-07-31 15:10:45.246--ClientSession(1901887672)--Connection(2055970986)--Thread(Thread[main,5,main])--DELETE FROM BOOK WHERE (ID = ?)
bind => [1]
[EL Finer]: transaction: 2014-07-31 15:10:45.247--ClientSession(1901887672)--Connection(2055970986)--Thread(Thread[main,5,main])--commit transaction
[EL Finest]: connection: 2014-07-31 15:10:45.248--ServerSession(686104144)--Connection(2055970986)--Thread(Thread[main,5,main])--Connection released to connection pool [default].
[EL Finer]: transaction: 2014-07-31 15:10:45.248--UnitOfWork(404057375)--Thread(Thread[main,5,main])--end unit of work commit
[EL Finer]: transaction: 2014-07-31 15:10:45.248--UnitOfWork(404057375)--Thread(Thread[main,5,main])--resume unit of work
[EL Finer]: transaction: 2014-07-31 15:10:45.249--UnitOfWork(404057375)--Thread(Thread[main,5,main])--release unit of work
[EL Finer]: connection: 2014-07-31 15:10:45.249--ClientSession(1901887672)--Thread(Thread[main,5,main])--client released
答案 0 :(得分:1)
实际上它正在发挥作用,但Embeddable不能处于关系的拥有方面。我创建了一个切换所有权的例子,它工作得很好。我假设规范的第2.5节中的以下词语适用:
自实例以来 可嵌入类本身没有持久性标识,来自引用实体的关系是 到包含可嵌入实例的实体而不是嵌入本身。 [实体不能与另一个实体(或其自身)的可嵌入类具有单向关系。]
正在运行的精简示例:
@Embeddable
public class BookContent {
@OneToOne(mappedBy="book",cascade={CascadeType.ALL})
Page page;
}
@Entity
public class Book {
@Id @GeneratedValue int id;
@Embedded
public BookContent bookContent;
}
@Entity
public class Page {
@Id @GeneratedValue int id;
@OneToOne
Book book;
}
注意:现在Page
是关系的所有者。
我认为拥有一页的书不是我们通常看到的,所以我还检查@OneToMany
是否正常工作。
// BookContent
@OneToMany(mappedBy="book",cascade={CascadeType.ALL})
List<Page> page;
// Page
@ManyToOne
Book book;
<强>更新强> 根据API Javadoc,嵌入式关系的所有权实际上是有效的:
如果关系是双向的,并且包含可嵌入类的实体位于关系的拥有方,则非拥有方必须使用OneToOne批注的mappedBy元素来指定可嵌入类的关系字段或属性。必须在mappedBy元素中使用点(“。”)表示法语法来指示嵌入属性中的关系属性。
但即使正确映射了Eclipselink,也不允许删除。