我知道最佳实践是同时拥有服务和 dao 层,并在服务级别添加 @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 注释属于哪里? 但仍然没有找到我的答案。
所以我想知道用@Transactional 注释DAO 方法真的是个坏主意。受http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/#apistrategy的启发,我想出了一个解决方案。
如果:
- 我只有一个服务类(这是真正需要的)并用 @Transactional 注释它的方法
- 对于所有其他(简单)情况:我用 @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 都使用“上方”管理的会话。
这是一个非常糟糕的主意吗?有没有更好的方法来实现我所需要的?