2

我有 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 接口是一个 MyBatis 类映射器,它关联到 XML 文件(Look)。我不知道这是否是一个 DAO 类。我想我实际上应该称它为Persisence LayerMapper Layer

在此处输入图像描述

资料来源: http: //www.infoq.com/articles/ddd-in-practice

如你看到的。表示层,在我的例子中是控制器层(我想我又犯了一个错误命名),直接调用到 DTO(或者这就是我的理解)

如果在我的控制器或表示层(无论你怎么称呼它)我需要使用插入或更新操作,我可以直接从映射器类调用,或者我必须为从此类调用映射器类新创建一个业务类

现在。如果可以使用此配置,我有疑问:

假设在我的业务类的方法中我需要调用插入操作。这就像:

@Service("business")
public class BusinessImpl implements Business{
    @Autowired
    private DaoMapper mapper;

    @Override
    @Transactional
    public void insert(){
        mapper.insert();
    }
}

但是来自 DaoMapper 接口的方法insert已经有@Transactional注释。方法insert将受到@Transactional注释的两次影响。这不会是个问题吗?

4

3 回答 3

3

我建议不要直接在控制器中使用 DAO。在我看来。Dao 层是从数据库的映射,如果你想改变另一个数据库(例如从 sql 到 nosql),唯一的事情就是只创建一个新的 DAO 并注入,而让控制器和服务功能完全不改变。控制器也是如此,它的主要职责是处理请求和响应,工作应该由业务/服务层来完成。如果是错误的感谢指出

于 2013-05-21T07:12:02.943 回答
1

如果你想删除层,你可以拥有控制器和服务,但跳过 DAO。您的服务可以直接调用映射器,因为您没有任何特定的查询代码。我知道一些像 Adam Bien 这样知名的 Java 人认为 DAO 是一种死模式。 http://www.adam-bien.com/roller/abien/entry/jpa_ejb3_killed_the_dao

于 2013-05-21T06:57:29.047 回答
0

服务层定义域模型(业务逻辑)的操作及其原子性。

我建议无论如何都有服务层。它具有重要的功能。它实现了你的域模型的“动词”/动作,它是一个很好的地方,你还可以通过@Transactional. 在我看来,用@Transactional. 实体(在您的情况下是 MyBatis 结果 POJO)是您的域模型的“名词”。

没有动作的领域模型是没有用的。

只有“名词”的领域模型是没有用的,您需要能够对它执行一些操作(“动词”)。“动词”由服务层实现。这就是为什么我认为在 99.9% 的情况下服务层是必要的。到目前为止,您只遇到了业务逻辑操作与 CRUD 操作 1:1 的简单情况。但这是两个不同的东西。可能有更复杂的情况。想象一下在线银行应用程序,您有注册新客户的用例。这是一个涉及多个实体的业务逻辑操作:您需要创建用户并且需要创建与该用户关联的银行帐户。这必须发生在单个 SQL 事务中。“动词”-“名词”的分离是相当自然的做法。

控制器处理 Web 方面,它们不用于实现域模型的操作。

控制器是网页控制器或 REST 控制器。它们处理与页面模型相关的方面(@ManagedBean在 JSF 的情况下)或定义 RESTful API(@RestController在 Spring WebMVC 的情况下)。它们并非旨在实现域模型的操作。同样由于这个原因,将实体用作 RESTful API 的 DTO 也是一种不好的做法。实体是领域模型“名词”,RESTful API 的 DTO 定义了 RESTful API 层的表示。这些是不同的东西。

于 2021-05-09T11:57:27.607 回答