java JPA 2 - 在 JavaSE 中使用 EntityManager - 几个问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4066048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA 2 - Using the EntityManager in JavaSE - a couple of questions
提问by Brian DiCasa
I have a couple questions regarding using the entity manager in a JavaSE environment.
我有几个关于在 JavaSE 环境中使用实体管理器的问题。
I'm using the repository pattern to perform my CRUD operations on the database. There will be a base repository class like so:
我正在使用存储库模式对数据库执行我的 CRUD 操作。将有一个基本存储库类,如下所示:
public class Repository<T> implements IRepository<T> {
private EntityManager em;
private String persistenceUnitName;
public Repository(String persistenceUnitName) {
this.persistenceUnitName = persistenceUnitName;
}
@Override
public T find(Class<T> type, Object id) {
return em.find(type, id);
}
private EntityManager getEntityManager() {
if (this.em == null) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
em = emf.createEntityManager();
}
return em;
}
...
...
}
I will then have classes like EmployeeRepository that will inherit Repository. These repository classes will be created in my service layer.
然后,我将拥有像 EmployeeRepository 这样将继承 Repository 的类。这些存储库类将在我的服务层中创建。
Is this a good way of initializing the entity manager? I'm starting to think that it's not - it seems like you should only have one entity manager per persistence unit? Where as in this case you would have an entity manager for every repository you create... How would you go about ensuring you only have one entity manager per persistence unit? Also, I noticed that the entity manager and entity manager factory methods have a close method - when should these be called? On a server terminate event?
这是初始化实体管理器的好方法吗?我开始认为它不是 - 每个持久性单元似乎应该只有一个实体管理器?在这种情况下,您创建的每个存储库都有一个实体管理器……您将如何确保每个持久性单元只有一个实体管理器?另外,我注意到实体管理器和实体管理器工厂方法有一个关闭方法 - 什么时候应该调用它们?在服务器终止事件上?
If you know of any good sources about using JPA in JavaSE I would appreciate the info.
如果您知道有关在 JavaSE 中使用 JPA 的任何好的资源,我将不胜感激。
Thanks!
谢谢!
采纳答案by Arthur Ronald
Almost. You need just one EntityManagerFactory per persistence unit.
几乎。每个持久性单元只需要一个 EntityManagerFactory。
How would you go about ensuring you only have one EntityManagerFactory per persistence unit ?
您将如何确保每个持久性单元只有一个 EntityManagerFactory ?
Usually developers create an helper class with a singleton EntityManagerFactory such as
通常开发人员会创建一个带有单例 EntityManagerFactory 的辅助类,例如
public class EntityManagerFactoryHelper {
private static EntityManagerFactory factory;
static {
try {
// Set up factory right here
} catch(ExceptionInInitializerError e) {
throw e;
}
}
public static EntityManagerFactory getFactory() {
return this.factory;
}
}
EntityManager, in other hand, is used to interact with a set of managed entity instances called persistence context.
另一方面,EntityManager用于与一组称为持久性上下文的托管实体实例进行交互。
If you want to know why i use ErrorInInitializerError, its API is clear
如果你想知道我为什么使用ErrorInInitializerError,它的 API 很清楚
Signals that an unexpected exception has occurred in a static initializer
在静态初始化程序中发生意外异常的信号
...
...
Is this a good way of initializing the entity manager ?
这是初始化实体管理器的好方法吗?
Well, the service layer is used to delimit Transaction boundary. So for each use case, you can create your EntityManager and pass by reference for each colaboratorneeded to help you to execute your use case.
嗯,服务层是用来划定事务边界的。因此,对于每个用例,您可以创建 EntityManager 并通过引用传递帮助您执行用例所需的每个协作者。
public static br.com.helper.EntityManagerFactoryHelper.getFactory;
public EmployeeService {
public void doSomething() {
EntityManager eManager = getFactory().createEntityManager();
eManager.getTransaction().begin();
EmployeeRepository repository = new EmployeeRepository(eManager);
eManager.getTransaction().commit();
}
}
Now imagine you need the boilerplate code shown above for each use case.
现在假设您需要上面显示的每个用例的样板代码。
public void forEachUseCase() {
// Create an EntityManager
// Begin a Transaction
EmployeeRepository repository = new EmployeeRepository(eManager);
// And finally, commit
}
You can rely on Springto help you to get rid of this boilerplate code.
您可以依靠Spring来帮助您摆脱这些样板代码。
回答by Trenton D. Adams
Brian,
布莱恩,
It is okay to share EntityManagerFactory, but it is not okay to share EntityManager. See the Java Persistence wikibook.
共享EntityManagerFactory是可以的,但是共享EntityManager就不行了。请参阅Java 持久性 wikibook。
A more modern approach would be to do singletons with enums. So, assuming you don't expect to go around changing your persistence unit names (I would expect that not to occur anyhow)...
更现代的方法是用枚举做单例。因此,假设您不希望更改持久性单元名称(我希望无论如何都不会发生)......
So ideally...
所以理想...
- Use a singleton for the EntityManagerFactory instance, per persistence unit.
- Create a new entity manager on every call to retrieve one, and don't share them.
- 每个持久性单元为 EntityManagerFactory 实例使用单例。
- 在每次调用时创建一个新的实体管理器来检索一个,并且不要共享它们。
Using an enum for the singleton mechanism provides for... (Effective Java Second edition)
将枚举用于单例机制提供了...(Effective Java Second edition)
- Being concise
- Provides serialization machinery for free
- Prevents multiple instantiation of EntityManagerFactory with no synchronization problems. This happens because enum constructors are called at class load time, and cannot be called by your code.
- Ensures EntityManager is not shared unless a programmer makes the incorrect choice to do so.
- 简洁
- 免费提供序列化机器
- 防止 EntityManagerFactory 的多个实例化而没有同步问题。发生这种情况是因为枚举构造函数在类加载时被调用,并且不能被您的代码调用。
- 确保 EntityManager 不被共享,除非程序员做出了错误的选择。
public enum PersistenceUnitFactory { PERSISTENCE_UNIT_1("persistenceUnit1"), PERSISTENCE_UNIT_2("persistenceUnit2"); private final EntityManagerFactory emf; /** * Maps the persistence unit name to this instance of the enum. * * @param persistenceUnitName the name of the peristence unit in * persistence.xml * * @see #getPersistenceUnitName() */ PersistenceUnitFactory(final String persistenceUnitName) { emf = Persistence.createEntityManagerFactory(persistenceUnitName); } /** * Creates a new {@link EntityManager}. NEVER share this across threads. * * @return a new {@link EntityManager} */ EntityManager createEntityManager() { return emf.createEntityManager(); } }
public enum PersistenceUnitFactory { PERSISTENCE_UNIT_1("persistenceUnit1"), PERSISTENCE_UNIT_2("persistenceUnit2"); private final EntityManagerFactory emf; /** * Maps the persistence unit name to this instance of the enum. * * @param persistenceUnitName the name of the peristence unit in * persistence.xml * * @see #getPersistenceUnitName() */ PersistenceUnitFactory(final String persistenceUnitName) { emf = Persistence.createEntityManagerFactory(persistenceUnitName); } /** * Creates a new {@link EntityManager}. NEVER share this across threads. * * @return a new {@link EntityManager} */ EntityManager createEntityManager() { return emf.createEntityManager(); } }
Then it's as simple as asking for an EntityManager...
那么它就像要求一个 EntityManager 一样简单......
PersistenceUnitFactory.PERSISTENCE_UNIT_1.createEntityManager();
You can add more persistence units as you need them.
您可以根据需要添加更多持久性单元。