【问题标题】:For what to use DAO classes and Service classes用于什么 DAO 类和 Service 类
【发布时间】:2017-05-25 22:19:24
【问题描述】:

我已阅读有关 DAO 类和服务类的信息,但我不明白它们的用途。 我已经用 spring 和 hibernate 在 maven 中启动了一个项目,直到现在我已经在 servlet.xml 中添加了 hibernate 的配置:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
    <property name="annotatedClasses">
        <list>
              <value>com.fabbydesign.model.Useradmin</value>
        </list>
    </property>
</bean>

控制器的登录方法如下:

@RequestMapping(value = "/do.html", method = RequestMethod.POST)
public String doLogin(@Valid @ModelAttribute("userLogin") LoginForm lf, BindingResult bindingResult, Map<String, Object> model, HttpServletRequest request){

    //bindingResult.rejectValue("username", "label.title"); - to add new message error
    logger.trace("showLogin - post");

    //check fields if the filds are filled and respects the size from beans
    if(bindingResult.hasErrors())
        return "login";

    boolean userExists = loginService.checkLogin(lf.getUsername(), lf.getPassword());

    if(!userExists){
        bindingResult.rejectValue("username", "login.username.wrongUserOrPassword");
        return "login";
    }
    else{//set session
        request.getSession().setAttribute(adminSesName, true);
    }

    return "redirect:/admin/dashboard.html";
}

loginServiceImpl:

@Service("loginService")

公共类 LoginServiceImpl 实现 LoginService {

@Autowired
private LoginDAO loginDAO;

public void setLoginDAO(LoginDAO loginDAO) {
    this.loginDAO = loginDAO;
}

public Boolean checkLogin(String userName, String userPassword) {
    return loginDAO.checkLogin(userName, userPassword);
}

和 loginDAOimpl:

@Repository("loginDAO")

公共类 LoginDAOImpl 实现 LoginDAO {

@Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}

protected Session getSession() {
    return sessionFactory.openSession();
}

final static Logger logger = Logger.getLogger(LoginDAOImpl.class);

public boolean checkLogin(String username, String password) {

    Boolean userFound = false;
    Session session = sessionFactory.openSession();
    String sql = "from Useradmin where username = ?";
    Query<?> query = session.createQuery(sql);
    query.setParameter(0, username);

    List<?> list = query.list();
    if ((list != null) && (list.size() == 1)) {
        Useradmin ua = (Useradmin) list.get(0);

        if (BCrypt.checkpw(password, ua.getPassword())) {
            userFound = true;
        }

    }
    return userFound;
}

那么,我应该在服务类和 DAO 类中写什么? 我的理解是,从数据库中操作数据的代码需要保留在 DAO 类中,但服务类是干什么用的? 谢谢!

【问题讨论】:

  • 服务类用于业务逻辑
  • DAO - 数据库层,运行数据查询
  • 您可以暂时阅读这些 SO 帖子:DAOService classes
  • 我投票结束这个问题,因为这个问题是关于架构而不是编程问题

标签: java spring hibernate dao service-layer


【解决方案1】:

你可以参考这个简单的例子:

1.PersonDao只关心数据库操作。

package com.pechen.dao;

import java.util.List;

import com.pechen.entity.Person;

public interface PersonDao {

    public void save(Person p);

    public List<Person> list();

}

2.PersonDaoImpl 是实现。

package com.pechen.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;

import com.pechen.entity.Person;

public class PersonDaoImpl implements PersonDao {

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void save(Person p) {
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();
        session.save(p);
        tx.commit();
        session.close();
    }

    @SuppressWarnings("unchecked")
    public List<Person> list() {
        Session session = sessionFactory.openSession();
        List<Person> rst = session.createQuery("from person").getResultList();
        session.close();
        return rst;
    }

}

3。 PersonService关心业务逻辑,在数据库操作之前你可以为所欲为。

package com.pechen.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.pechen.dao.PersonDao;
import com.pechen.dao.PersonDaoImpl;
import com.pechen.entity.Person;

public class PersonService {

    @Autowired
    private PersonDao personDao;

    public void setPersonDao(PersonDaoImpl personImpl) {
        this.personDao = personImpl;
    }

    public void savePerson(Person person) {
        // other business logic
        this.personDao.save(person);
        System.out.println("Save person successfully: " + person);
    }

    public List<Person> getPersons() {
        // other business logic
        return this.personDao.list();
    }

}

【讨论】:

  • 感谢您的示例,这很有帮助。所以,从我从您的示例中了解到,例如,业务逻辑从 DAO 获取数据,例如过滤数据,或者例如在这里进行一些分页,然后在业务逻辑完成后检索数据,对吗?有没有办法避免添加此代码:@Autowired private SessionFactory sessionFactory;公共无效 setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } 到我拥有的每个服务层?例如创建一个通用的,其余的来实现通用的?
  • 您对业务逻辑的理解是正确的。你提到的代码在Dao层,这样可能很难避免这个代码块。如果您不使用依赖注入,则可能是这样。
  • 好的,10 倍。例如,我的控制器中有这段代码,用于从 xml 中提取静态数据: context = new ClassPathXmlApplicationContext("staticData/formFill.xml"); StudentFormDataBean sb (StudentFormDataBean)context.getBean("studentFormData");返回 sb.getTypeOfStudies();在这种情况下,我应该选择你的例子中的一些逻辑:创建一个服务类和一个 dao 类?
  • 可以,你可以创建一个service和dao来管理业务逻辑和db操作。
【解决方案2】:

DAO 提供与数据库和操作的连接。

服务层提供了对发送到和从 DAO 发送的数据进行操作的逻辑。

还有安全性 - 如果您的服务层与数据库无关,则除了通过服务之外,从客户端访问数据库会更加困难。

【讨论】:

  • sa,关于 DAO,我知道它从数据库中接收和查询数据。据我了解,如果我想更改数据库(从 mysql 到 oracle),我只需要更改 daoIMPL 类?
  • 我很确定你的 daoIMP 只是接口,如果你想在 spring 中更改数据库,你所要做的就是在应用程序配置中更改数据库驱动程序,如果你使用像 hibernate 这样的 ORM,你应该更改 hibernate从 MySQLDialect 到 ORACLE 等方言
  • 如果你对实现感兴趣,你可以阅读这个javaworld.com/article/2074052/design-patterns/…它有点旧的文章,但仍然很有帮助:)
  • DAO 不应该真正管理与数据库的连接,它应该使用连接假设您有多个必须在 TX 事务中更新的表......
【解决方案3】:

Service层提供业务操作和调用DAO层。

DAO 层用于数据库层。这意味着它执行数据操作。这是您进行数据检索、数据保存和其他数据库操作的地方。

【讨论】:

    【解决方案4】:

    这个问题的答案可能很详细,所以我会在这里尽量坚持一些细节,并会在必要时发布链接。

    对于一些基础工作,

    分层和分层架构:您必须了解应用程序的层和层之间的区别。

    参考资料:- What is the difference between tier vs layer application?

    N-Tiered vs N-Layered architecture/design

    因此,如果您的应用程序具有三个主要层:表示层、服务层和数据库,那么服务层就是保留服务类的层。这是将核心业务逻辑添加到您的应用程序的地方。例如。如果您正在使用三层开发票务应用程序,并且添加了全面的身份验证功能。

    1. 网页将成为表示层的一部分。
    2. 验证用户 ID、加密检查等功能 超时检查等将成为您服务层的一部分(服务 类)
    3. 与数据库的连接和各自的交互将在数据库层 (Hibernate) 中得到处理

    另外: 如今,应用程序架构不仅仅局限于三层系统。分布式应用程序架构的采用越来越多,其中上面第 2 点中提到的服务层被分解为多个小型服务,每个服务都有自己的数据库。 (关键字检查:Microservices)。此外,他们使用消息队列进行交互,但谈论所有这些事情与这个问题无关。

    推荐: 1. 阅读有关服务层设计的文章,以及不同的需求如何导致服务类的不同设计。 2. 您阅读了服务设计中常用的设计模式,如提供者、工厂、单例等。

    希望我已经回答了你的问题。

    注意:您需要用“架构”标记您的问题,因为它更多的是架构问题而不是 Java 编程问题。

    【讨论】:

    • 10x 供您发表评论。如何标记我的问题?添加另一个名为“架构”的标签?但是,在我了解了 DAO 和服务层之后,我会询问代码是否可以,以及如何更好,所以......问题将是关于 java 编程的 :)
    • 您绝对可以询问代码...我会尽我所能回答。您可能需要为此发布一个不同的问题。另外,我不认为你可以在问题中添加标签,我也不会。刚刚检查了元数据,发现需要有 1500 的权限才能添加标签。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    • 2013-07-28
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    相关资源
    最近更新 更多