我知道最佳实践是同时拥有服务层和数据访问层,并在服务层添加@Transactional注解。但在我的情况下,这意味着大部分服务类只是为了重复DAO方法而创建... 这相当令人烦恼。
例如:
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)
}
}
这是多么蠢啊?
在大多数情况下,我真的不需要繁琐的服务方法,因为通常只涉及获取例如类别描述和与类别匹配的实体列表。这就是为什么我正在寻找简化的解决方案。像使用泛型来避免重复DAO一样聪明 :D http://www.javablog.fr/javahibernate-dont-repeat-the-dao-with-a-genericdao.html
我已经搜索了答案。其中包括我阅读过的其他问题,但仍然没有找到我的答案。
所以我想知道,用@Transactional注释DAO方法是否真的是一个坏主意。受http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/#apistrategy的启发,我想出了一个解决方案。
如果:
- 我只有一个服务类(真的需要),并对其方法进行@Transaction注释
- 对于所有其他(简单)情况:我使用@Transactional(propagation = Propagation.MANDATORY)注释DAO方法,然后在我的控制器方法中使用@Transactional(propagation = Propagation.REQUIRES_NEW)
** 更新1 **
它可能看起来像这样:
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";
}
}
在每种情况下,DAO都使用由上层管理的会话。
这是一个很糟糕的想法吗?有没有更好的方法来实现我需要的功能?