Mic*_*vin 4 java collections orm hibernate jpa
我想在我的数据库中复制一组实体.我用以下方式检索了这个系列:
CategoryHistory chNew = new CategoryHistory();
CategoryHistory chLast = (CategoryHistory)em.createQuery("SELECT ch from CategoryHistory ch WHERE ch.date = MAX(date)").getSingleResult;
List<Category> categories = chLast.getCategories();
chNew.addCategories(categories)// Should be a copy of the categories: OneToMany
Run Code Online (Sandbox Code Playgroud)
现在我想复制一个'类别'列表并用EntityManager保存它.我正在使用JPA/Hibernate. UPDATE
在知道如何分离我的实体之后,我需要知道要分离的内容:当前代码:
CategoryHistory chLast = (CategoryHistory)em.createQuery("SELECT ch from CategoryHistory ch WHERE ch.date=(SELECT MAX(date) from CategoryHistory)").getSingleResult();
Set<Category> categories =chLast.getCategories();
//detach
org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession();
session.evict(chLast);//detaches also its child-entities?
//set the realations
chNew.setCategories(categories);
for (Category category : categories) {
category.setCategoryHistory(chNew);
}
//set now create date
chNew.setDate(Calendar.getInstance().getTime());
//persist
em.persist(chNew);
Run Code Online (Sandbox Code Playgroud)
这会引发failed to lazily initialize a collection of role: entities.CategoryHistory.categories, no session or session was closed异常.
我认为他想再懒得加载类别,因为我让它们分离了.我现在应该怎么做?
您需要从会话中分离您的实例.有三种方法可以做到这一点:
然后,您必须更改业务键(因此在使用未修改的实例false调用时将返回新equals()实例).这是重要的一步:没有它,Hibernate会将实例重新附加到数据库中的现有实例,否则您将得到其他奇怪的错误.
之后,您可以像保存其他实例一样保存新副本.
Aaron Diguila的答案就是去这里的方式,即你需要detach你的实例,设置商业密钥null然后再设置persist它们.
遗憾的是,没有办法使用JPA 1.x将一个对象与实体管理器断开连接(JPA 2.0将具有EntityManager.detach(Object)并修复此问题).所以,要么等待JPA 2.x(我猜不是一个选项),要么使用Hibernate的底层Session.
为此,您可以将EntityManager的委托转换为Hibernate会话.
Session session = (Session) em.getDelegate();
Run Code Online (Sandbox Code Playgroud)
当然,这仅在您将Hibernate用作Java持久性提供程序时才有效,因为委托是Session API.
然后,分离你的对象:
session.evict(object);
Run Code Online (Sandbox Code Playgroud)
更新:根据使用EntityManager.getDelegate()时要小心,使用 GlassFish应该实际使用(在您的情况下也可能):
org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession();
Run Code Online (Sandbox Code Playgroud)
但这不适用于建议使用前面提到的代码的JBoss .
org.hibernate.Session session = (Session) em.getDelegate();
Run Code Online (Sandbox Code Playgroud)
虽然我理解使用getDelegate()JPA代码是不可移植的,但我必须承认我并不期望这个方法调用的结果是特定于实现的.
更新2:要回答问题的更新部分,我不确定您是否急切地加载了类别.这不是最好的方法,但如果你categories.get(0)在驱逐前打电话会怎么样?此外,我可能会错过那部分,但是,你在哪里取消了类别的关键?
| 归档时间: |
|
| 查看次数: |
12816 次 |
| 最近记录: |