我使用JSF,Spring和Mybatis进行webapp。这些框架分别在控制器,业务和dao层中使用。在我的DAO层中,我有CRUD操作的方法。现在,在我的控制器层中,我需要使用插入操作。为此,我可以使用此配置:
控制器层
我正在使用带注释的JSF
@ManagedBean
public class Controller{
@ManagedProperty("#{business}")
private Business business;
public void insert(){
business.insert();
}
}
业务层
我正在使用带注释的Spring
public interface Business{
public void insert();
}
@Service("business")
public class BusinessImpl implements Business{
@Autowired
private DaoMapper mapper;
@Override
@Transactional
public void insert(){
mapper.insert();
}
}
DAO图层
我正在使用Mybatis(mybatis-spring库)
public interface DaoMapper{
public void insert();
}
但是在这种情况下我的业务层只调用DAO层并且没有实现任何其他操作,我会考虑使用这种配置:
控制器层
@ManagedBean
public class Controller{
@ManagedProperty("#{daoMapper}")
private DaoMapper mapper;
public void insert(){
mapper.insert();
}
}
DAO图层
public interface DaoMapper{
@Transactional
public void insert();
}
我已经测试过并且工作正常,但我想知道我是否会招致不良行为
[编辑]
实际上,DaoMapper接口是一个与XML文件(Look)相关联的MyBatis类映射器。我不知道这是否是DAO课程。我想我应该把它称为 Persisence Layer 或 Mapper Layer
来源:http://www.infoq.com/articles/ddd-in-practice
如你所见。表示层,在我的情况下,控制器层(我想我又犯了另一个错误命名),直接调用DTO(或者这就是我的理解)
如果在我的控制器或表示层(无论你怎么称呼它)我需要使用插入或更新操作,我可以直接从mapper类调用,或者我必须为这个类调用mapper类创建一个新的业务类
现在。如果可以使用这种配置我有疑问:
假设在我的业务类的方法中,我需要调用插入操作。这就像:
@Service("business")
public class BusinessImpl implements Business{
@Autowired
private DaoMapper mapper;
@Override
@Transactional
public void insert(){
mapper.insert();
}
}
但是来自DaoMapper界面的方法插入已经有 @Transactional 注释。方法插入将受到 @Transactional 注释的两次影响。这不是问题吗?
答案 0 :(得分:2)
我建议不直接在控制器中使用DAO。在我看来。 Dao层是来自数据库的映射,就像你想要更改另一个数据库(例如从sql到nosql)一样,唯一的事情就是只创建一个新的DAO并注入,但是让控制器和服务功能完全没有改变。控制器也是如此,它的主要职责是处理请求和响应,工作应该由业务/服务层完成。如果错误的话,请指出
答案 1 :(得分:1)
如果要删除图层,可以使用Controller和Service,但跳过DAO。 您的服务可以直接调用映射器,因为您没有任何特定的查询代码。 我知道像Adam Bien这样的知名Java人士认为DAO是一种死亡模式。 http://www.adam-bien.com/roller/abien/entry/jpa_ejb3_killed_the_dao
答案 2 :(得分:0)
我建议无论如何都有服务层。它具有重要的功能。它实现了域模型的“动词”/动作,并且是您还可以通过 @Transactional
定义操作原子性的好地方。在我看来,使用 @Transactional
注释 MyBatis 映射器方法是一种不好的做法。实体(在您的案例中是 MyBatis 结果 POJO)是您的域模型的“名词”。
只有“名词”的域模型是没有用的,你需要能够对它执行一些操作(“动词”)。 “动词”由服务层实现。这就是为什么我认为在 99.9% 的情况下服务层是必要的。 到目前为止,您只遇到了业务逻辑操作与 CRUD 操作 1:1 的简单情况。但这是两件不同的事情。可能会有更复杂的情况。想象一下在线银行应用程序,您有注册新客户的用例。这是一个涉及多个实体的业务逻辑操作:您需要创建用户,并且需要创建与该用户关联的银行帐户。这必须发生在单个 SQL 事务中。 “动词”-“名词”分离是很自然的方法。
控制器是网页控制器或 REST 控制器。它们处理与页面模型相关的方面(在 JSF 的情况下为 @ManagedBean
)或定义 RESTful API(在 Spring WebMVC 的情况下为 @RestController
)。它们不是为了实现领域模型的动作。
同样由于这个原因,将实体用作 RESTful API 的 DTO 也是一种不好的做法。实体是域模型“名词”,RESTful API 的 DTO 定义了 RESTful API 层的表示。这些是不同的东西。