Transakcja

Odpowiedz Nowy wątek
2017-03-20 13:54
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

edytowany 1x, ostatnio: borpaw, 2017-03-20 13:55

Pozostało 580 znaków

2017-03-20 13:58
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);
}
edytowany 1x, ostatnio: scibi92, 2017-03-20 14:04

Pozostało 580 znaków

2017-03-20 14:01
0

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

Pozostało 580 znaków

2017-03-20 14:05
0

Piszesz w JEE czy Springu?

Pozostało 580 znaków

2017-03-20 14:07
0

spring

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

edytowany 1x, ostatnio: Koziołek, 2017-03-20 15:03

Pozostało 580 znaków

2017-03-20 14:32
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.


Bardzo lubie Singletony, dlatego robię po kilka instancji każdego.
A faktycznie, pomyliło mi się z Session z hibernate tam trzeba było dac update :) - scibi92 2017-03-20 14:47

Pozostało 580 znaków

2017-03-20 14:40
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!
edytowany 2x, ostatnio: Shalom, 2017-03-20 15:53
Dokładnie, dlatego posiadanie save czy update uważam w tej architekturze ("encja...") za błąd, bo daje złudne poczucie kontroli. I tak się zapisze i lepiej nie wprowadzać czytających kod w błąd wywoływaniem jakiegoś save() czy update(). - jarekr000000 2017-03-20 14:44
Naprawiałem kiedyś w projekcie buga z serii dane znikają z bazy danych!i okazało się właśnie że ktoś chciał sobie wysłać dane do widoku, ale jednocześnie nie wszystko, więc nullował sobie parametry w obiektach / filtrował listy i dopiero takie coś zwracał do widoku. Ale że te wszystkie operacje działy się wewnątrz transakcji a on cudował z obiektem entity to... ;] - Shalom 2017-03-20 15:57
E... ja kiedyś sobie sam tak zrobiłem (z 10 lat temu) :-) Problem wyszedł na demo - weszliśmy na widok Usera bez uprawienień (który to miał tylko pokazywać część danych, zgadnij jak zrobiliśmy żeby części pól nie wyświetlać :-) ?). Session per view + Spring + architektura encja na twarz -> jaka piękna katastrofa. - jarekr000000 2017-03-20 16:08

Pozostało 580 znaków

2017-03-20 14:47
0

@borpaw To lekturkę mam dla Ciebie : http://docs.spring.io/spring-[...]ference/html/transaction.html

Pozostało 580 znaków

2017-03-20 14:48
0

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

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

Pozostało 580 znaków

2017-03-20 15:04
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.

Pozostało 580 znaków

2017-03-20 22:27
Wesoły Pomidor
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?

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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