I know that the best practice is having both service and dao layers and to add @Transactional annotations on the service level. But in my case it means most of my service classes is created just to repeat DAO methods... It is quite irritating.
eg.
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)
}
}
How dumb is that?
In most cases I really don't need fancy service methods since usually it is a matter of geting eg. a cathegory description and a list of entities that match the cathegory. That's why I'm looking for a simplified solution. Something as brilliant as using generics to avoid repeating DAOs :D http://www.javablog.fr/javahibernate-dont-repeat-the-dao-with-a-genericdao.html
I've searched for the answer. Among others I've read Where does the @Transactional annotation belong? but still haven't found my answer.
So I wonder if annotating DAO methods with @Transactional is really such a bad idea. Inspired by http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/#apistrategy I figured out a solution.
WHAT IF:
- I have only one service class (which is really needed) and annotate its methods with @Transactional
- for all other (simple) cases: I annotate DAO methods with @Transactional(propagation = Propagation.MANDATORY) and my controller methods with @Transactional(propagation = Propagation.REQUIRES_NEW)
** UPDATE 1 **
It would look something like this:
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";
}
}
In each case DAO uses session which is managed "above".
Is it very bad idea? Is there any better way to achieve what I need?