努力去理解EntityManager的正确使用

我正在开始一个新的项目,我完全不熟悉JPA / Hibernate的使用。 我想了解如何正确使用EntityManager。 更确切地说,什么时候将其实例化,我需要多less,我是否应该closures它们,我应该把所有事情都交易吗?

无论如何,在我当前的代码中,当试图读取一个我以前保存的实体时,我得到了一个org.hibernate.LazyInitializationException。 我会理解相反的(阅读一个事务中的antity,然后试图将读取的实体保存在另一个事务中,但由于事务结束,实体是非托pipe的,因此保存失败),但是这个我不明白。

我把我的代码放在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' 

真的我失去了什么时候创buildEntityManagers ^^任何帮助将不胜感激,但请简单的解释我真的是新的这一点。

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

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

请参阅什么是持久对象?

每个使用entityManager加载的对象都将处于受pipe理状态(请参阅实体生命周期),直到closuresEM。 当一个实体被managed ,所有对它的修改都将被跟踪,并在冲刷EM时被保留。 如果你访问一些懒惰的获取属性,一个请求将被自动触发来dynamic加载数据,但是如果实体处于分离状态(如果EM已经closures),访问一个懒属性将导致你得到的错误。

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

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

对于CRUD应用程序,生命周期一般如下:

  • 创buildEM
  • 获取一些实体(他们是这样pipe理的,任何对懒惰属性的访问都会从DB加载数据)
  • closuresEM(实体现在分离,任何对lazy属性的访问都会导致LazyInitializationException)
  • 将数据显示给用户

在用户更新validation:

  • 创build它们
  • 开一笔交易
  • 合并(附加)你更新的实体(这就是你所说的保存)(如果你已经设置了一些optmisticlocking,他们将检查实体版本对数据库在这里)
  • 最终执行一些业务validation或额外的更新
  • 提交交易并closuresem(更改将被刷新)

请记住,EM是一个轻量级的对象,便宜的创build和销毁,而不是THREADSAFE。

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