Java中的数据访问对象(DAO)

412
我正在查看一份文件,遇到了一个叫做DAO的术语。我发现它是一个数据访问对象。有人可以解释一下这到底是什么吗?
我知道它是一种用于从不同类型的数据源访问数据的接口,而在我的研究过程中,我还遇到了一个叫做数据源数据源对象的概念,这更加让我困惑。
我真的想知道在编程中,DAO是如何使用的。它是如何使用的?如果有任何解释这个概念的基础知识的页面链接,我也会很感激。
13个回答

520
数据访问对象(Data Access Object)基本上是一个对象或接口,提供对底层数据库或任何其他持久性存储的访问。
引自:http://en.wikipedia.org/wiki/Data_access_object 此外,请查看此处的序列图: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html 也许一个简单的例子可以帮助您理解这个概念:
假设我们有一个实体来表示雇员:
public class Employee {

    private int id;
    private String name;


    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

员工实体将被持久化到数据库中对应的Employee表中。 一个简单的DAO接口用于处理操纵员工实体所需的数据库操作,如下所示:
interface EmployeeDAO {

    List<Employee> findAll();
    List<Employee> findById();
    List<Employee> findByName();
    boolean insertEmployee(Employee employee);
    boolean updateEmployee(Employee employee);
    boolean deleteEmployee(Employee employee);

}

接下来,我们需要为该接口提供具体实现以处理SQL服务器,以及另一种处理平面文件等。


4
嗨Rami,我真的很高兴你用一个非常简单的例子来解释给我,这正是我需要的。你能否解释一下你所说的“具体实现”是什么意思?你是不是指我们必须通过将接口实现到类中来编写方法的定义..? - Vasanth Nag K V
1
是的,没错。就像一个名为EmployeeSQLServerDAO的类,通过以与SQL Server相关的方式提供其方法的完整实现来实现EmployeeDAO接口。 - Rami
8
那么一个DAO就是这样吗?它只是一个我们编写的类,用于访问数据库。每当需要从数据库获取服务时,我们创建一个DAO对象进行数据库操作,然后在获取所需数据后将DAO对象丢弃。我说的对吗?Rami,我能知道DAO概念的范围吗? - Vasanth Nag K V
8
是的,正如其名称所示,“The DAO”用于访问/更新特定实体/类的底层存储。因此,在上面的例子中,我们有一个员工类/实体,我们使用SQL服务器数据库表进行持久化。员工DAO将包含插入/删除/更新/选择员工的方法。 - Rami
3
@PhilipRego 我们当然可以有多个实现,例如MSSQL服务器实现和另一个使用CSV文件的实现,以用于单元测试。 - Rami
显示剩余10条评论

110

什么是数据访问对象(DAO) -

它是一个对象/接口,用于从数据存储的数据库中访问数据

为什么我们要使用DAO:

将数据检索与数据资源(如数据库)分离。
概念是"将数据资源的客户端界面与其数据访问机制分开。"
 

直接访问数据的问题在于数据源可能会更改。例如,考虑您的应用程序部署在访问Oracle数据库的环境中。然后它随后部署到使用Microsoft SQL Server的环境中。如果您的应用程序使用存储过程和特定于数据库的代码(例如生成数字序列),则如何在应用程序中处理它?你有两个选择:

  • 重写应用程序以使用SQL Server而不是Oracle(或添加条件代码以处理差异),或
  • 创建位于应用程序逻辑和数据访问层之间的层

DAO模式由以下内容组成:

  • Data Access Object接口 - 此接口定义要执行的标准操作模型对象(s)。
  • Data Access Object具体类 - 此类实现上述接口。这个类负责从数据源获取数据,可以是数据库/xml或任何其他存储机制。
  • 模型对象或值对象 - 此对象是简单的POJO,包含用DAO类检索的数据的get/set方法

查看示例

我希望这已经澄清了您对DAO的理解!


15

DAO(数据访问对象)是企业应用程序中非常常用的设计模式。它基本上是用来从各种数据源(DBMS、XML等)访问数据的模块。我建议您阅读一些示例,比如这个:

DAO示例

请注意,有不同的方式来实现原始的DAO模式,并且有许多框架可以简化您的工作。例如,ORM(对象关系映射)框架如iBatis或Hibernate,用于将SQL查询结果映射到Java对象。

希望对您有所帮助, 再见!


9
DAO模式或数据访问对象模式用于将低级别的数据访问API或操作与高级别的业务服务分离。以下是DAO模式的参与者。
- 数据访问对象接口 - 此接口定义要对模型对象执行的标准操作。 - 数据访问对象具体类 - 此类实现上述接口。该类负责从数据源(可以是数据库/ XML或任何其他存储机制)获取数据。 - 模型对象或值对象 - 这个对象是一个简单的POJO,包含get / set方法,用于存储使用DAO类检索的数据。
示例代码在这里: https://dzone.com/articles/building-simple-data-access-layer-using-jdbc

9
不要被过多的解释所困惑。DAO:从名称本身可以看出,它使用对象访问数据。DAO应该与其他业务逻辑分离。

当你将某物解构到其基本含义时,它变得如此具体。"数据访问对象" 对我来说听起来很"陌生"和抽象,但是你的简单解释使它变得容易理解,即使最初的名称应该从一开始就显而易见。 - Prid

8

我会尽力帮忙翻译,以下是涉及到IT技术的内容,为了确保准确性,我会尽量在不改变原意的情况下使其更加通俗易懂。请注意不要删除或更改HTML标签。

我将不针对Java进行专业描述,因为DAO和ORM在所有编程语言中都有应用。

要理解DAO,您首先需要了解ORM(对象关系映射)。这意味着,如果您有一个名为“person”的表,其中包含“name”和“age”两列,那么您需要创建该表的对象模板:

type Person {
name
age
}

现在,通过使用DAO,您可以不编写特定的查询语句来获取所有人的信息,无论您使用哪种类型的数据库(这可能会出现错误),您只需要执行以下操作:
list persons = DAO.getPersons();
...
person = DAO.getPersonWithName("John");
age = person.age;

你不需要亲自编写DAO抽象层,通常情况下,它是一些开源项目的一部分,具体取决于你所使用的语言和框架。

现在来到这里的主要问题:“..它被用在哪里..”。通常情况下,如果你正在编写复杂的业务和特定领域的代码,如果没有DAO,你的生活将会非常困难。当然,你不必使用提供的ORM和DAO,而是可以编写自己的抽象层和本地查询。我曾经这样做过,但几乎总是后悔的。


6

我认为在Oracle网站上可以找到最好的示例(连同解释):这里。还有一个很好的教程可在此处找到。


3
是我一个人觉得大多数Java教程和信息网站都非常老旧吗?那个教程是2008年的!许多Java相关的热门搜索结果甚至更旧。 - bergie3000
5
这种模式并不新。 - Bằng Rikimaru

5

Spring JPA DAO

例如,我们有一个名为 Group 的实体。

为此实体创建 GroupRepository 存储库。

public interface GroupRepository extends JpaRepository<Group, Long> {   
}

接下来,我们需要创建一个服务层,使用这个仓库。

public interface Service<T, ID> {

    T save(T entity);

    void deleteById(ID id);

    List<T> findAll();

    T getOne(ID id);

    T editEntity(T entity);

    Optional<T> findById(ID id);
}

public abstract class AbstractService<T, ID, R extends JpaRepository<T, ID>> implements Service<T, ID> {

    private final R repository;

    protected AbstractService(R repository) {
        this.repository = repository;
    }

    @Override
    public T save(T entity) {
        return repository.save(entity);
    }

    @Override
    public void deleteById(ID id) {
        repository.deleteById(id);
    }

    @Override
    public List<T> findAll() {
        return repository.findAll();
    }

    @Override
    public T getOne(ID id) {
        return repository.getOne(id);
    }

    @Override
    public Optional<T> findById(ID id) {
        return repository.findById(id);
    }

    @Override
    public T editEntity(T entity) {
        return repository.saveAndFlush(entity);
    }
}

@org.springframework.stereotype.Service
public class GroupServiceImpl extends AbstractService<Group, Long, GroupRepository> {

    private final GroupRepository groupRepository;

    @Autowired
    protected GroupServiceImpl(GroupRepository repository) {
        super(repository);
        this.groupRepository = repository;
    }
}

在控制器中,我们使用这个服务。
@RestController
@RequestMapping("/api")
class GroupController {

    private final Logger log = LoggerFactory.getLogger(GroupController.class);

    private final GroupServiceImpl groupService;

    @Autowired
    public GroupController(GroupServiceImpl groupService) {
        this.groupService = groupService;
    }

    @GetMapping("/groups")
    Collection<Group> groups() {
        return groupService.findAll();
    }

    @GetMapping("/group/{id}")
    ResponseEntity<?> getGroup(@PathVariable Long id) {
        Optional<Group> group = groupService.findById(id);
        return group.map(response -> ResponseEntity.ok().body(response))
                .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @PostMapping("/group")
    ResponseEntity<Group> createGroup(@Valid @RequestBody Group group) throws URISyntaxException {
        log.info("Request to create group: {}", group);
        Group result = groupService.save(group);
        return ResponseEntity.created(new URI("/api/group/" + result.getId()))
                .body(result);
    }

    @PutMapping("/group")
    ResponseEntity<Group> updateGroup(@Valid @RequestBody Group group) {
        log.info("Request to update group: {}", group);
        Group result = groupService.save(group);
        return ResponseEntity.ok().body(result);
    }

    @DeleteMapping("/group/{id}")
    public ResponseEntity<?> deleteGroup(@PathVariable Long id) {
        log.info("Request to delete group: {}", id);
        groupService.deleteById(id);
        return ResponseEntity.ok().build();
    }    
}

这似乎在解释存储库模式而不是原始作者要求的DAO模式。此外,我认为您的示例可能会误导,因为您的接口应该遵循集合的方法,因此您的某些操作并不适合。 - BuzZin'

4
数据访问对象(Data Access Object)负责管理与数据源的连接以获取和存储数据。它抽象了底层的数据访问实现,使业务对象能够透明地访问数据源。数据源可以是任何数据库,例如关系型数据库、XML仓库或平面文件系统等。

3

Dao类用于重用JDBC逻辑,Dao(Data Access Object)是一种设计模式。dao是一个简单的Java类,其中包含JDBC逻辑。

数据访问层在将业务逻辑层和持久层分离方面表现出色。DAO设计模式完全隐藏了其客户端的数据访问实现。

Java数据访问对象(Java DAO)是业务应用程序中的重要组件。业务应用程序几乎总是需要从关系型或对象数据库中访问数据,而Java平台提供了许多访问这些数据的技术。最古老且最成熟的技术是使用Java数据库连接(JDBC)API,它提供了执行针对数据库的SQL查询并逐个获取结果列的能力。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接