[英]How to avoid repeatig DAO methods in Service classes? @Transactional annotated DAO and Service classes - is it acceptable practice?
我知道最佳做法是同時使用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)
}
}
那是多么愚蠢?
在大多數情況下,我真的不需要花哨的服務方法,因為通常這是一個例如。 導管描述和與導管相匹配的實體列表。 這就是為什么我在尋找簡化的解決方案。 像使用泛型以避免重復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";
}
}
在每種情況下,DAO使用在“上方”管理的會話。
這是非常糟糕的主意嗎? 有沒有更好的方法來實現我的需求?
我不會說這是一個壞主意,因為它取決於您選擇設計應用程序的情況。
如果你覺得,你不需要任何服務類(即API的類比純DAO API更多),那么我覺得最好避免使用服務類,只使用直接自動連接到控制器的DAO實現。
但是如果你需要做一些額外的邏輯並希望將它作為API公開,那么你可以編寫服務類,它將實現自定義邏輯以及這些DAO方法的包裝函數(如上所述)。 這將使代碼更清晰,因為您只需要將服務類連接到控制器中,同時您可以使用服務類中的包裝API進行DAO調用。
如果您只為自定義API保留服務類而沒有DAO的任何包裝API,那么如果您需要進行任何數據訪問調用,您還需要將DAO連接到控制器類。 因此,在這種情況下,您將有效地連接服務類和控制器類中的DAO。
更新1
以下是其中一個示例項目的Controller和Service類
調節器
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)
}
}
服務類
@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);
}
}
如您所見,唯一的服務是在控制器類中連接,並且dao連接到服務類。 這就是我所說的混合模式。 抱歉,如果我困惑你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.