Pat*_*a K 10 java spring annotations dao transactions
我知道最佳做法是同时使用service和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)
}
}
Run Code Online (Sandbox Code Playgroud)
那是多么愚蠢?
在大多数情况下,我真的不需要花哨的服务方法,因为通常这是一个例如.导管描述和与导管相匹配的实体列表.这就是为什么我在寻找简化的解决方案.像使用泛型来避免重复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我找到了一个解决方案.
如果:
**更新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";
}
}
Run Code Online (Sandbox Code Playgroud)
在每种情况下,DAO使用在"上方"管理的会话.
这是非常糟糕的主意吗?有没有更好的方法来实现我的需求?
我不会说这是一个坏主意,因为这取决于您选择设计应用程序的情况。
如果您觉得不需要任何服务类(即具有比纯 DAO API 功能更多的 API 的类),那么我认为最好避免服务类,而只使用直接自动连接到控制器的 DAO 实现。
但是,如果您需要执行一些额外的逻辑并希望将其公开为 API,那么您可以编写服务类,该服务类将实现自定义逻辑以及这些 DAO 方法的包装函数(就像您上面给出的那样)。这将使代码更加清晰,因为您只需将服务类连接到控制器中,同时您可以使用服务类中的包装器 API 进行 DAO 调用。
如果您仅为自定义 API 保留服务类,并且没有 DAO 的任何包装 API,那么如果需要进行任何数据访问调用,您还需要将 DAO 连接到控制器类中。因此,在这种情况下,您将有效地在服务类和控制器类中连接 DAO。
更新1
这是来自示例项目之一的控制器和服务类
控制器
public class HomePageController {
@Autowired
private VideoService videoService;
//Controller method
@RequestMapping(value = "/tag/mostviewed")
public @ResponseBody
Map<String, List<Video>> showMostViewedVideosForTag (){
//service api
videoService.getMostViewedVideo(curatorTagName)
}
}
Run Code Online (Sandbox Code Playgroud)
服务等级
@Service(value = "videoService")
@Transactional(readOnly = true)
public class VideoServiceImpl implements VideoService {
@Autowired
private VideoDAO videoDAO;
@Autowired
private TagDAO tagDAO;
// WRAPPER API FOR THE DAO
@Override
public List<Video> getMostViewedVideo(String tagName) {
return videoDAO.getMostViewedVideo(tagName);
}
// A non wrapper API which does some business logic
@Override
@Transactional
public void assignTagsToVideo(String videoId, String userId, String... tags) {
for (String tag : tags) {
if (tagHeritageDAO.getTagHeritage(tag, videoId, userId) == null) {
Tag tagObj = tagDAO.getTag(tag);
if (tagObj != null) {
//some logic here to add tags to video
}
}
}
videoDAO.update(video);
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,唯一的服务连接到控制器类中,而 dao 则连接到服务类。这就是我所说的混合模式。如果我让你困惑了,我很抱歉。
归档时间: |
|
查看次数: |
2173 次 |
最近记录: |