Transakcje przy repozytoriach Spring Data

0

W jaki sposób najczęściej obsługuje się transakcje, gdy korzysta się ze Spring Data? Tworzy się dodatkowy serwis, z metodami dla których chcemy nałożyć transakcje?

Repozytorium:

package com.mp.webapp.repository;

import com.mp.webapp.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<UserEntity, Long> {
}

Serwis:

package com.mp.webapp.service;

import com.mp.webapp.entity.UserEntity;
import com.mp.webapp.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class UserService implements IUserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    @Transactional
    public UserEntity save(UserEntity user) {
        return userRepository.save(user);
    }

    @Override
    @Transactional
    public Iterable<UserEntity> save(Iterable<UserEntity> users) {
        return userRepository.save(users);
    }

    @Override
    @Transactional
    public void delete(UserEntity user) {
        userRepository.delete(user);
    }

    @Override
    @Transactional
    public void delete(Iterable<UserEntity> users) {
        userRepository.delete(users);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        userRepository.delete(id);
    }

    @Override
    public List<UserEntity> findAll() {
        return userRepository.findAll();
    }
}

Korzystając z takiego serwisu nie mamy dostępu do wszystkich metod jakie udostępnia interfejs JpaRepository. Może jest jakiś lepszy sposób?

0

A na interfejsie od repo nie mozesz dac Transactional

0

Ale wtedy wszystkie metody interfejsu są objęte transakcją, tak się robi?

1

@Szczery adnotacja transactional nie działa dla interfejsów. Musi być aplikowana dla konkretnych klas. Polecam korzystać z IntelliJ, on ładnie oznacza takie rzeczy i od razu widzisz które metody złapały jakieś AOP a które nie.
@bakeraw2 możesz zawsze adnotować całą klasę, ale nie interfejs ;)
Ale generalnie zrobiłeś to źle, a przynajmniej niezbyt dobrze.

  1. Ten twój serwis to DAO, nie bardzo rozumiem co on niby dodaje do tego dao co mu wstrzykujesz skoro on tylko deleguje metody. Po co ta klasa w ogóle jest? o_O
  2. Transakcje lepiej wyciagać wysoko, z powodu wydajności i z powodu atomowych operacji. W jakimś faktycznym serwisie który obsługuje logikę biznesową będziesz często miał kilka operacji związanych z jedną "logiką" i warto żeby cały taki zestaw był atomowy.
1

Bzdury, bzdury, bzdury!!!

Crudowe metody w JPA Data są objęte transakcją domyślnie. Na metodach interfejsu ze Spring DATA! można oczywiście definiować @Transactional !

Radzę poczytać dokumentację, a nie wypisywać głupoty. To tylko ok. 40 stron. Proszę się zapoznać z tym:

http://docs.spring.io/spring-data/jpa/docs/1.0.0.M1/reference/html/#transactions

A co do pomysłu z posta autora co do klasy serwisu opakowującej DAO, to jest poroniony pomysł. Głupota do kwadratu. Jak już napisał kolega Shalom, serwis to tylko z logiką biznesową.

0

@krgr albo ja nie rozumiem o co ci chodzi, albo ty nie rozumiesz o czym pisałem, więc po kolei:
Nie można dać @Transactional na interfejsie. Tzn można, ale to wcale nie sprawi że wszystkie klasy które go implementują nagle będą miały @Transactional. Tak samo zresztą jest dla metod w definicji interfejsu - nie można na nich dać @Transactional. W konkretnych implementacjach możemy jak najbardziej dodać taką adnotację i będzie ok i zupełnie bez znaczenia jest czy będzie to metoda z takiego czy innego interfejsu.
Wyobraź sobie że znam dokumentację jak i Springa całkiem znośnie ;) Ja polecam za to czytać posty ze zrozumieniem. Są krótsze niż 40 stron, więc może dasz radę ;)
Ale skoro polecasz dokumentację której sam nie czytasz?

Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.

1

Shalom kolego,

Czy znasz Spring Data JPA? Tam się nie implementuje interfejsów. Dałem konkretnego linka do konkretnego przypadku, który autor rozpatrywał. Zresztą wyraźnie napisałem, że chodzi o Spring DATA!

0

@krgr kajam się, faktycznie nie zrozumiałem do końca o co autor pytał a potem źle zrozumiałem twój komentarz. Mea culpa!

@bakeraw2 tak jak napisał @krgr repozytoria generowane przez Spring Data automatycznie są tranzakcyjne, nie musisz nic więcej z nimi robić. Ale ja bym się zastanowił czy to jest całkiem dobre rozwiązanie. Bo zakładanie tranzakcji tak nisko, szczególnie jeśli potem operujesz sporo na bazie, może być zwyczajnie bardzo kosztowne. Dlatego mimo wszystko obejmowanie metod biznesowego serwisu tranzakcjami ma sens.

0

Ok,

Co do service'u to uważam że zazwyczaj jest niezbędny. Domyślnie Spring załatwia za nas wszystkie problemy, które mogłyby wyniknąć z zarządzania transakcjami - poprzez poziom propagacji transakcji ustawiony na REQUIRED. Dzięki temu transakcje w serwisie 'opakują' transakcje na DAO. Więc tymi transakcjami na DAO bym się nie przejmował.

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