Transakcja

0

Witam czy jest możliwe takie działanie: Metoda load w jednej transakcji oraz metoda save w drugiej, oraz takie złożenie jak poniżej.
Czy entityManager może działać między transakcjami? np żeby zadziałała metoda em.contains(entity)

	@PersistenceContext
	private EntityManager em;
	@Transactional
	public T load(PK id) {

		return em.find(type, id);
	}
	@Transactional
	public void save(T entity) {

		em.persist(entity);
	}
	Orders order = orderRepository.load(1L);
	order.setName("name");
	orderRepository.save(order);

Dostaję tutaj wyjątek:
PersistentObjectException: detached entity passed to persist

0

Musisz mieć na serwisie
Tzn. coś takiego:


@Transactional(propagation = Propagation.REQUIRED){
public void update(Long id,String name){
Orders order = orderRepository.load(id);
    order.setName(name);
    orderRepository.save(order);
}

0

orderRepository jest serwisem tzn jest zadeklarowany jako @Bean w konfiguracji jeśli o to Ci chodzi?

0

Piszesz w JEE czy Springu?

0

spring

Tak jak napisałeś to działa tylko myślałem o tym żeby parametrem metody było <T entity> tak jak w przedstawionym kodzie.

1

Najbardziej nie wiem po co w tym wszystkim save - przecież on tylko psuje

@Transactional(propagation = Propagation.REQUIRED){
public void update(Long id,String name){
Orders order = orderRepository.load(id);
    order.setName(name);

}

i wystarczy.

2
  1. Transakcje na poziomie DAO to zwykle zło. Jakbyś to napisał po ludzku, czyli transakcje miał na poziomie serwisu to w ogóle nie byłoby kłopotu.
  2. Jeśli mimo to wyciągasz obiekt "poza" transakcje to jest odpięty od bazy danych automatycznie i musisz go znowu powiązać przez load
  3. W trakcie kiedy obiekt jest powiązany z sesją bazy danych nie trzeba robić żadnych save, bo wszystkie zmiany automatycznie są wprowadzane. Jest to też pewne ryzyko, bo możesz sobie tak przypadkiem coś z bazy skasować jeśli "bawisz się" obiektem pobranym z bazy przy aktywnej sesji!
0

Możesz użyć 'EntityManager/merge'

managed =em.merge(detached)
managed.setXXX(..)
1

Czy entityManager może działać między transakcjami?

Tak to jest kontekst rozszerzony. Tyle tylko, że on tu nic nie załatwi, bo operujesz na odłączonej encji.

0
Shalom napisał(a):
  1. Transakcje na poziomie DAO to zwykle zło. Jakbyś to napisał po ludzku, czyli transakcje miał na poziomie serwisu to w ogóle nie byłoby kłopotu.
  2. Jeśli mimo to wyciągasz obiekt "poza" transakcje to jest odpięty od bazy danych automatycznie i musisz go znowu powiązać przez load
  3. W trakcie kiedy obiekt jest powiązany z sesją bazy danych nie trzeba robić żadnych save, bo wszystkie zmiany automatycznie są wprowadzane. Jest to też pewne ryzyko, bo możesz sobie tak przypadkiem coś z bazy skasować jeśli "bawisz się" obiektem pobranym z bazy przy aktywnej sesji!

Drążę jeszcze temat żeby dobrze zrozumieć, (pomińmy to że kod jest nie "elegancki" i transakcja nie jest we właściwej warstwie) np coś takiego, w pliku konfiguracyjnym mam entityManager z entityManagerFactory:

	@Bean
	public EntityManager entityManager(){
		
		EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence");
		EntityManager em = entityManagerFactory.createEntityManager();
		
		return em;
	}

	@Bean("ordersDao")
	public OrdersDao orders() {
		return new OrdersDao();
	}
@Autowired
	private EntityManager em;
	
	
	public Orders load(Long id) {

		Orders order = null;
		
		em.getTransaction().begin();
		order = em.find(Orders.class, 1L);
		em.getTransaction().commit();
		
		return order;
	}


	public void save(Orders aggregate) {

		em.getTransaction().begin();
		em.persist(aggregate);		
		em.getTransaction().commit();
	}

I w Main.java

		 Orders order = ordersDao.load(1L);
		 order.setName("name");
		 ordersDao.save(order);

to działa dlaczego nie działa z to samo z użyciem @Transactional? Chyba że to nie jest to samo? Czym się różni?

Taki efekt deatached otrzymuje dopiero w tej sytuacji:

	public void save(Orders aggregate) {

		em.getTransaction().begin();
		em.clear();  // Odłączam zarządzanie encją
		em.persist(aggregate);		
		em.getTransaction().commit();
	}

Otrzymuje:

PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist:

I tu sprawa jest jasna widze to, czy to oznacza że po @Transactional jest clear entityManagera? Czym to się różni?

0

Szczerze powiedziawszy to nie rozumiem jak Ci może to w ogóle działać w przypadku pierwszym - powinieneś mieć "EntityExistsException" (albo czegoś nie widzę).

0

Wraz z zakończeniem transakcji EM jest niszczony. Jedyny wyjątek – rozszerzony persistance context.

0

No właśnie jak to wyjaśnić dlaczego to działa, musi być jakaś różnica pomiędzy @Transactional a drugim rozwiązaniem. Ale zapewniam, że to działa.

0

Może masz jakąś skopaną implementację JPA ? (nie powinno działać -> wyrzuć :-) )

0

można tu jakoś przesłać źródła czy trzeba wszystko wklejać?

0

Najlepiej wstaw źródła na jakiegoś Githuba - wtedy łatwo będzie ogarnąć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1