复制实体集合并持久化在Hibernate / JPA中 [英] Duplicate a collection of entities and persist in Hibernate/JPA

查看:824
本文介绍了复制实体集合并持久化在Hibernate / JPA中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想复制我的数据库中的实体集合。
我检索集合:

 类别History chNew = new CategoryHistory 
CategoryHistory chLast =(CategoryHistory)em.createQuery(SELECT ch from CategoryHistory ch WHERE ch.date = MAX(date))。getSingleResult;
List< Category>类别= chLast.getCategories();
chNew.addCategories(categories)//应该是类别的副本:OneToMany

现在我想复制一个'类别'列表,并与EntityManager持久化。
我使用JPA / Hibernate。
UPDATE



在知道如何分离我的实体之后,我需要知道要分离什么:
当前代码:

  CategoryHistory chLast =(CategoryHistory)em.createQuery(SELECT ch from CategoryHistory ch WHERE ch.date =(SELECT MAX )from CategoryHistory))。getSingleResult(); 
设置<类别>类别= chLast.getCategories();

// detach
org.hibernate.Session session =((org.hibernate.ejb.EntityManagerImpl)em.getDelegate())。getSession();
session.evict(chLast); //也分离它的子实体?

//设置方程
chNew.setCategories(categories);
for(Category category:categories){
category.setCategoryHistory(chNew);
}
//设置现在创建日期
chNew.setDate(Calendar.getInstance()。getTime());

// persist
em.persist(chNew);

这会抛出无法延迟初始化角色集合:entities.CategoryHistory .categories,没有会话或会话被关闭例外。



我想他想延迟加载类别,

解决方案

Aaron Diguila的 detach ,那么你可以使用您的实例,将业务键设置为 null ,然后持久

$遗憾的是,没有办法用JPA 1.x断开一个对象与实体管理器的连接(JPA 2.0会有 EntityManager.detach(Object)并修复此问题)。所以,要么等待JPA 2.x(不是我猜测的选项),要么使用Hibernate的底层 Session



为此,您可以将EntityManager的委托转换为Hibernate会话。

 会话session =(Session)em.getDelegate (); 

当然,这只适用于使用Hibernate作为Java Persistence提供者,因为委托是会话API。



然后,要分离您的对象:

  session.evict目的); 

UPDATE:根据时要小心,使用GlassFish时,应该实际使用的方法是:使用EntityManager.getDelegate() (也可能在你的case):

  org.hibernate.Session session =((org.hibernate.ejb.EntityManagerImpl) em.getDelegate())。getSession(); 

在JBoss中工作建议使用前面提到的代码。

  org.hibernate.Session session =(Session)em.getDelegate();虽然我明白,使用 getDelegate() 

使得JPA代码不可移植,我必须承认,我并不期望此方法调用的结果是实现特定的。



UPDATE2:要回答问题的更新部分,我不确定你急切地加载类别。这不是最好的方法,但如果你在驱逐之前调用 categories.get(0)会发生什么?此外,我可能会缺少这一部分,但你在哪里可以消除类别的关键?


I want to duplicate a collection of entities in my database. I retreive the collection with:

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

Now i want to duplicate a list of 'categories' and persist it with EntityManager. I'm using JPA/Hibernate. UPDATE

After knowing how to detach my entities, i need to know what to detach: current code:

    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);

This throws a failed to lazily initialize a collection of role: entities.CategoryHistory.categories, no session or session was closed exception.

I think he wants to lazy load the categories again, as i have them detached. What should i do now?

解决方案

Aaron Diguila's answer is the way to go here, i.e. you need to detach your instances, set the business key to null and then persist them.

Sadly, there is no way to disconnect one object from the entity manager with JPA 1.x (JPA 2.0 will have EntityManager.detach(Object) and fix this). So, either wait for JPA 2.x (not an option I guess) or use Hibernate's underlying Session.

To do so, you can cast the delegate of an EntityManager to an Hibernate Session.

Session session = (Session) em.getDelegate();

Of course, this only works if you use Hibernate as a Java Persistence provider, because the delegate is the Session API.

Then, to detach your object:

session.evict(object);

UPDATE: According to Be careful while using EntityManager.getDelegate(), with GlassFish one should actually use (and likely in your case too) :

org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession();

But this would not work in JBoss that suggest to use the code previously mentioned.

org.hibernate.Session session = (Session) em.getDelegate();

While I understand that using getDelegate() makes JPA code non-portable, I must admit that I was not expecting the result of this method call to be implementation specific.

UPDATE2: To answer the updated part of the question, I'm not sure that you eagerly loaded the categories. This is not the best way to do this but what happens if you call categories.get(0) before eviction? Also, I may be missing that part but, where do you nullify the key of categories?

这篇关于复制实体集合并持久化在Hibernate / JPA中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆