I'm working on a homework that using JPA but without spring. It has service layer and repository layer. I try to begin transaction in service and call save or update from repository and then commit in service. But how to get Current EntityManager in repository? My cod is like this:
Service:
public void save(Entity entity){
var em = factory.createEntityManager();
var t = em.getTransaction();
try {
t.begin();
repository1.save(entity);
// For saving one to many relation
repository2.save(entity.getChildEntity());
t.commit();
} catch (Exception e) {
t.rollback();
}
}
Repository:
// I don't want to pass EntityManager to method
public void save(T entity) {
var em = ? // How can I get EntityManager hear?
em.persist(entity);
}
CodePudding user response:
In your first snippet of the service I see that you have a factory
and there you create an EntityManager
. So the factory
exists...
Take your factory and make it accessible everywhere in your program. How?
Create a class specific only to creating the factory and the hibernate session. There you create public static getters for the fields that you need (such as the factory
and EntityManager
).
Example:
public class HibernateUtils
{
public static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory()
{
try
{
// Create the SessionFactory from hibernate.cfg.xml
return new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex)
{
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
// Close caches and connection pools
getSessionFactory().close();
}
}
CodePudding user response:
In Spring, the use of Services and Repositories is a further abstraction of JPA. If you want to use JPA without Spring, you can inject EntityManager using standard JavaEE/JakartaEE technologies, that is what Spring does under the hood.
Otherwise, if you want to do it by yourself, keep in mind that JPA is a standard for which there are a couple of implementations.
Let's take in consideration Hibernate, go to read the docs, stick with EntityManagerFactory and EntityManager instead of SessionManager (specific to Hibernate).
You can instantiate an EntityManager as:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my_PU");
EntityManager em = emf.createEntityManager();
The "my_PU" is a persistenceUnit that you need to define.
More info here: https://docs.oracle.com/cd/E19798-01/821-1841/bnbrj/index.html#:~:text=A persistence unit defines a,the persistence.xml configuration file.
CodePudding user response:
public class EntityManagerProvider {
private static final EntityManager entityManager;
public EntityManagerProvider() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("com.example.factory");
this.entityManager = emf.createEntityManager();
}
public static EntityManager getEntityManager() {
return entityManager;
}
}
Second Approach :
public class EntityManagerProvider {
private static final EntityManager entityManager;
private EntityManagerProvider() {}
public static synchronized EntityManager createOrGetEntityManager() {
if(entityManager == null) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("com.example.factory");
EntityManagerProvider.entityManager = emf.createEntityManager();
return EntityManagerProvider.entityManager;
}
return EntityManagerProvider.entityManager;
}
}
You need to create entityManager once and use it everywhere. I don't know where you create factory class but you can create entityManagerProvider class after creation of factory class.
You can simply call EntityManagerProvider.getEntityManager() to receive entityManager from class.
Please note that you don't need to initialize everywhere you can do it once and use it everywhere.
SecondApproach is better you can use it simply everywhere. EntityManagerProvider.createOrGetEntityManager method will give you entityManager.