Wiem, że najlepszą praktyką jest posiadanie zarówno warstwy usługowej, jak i dao oraz dodawanie adnotacji @Transactional na poziomie usługi. Ale w moim przypadku oznacza to, że większość moich klas usług jest tworzona tylko po to, aby powtarzać metody DAO ... To dość irytujące.Jak uniknąć powtarzania metod DAO w klasach usług? @Transactional adnotowane DAO i klasy usług - czy jest to dopuszczalna praktyka?
np.
public interface FooDAO {
public List<FooVO> list(int cathegoryId);
public List<FooVO> list(int cathegoryId, int ownerId);
}
@Service
@Transactional
public class FooService {
protected @Autowired FooDAO dao;
public List<FooVO> list(int cathegoryId) {
dao.list(cathegoryId);
}
public List<FooVO> list(int cathegoryId, int authorId) {
dao.list(cathegoryId, authorId)
}
}
Jakie to głupie?
W większości przypadków naprawdę nie potrzebuję wyrafinowanych metod serwisowania, ponieważ zazwyczaj jest to kwestia zdobycia np. opis kategorii i listę podmiotów pasujących do kategorii. Dlatego szukam uproszczonego rozwiązania. Coś tak wspaniałego jak używanie generycznych, aby uniknąć powtarzania DAO: D http://www.javablog.fr/javahibernate-dont-repeat-the-dao-with-a-genericdao.html
Szukałem odpowiedzi. Między innymi przeczytałem Where does the @Transactional annotation belong? , ale nadal nie znalazłem mojej odpowiedzi.
Więc zastanawiam się, czy przypisywanie metod DAO za pomocą @Transactional jest naprawdę tak złym pomysłem. Zainspirowany przez http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/#apistrategy znalazłem rozwiązanie.
CO JEŚLI:
- Mam tylko jedną klasę usług (co jest naprawdę potrzebne) i opisywanie swoich metod z @Transactional
- dla wszystkich innych przypadkach (prosty): I opisywanie metody DAO z @Transactional (propagacja = Propagation.MANDATORY) i moje metody kontroler z @Transactional (propagacja = Propagation.REQUIRES_NEW)
** UPDATE 1 **
Wyglądałoby mniej więcej tak:
public interface FooDAO {
@Transactional(propagation = Propagation.MANDATORY, readOnly=true)
public List<FooVO> list(int cathegoryId);
...
}
@Service
public class FooService {
protected @Autowired FooDAO dao;
@Transactional // propagation REQUIRED
public List<FooVO> magic(FooVO fooVO) {
//do sth complicated here ;)
}
// We do not repeat DAO methods in the Service class.
// No wrapping methods here !!!
}
@Controller
public class FooMagicController {
protected @Autowired FooService fooService;
...
fooService.magic(fooVO);
...
}
@Controller
public class FooController {
protected @Autowired FooDAO dao; //DAO wired directly in the Controller class !!!
@Transactional(propagation = Propagation.REQUIRES_NEW)
@RequestMapping(".....")
public String listFoo(Model model,...) throws Exception {
model.addAttribute("list", dao.list(13));
return "xyz";
}
}
W każdym przypadku DAO używa sesji, która jest zarządzana "powyżej".
Czy to bardzo zły pomysł? Czy istnieje lepszy sposób na osiągnięcie tego, czego potrzebuję?
Znalazłem podobne pytanie: http://stackoverflow.com/questions/4462785/transactional-controller-vs-service "tak, dodanie @Transactional do metod kontrolera jest całkowicie poprawne." , ale "kontroler nie powinien wiedzieć o warstwie trwałości i może być konieczne ponowne użycie logiki biznesowej w aplikacji komputerowej, w której nie ma już warstwy kontrolera." –