努力理解EntityManager的正确使用 [英] Struggling to understand EntityManager proper use

查看:589
本文介绍了努力理解EntityManager的正确使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开始一个新项目,而且我完全不熟悉JPA / Hibernate的使用。我试图了解如何正确使用EntityManager。更确切地说,什么时候实例化它们,我需要多少个,我应该关闭它们,我应该把所有东西都放到交易中吗?

无论如何,在我当前的代码中, org.hibernate.LazyInitializationException尝试读取我以前保存的实体。我会理解相反的情况(读取事务中的antity,然后尝试将读取的实体保存在另一个事务中,但由于事务结束,实体不受管理,因此保存失败),但是我无法理解。



我将代码放在GitHub上( https://github.com/GaetanLeu/intl ),它只是几个类。我的主要是在src / sandbox / MessageSandbox.java中,它在第28行失败,出现以下堆栈跟踪:

 主要org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话
在org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
在org.hibernate.proxy.AbstractLazyInitializer.getImplementation (AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at entity.MessageKey _ $$ _ jvstfcc_0.toString(MessageKey _ $$ _ jvstfcc_0 .java)
在java.lang.String.valueOf(String.java:2854)
在java.lang.StringBuilder.append(StringBuilder.java:128)
在com.google。 (java.lang.String.valueOf(String.java:2854))
位于java.io.PrintStream.println(PrintStream.java: 821)
在sandbox.MessageSandbox.main(MessageSa ndbox.java:28)

另外我从Hibernate得到一个警告,说我的EntityManager已经存在,会发生什么然后? EntityManagerFactory.createEntityManager方法是否返回现有的?

 警告:HHH000436:实体管理器工厂名称(intl)已经注册。如果实体管理器将被聚集或钝化,为属性'hibernate.ejb.entitymanager_factory_name'指定一个唯一值

真的我失去了什么时候创建EntityManagers ^^任何帮助将不胜感激,但请简单的解释我真的很新。



哦,顺便说一句,我想要精确我没有使用Spring,我没有EJB,我想现在手动操作EntityManagers直到我明白它。感谢:)

解决方案

entityManager管理持久化上下文,换句话说就是数据库状态的内存快照。

请参阅什么是一个持久化对象?使用entityManager加载的每个对象都将处于受管状态(请参见实体生命周期),直到您关闭EM。当一个实体托管时,对它进行的所有更改都将被跟踪,并在冲刷EM时保留。如果你访问一些懒惰的fetched属性,会自动触发一个请求来动态加载数据,但是如果实体处于分离状态(如果EM已关闭),访问懒惰属性将导致你得到的错误。



您的EM的范围(/生命周期)取决于您的执行上下文。例如,对于Web应用程序,通常会为每个http请求创建一个EM。

对于独立应用程序,您不得不介意数据库是否可以被另一个应用程序/线程更新。如果可以,你的持久性上下文可能与数据库状态不一致,你应该为每个工作单元(事务)创建它以避免这种情况。否则,您可以为所有应用程序生命周期创建一次实例并定期刷新。



对于CRUD应用程序,生命周期通常如下所示:




  • 创建EM

  • 获取一些实体(它们是如此管理的,任何对lazy属性的访问都会从DB加载数据)

  • 关闭EM(实体现在已分离,任何对lazy属性的访问都将导致LazyInitializationException)
  • 将数据显示给用户
  • li>


关于用户更新验证:


  • 创建em

  • 打开一个事务

  • 合并(附加)您更新的实体(这是您保存的内容)(如果您设置了一些optmistic锁定,em会在这里检查数据库的实体版本)

  • 最终执行一些业务验证或附加更新

  • 提交事务并关闭em更改将被刷新)



Keep是介意EM是一个轻量级的对象,便宜的创建和销毁,而不是THREADSAFE。

顺便说一句,JPA是一个Java EE规范是EJB的一部分(持久性部分)。其目标是用于Java EE容器环境(自JEE 6以来的Java EE应用服务器或CDI)。您仍然可以通过JPA合约在独立模式下使用hibernate,但即使在这种情况下,也必须考虑与spring耦合以利用容器管理的功能。


I'm starting a new project and I'm totally new to JPA/Hibernate use. I'm trying to understand how to use EntityManager properly. More precisely, when to instantiate them, how many do I need, should I close them, should I put everything into transactions?

Anyway, in my current code, I got an org.hibernate.LazyInitializationException while trying to read an entity that I previously saved. I would understand the opposite (reading an antity in a transaction then trying to save the read entity in another transaction but since transaction is over, the entity is unmanaged so save fails), but this I can't understand.

I put my code on GitHub (https://github.com/GaetanLeu/intl), it's just a couple of classes. My main is in src/sandbox/MessageSandbox.java and it fails at line 28 with the following stacktrace:

Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at entity.MessageKey_$$_jvstfcc_0.toString(MessageKey_$$_jvstfcc_0.java)
    at java.lang.String.valueOf(String.java:2854)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at com.google.common.base.Present.toString(Present.java:88)
    at java.lang.String.valueOf(String.java:2854)
    at java.io.PrintStream.println(PrintStream.java:821)
    at sandbox.MessageSandbox.main(MessageSandbox.java:28)

Also I got a warning from Hibernate saying my EntityManager already exists, what happens then? Is the EntityManagerFactory.createEntityManager method returning the existing one?

WARN: HHH000436: Entity manager factory name (intl) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'

Really I'm lost about when to create EntityManagers ^^ Any help would be appreciated, but please simple explanation I'm really new to this.

Oh BTW, I want to precise I'm not using Spring, I don't have EJBs, I want to manipulate EntityManagers manually for now until I understand it. Thanks :)

解决方案

An entityManager manages a persistence context, in other word an in memory snapshot of the database state.

See What is a persistence object?

Every object loaded using the entityManager will be in managed state (see entity life cycle) until you close the EM. When an entity is managed, all change made to it will be tracked and then persisted when flushing the EM. If you access some lazy fetched attribute, a request will be automatically triggered to dynamically load the data, but if the entity is in detached state (if EM have been closed) accessing a lazy attribute will lead to the error you get.

The scope (/lifecycle) of your EM depends of your execution context. For a web application for example, an EM will typically be created for each http request.

For a standalone application, you have to mind if the database can be updated by another application/thread or not. If it can, your persistent context may not be consistent with the database state and you should create it for every unit of work (transaction) to avoid that. Otherwise you can create a single instance once for all the application lifecyle and flush it regulary.

For a CRUD app the lifecycle is generally the following :

  • create the EM
  • fetch some entities (they are so managed, any access to lazy attribute will load the data from DB)
  • close the EM (entity are now detached, any access to lazy attribute will lead to LazyInitializationException)
  • display the data to the user

On user updates validation :

  • create the em
  • open a transaction
  • merge (attach) your updated entities (this is what you call save) (if you have set up some optmistic locking, em will check the entity version against the database here)
  • eventually perform some business validation or additional updates
  • commit the transaction and close the em (changes will be flushed)

Keep is mind that EM is a lightweight object, cheap to create and destroy and NOT THREADSAFE.

BTW, JPA is a Java EE specification which is part of the EJB one (the persistence part). Its aim is to be used in a java EE container context (Java EE application server or CDI since JEE 6). You still can use hibernate in standalone mode through the JPA contract but even in this case, coupling with spring must be considered to take advantage of container managed features.

这篇关于努力理解EntityManager的正确使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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