我正在开始一个新项目,我对使用JPA / Hibernate完全不熟悉。我正在尝试了解如何正确使用EntityManager。更确切地说,何时实例化它们,我需要多少,如果我关闭它们,我应该把所有东西都放到交易中吗?
无论如何,在我当前的代码中,我在尝试读取之前保存的实体时遇到了org.hibernate.LazyInitializationException。我会理解相反的事情(在事务中读取一个antity然后尝试将读取实体保存在另一个事务中但是由于事务已经结束,实体是不受管理的,因此保存失败),但这是我无法理解的。
我把我的代码放在GitHub(https://github.com/GaetanLeu/intl)上,它只是几个类。我的主要是在src / sandbox / MessageSandbox.java中,它在第28行失败,带有以下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)
另外我收到来自Hibernate的警告说我的EntityManager已经存在,那么会发生什么? EntityManagerFactory.createEntityManager方法是否返回现有的?
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'
我真的迷失了什么时候创建EntityManagers ^^任何帮助都会受到赞赏,但请简单解释我真的很新。
哦,顺便说一下,我想确切地说我没有使用Spring,我没有EJB,我想现在手动操作EntityManagers,直到我理解它为止。谢谢:))
答案 0 :(得分:12)
entityManager管理persistence context,换言之,管理数据库状态的内存快照。
请参阅What is a persistence object?
使用entityManager加载的每个对象都将处于托管状态(请参阅entity life cycle),直到关闭EM。当实体为managed
时,将对所有对其进行的更改进行跟踪,然后在刷新时保留EM。如果您访问一些延迟获取属性,将自动触发请求以动态加载数据,但如果实体处于分离状态(如果EM已关闭),则访问延迟属性将导致您获得的错误。
EM的范围(/生命周期)取决于您的执行上下文。例如,对于Web应用程序,通常会为每个http请求创建EM。
对于独立应用程序,您必须注意数据库是否可以由其他应用程序/线程更新。如果可以,您的持久化上下文可能与数据库状态不一致,您应该为每个工作单元(事务)创建它以避免这种情况。否则,您可以为所有应用程序生命周期创建一个实例,并定期刷新它。
对于CRUD应用程序,生命周期通常如下:
关于用户更新验证:
请记住,EM是一个轻量级对象,创建和销毁成本低廉,而且不是THREADSAFE。
BTW,JPA是Java EE规范,它是EJB的一部分(持久性部分)。其目的是在Java EE容器上下文中使用(自JEE 6以来的Java EE应用程序服务器或CDI)。您仍然可以通过JPA合同在独立模式下使用hibernate,但即使在这种情况下,也必须考虑与spring耦合以利用容器管理功能。