how @PersistenceContext deals with threads specially with entityManager and Session

16 hours ago 2
ARTICLE AD BOX

I am facing an issue and trying to figure out what is happening. From what I understand, using @PersistenceContext injects an EntityManager into my class. It should be thread-aware, tying the EntityManager to a thread using a ThreadLocal. However, looking at my code:

package org.example.service; import org.example.entity.Account; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import org.hibernate.Session; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class AccountParallelService { @PersistenceContext private EntityManager entityManager; @Transactional public void updateAccountAsync(Long accountId, String newName) { Session session = entityManager.unwrap(Session.class); org.hibernate.internal.SessionImpl realSession = entityManager.unwrap(org.hibernate.internal.SessionImpl.class); System.out.println("Session code: " +entityManager.unwrap(Session.class).hashCode()); System.out.println("Thread code: " + Thread.currentThread().hashCode()); System.out.println("Entity " + entityManager.hashCode()); System.out.println("realSession " + System.identityHashCode(realSession)); Account acc = entityManager.find(Account.class, accountId); if (acc != null) { acc.setFirstName(newName); entityManager.merge(acc); } try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }

When I call this method using three threads, it successfully executes on three different threads. However, it prints the same hash code for the Session and EntityManager, even though the SessionImpl hash code is different for each.

I saw a friend write similar code where the Session hash code was different for each thread, but unfortunately, I don't have his code to compare. I am a newbie to Spring and still learning.

package org.example; import org.example.service.AccountParallelService; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MainApp { public static void main(String[] args) { System.out.println("Starting Spring Application Context..."); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); AccountParallelService parallelService = context.getBean(AccountParallelService.class); try { ExecutorService service = Executors.newFixedThreadPool(5); List<Callable<Void>> tasks = new ArrayList<>(); tasks.add( () -> { parallelService.updateAccountAsync(1L, "Thread_Name_1"); return null; }); tasks.add(() -> { parallelService.updateAccountAsync(2L, "Thread_Name_2"); return null; }); tasks.add(() -> { parallelService.updateAccountAsync(3L, "Thread_Name_3"); return null; }); service.invokeAll(tasks); service.shutdown(); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("\nShutting down Spring Context..."); context.close(); } } } the out put Session code: 62790143 Session code: 62790143 Thread code: 498198174 Session code: 62790143 Thread code: 2143293285 Entity 62790143 Thread code: 95675270 Entity 62790143 realSession 1071349779 realSession 620176498 Entity 62790143 realSession 105967982
Read Entire Article