在 Hibernate ORM 中总是需要 DAO 层?

Posted

技术标签:

【中文标题】在 Hibernate ORM 中总是需要 DAO 层?【英文标题】:DAO Layer always required in Hibernate ORM? 【发布时间】:2013-01-07 18:52:57 【问题描述】:

我想我在实现 Hibernate ORM 时完全搞糊涂了。

我的理解是 Hibernate 可以让你消除 DAO 层。并不是说它是强制性的(甚至是有利的),但它确实让你这样做。

但是,就我而言,我不明白这怎么会发生。 我将使用我系统的两个实体 - Company 和 CompanyRegistration 来解释我的案例。

公司类-

@Entity
@Table(name = "Company")
public class Company extends LightEntity implements BaseSerializable 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Id")
    private int id;

    @Column(name = "Code")
    private String code;

    @Column(name = "Name")
    private String name;

    @Column(name = "Address")
    private String address;

    @Column(name = "ContactNumber1")
    private String contactNumber1;

    @Column(name = "ContactNumber2")
    private String contactNumber2;

    @Column(name = "EMail")
    private String email;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "company", cascade = CascadeType.ALL)
    private List<CompanyRegistration> companyRegistrations;

    public Company(String code, String name) 
        this.code = code;
        this.name = name;
    

    // getters and setters follow..

CompanyRegistration 类 -

@Entity
@Table(name = "CompanyRegistration")
public class CompanyRegistration extends LightEntity implements BaseSerializable 

    @Id
    @Column(name = "RegistrationNumber")
    private String registrationNumber;
    @Column(name = "YearOfRegistration")
    private String yearOfRegistration;
    @ManyToOne
    @JoinColumn(name = "CompanyId", nullable = false)
    private Company company;

    public CompanyRegistration(String registrationNumber, String yearOfRegistration, Company company) 
        this.registrationNumber = registrationNumber;
        this.yearOfRegistration = yearOfRegistration;
        this.company = company;
    

    public String getRegistrationNumber() 
        return registrationNumber;
    
    public String getYearOfRegistration() 
        return yearOfRegistration;
    
    public String getCompanyId() 
        return company.Id;
    

在 Company 类中,我指定了CascadeType.All,以便 Hibernate 负责保存、更新、删除等级联操作,并将它们持久化到数据库中。因此,CompanyRegistration 集合中的任何更改都将直接反映到其数据库表中。因此,Hibernate 将满足我持久保存 CompanyRegistration 集合的需求。

但是,我仍然必须使用 DAO 层来持久化 Company 对象,不是吗?我知道我可以在该层中使用 HQL 而不是标准 SQL,但这不是我关心的问题。还有一个单独的层。

我很可能误解了这里的概念。

所以,我的问题是事情是这样运作的吗? 另外,除了缓存(对我来说是一个很大的优势)、自动持久化集合(但不是所有者对象)和 HQL(由于我还没有使用过,因此无法对此发表评论)之外,Hibernate 提供了哪些优势?

【问题讨论】:

【参考方案1】:

我想你还没有理解DAO layer aka Data Access Objects 层本身的含义。无论你使用什么 ORM 工具,你总是需要一个 DAO 层。每个实体在 DAO 层都有它的 DAO 类。正是这一层,每个实体类创建会话对象并在 persistent 对象上调用 hibernate api,即 save()、update()、delete() 等。是的,您需要了解休眠中的HQL。我们将它用于休眠的某些功能,例如 createQuery() api。并阅读this 了解 DAO 模式。

【讨论】:

我同意。 ORM 不是 DAO 的替代/覆盖模式。它们应该一起使用。对吗? 对的伙伴,你总是可以实现你的选择或要求的设计模式,但最后你有一个 DAO 层用于使用 ORM 工具访问数据库。【参考方案2】:

您的 DAO 实现将仅用于调用 EntityManager 中的方法,您不需要创建 SQL 或 HQL 来插入,您可以通过调用 EntityManager 的 persist 方法轻松完成。

public class CompanyDAOImpl

    public void save(Company company) 
        entityManager.persist(company) 
    


entityManager 可以通过 spring 配置设置,也可以将其设置为对象...这取决于您如何创建它。

【讨论】:

entityManager.remove(object); entityManager.find(class, id);也是您可以调用的其他方法。您可以查看 javadoc 以更好地理解 docs.oracle.com/javaee/5/api/javax/persistence/… 好的。这意味着我只能在特定数据检索的情况下使用 HQL,而 EntityManager 可能无法执行,对吧? 另外,对于 Hibernate 会话管理,Session 不是比 EntityManager 更好吗? 是的,但是你也可以使用HQL来插入、删除等……我从来不需要使用的 是的。我明白了。但是我觉得还是尽量利用EntityManager/Session比较好。【参考方案3】:

Hibernate 最大的优势是对象关系映射。它会自动为您在关系数据和对象之间进行映射。如果没有 Hibernate,您将不得不编写自己的代码来手动创建域对象,或者从您每次检索的数据集中创建对象列表。

一个例子,当你使用 Hibernate 检索一个对象时,session.get(objectId),它返回一个所谓的托管对象。当事务提交时,Hibernate 将对这个对象进行脏检查(检查修改),并在必要时将更改刷新到 db。您实际上不需要调用更新操作。

其他好处包括:

LazyLoading:关系集合可以在以后需要时加载 而不是一次全部。它提高了性能,因为如果 您的收藏很大,在您需要时加载所有内容 消耗大量内存。 并发处理:Hibernate 为您提供了以下功能: 处理并发,例如 OptimisticLocking。如果你使用 OptimisticLocking,每次将对象保存到数据库时,它 将检查版本列中的冲突并抛出 如有例外。

否则,您将不得不自己实现来处理这些情况。

关于EntityManager和Session的区别,它们是Hibernate的两个ORM API实现。 EntityManager 是JPA 的实现。语法和用法之间存在一些差异。您可以选择使用其中任何一个。你最好坚持一个。我已经看到了在这两者之间混合的程序。

【讨论】:

顺便说一句,您对添加额外的 DAO 层有何顾虑?可以将数据访问代码放在模型层而不是单独的层中。可以看到Spring Roo生成的代码的实现@ 我不关心添加 DAO 层,而是关心数据访问代码;它是否与模型一起存在或存在于单独的层中。但是,现在我明白 ORM 不是 DAO 模式的替代品。那是我的误解。

以上是关于在 Hibernate ORM 中总是需要 DAO 层?的主要内容,如果未能解决你的问题,请参考以下文章

ORM 和 DAO - 设计问题

hibernate框架

mybatis(Mybatis与hibernate的不同原始Dao开发Mapper动态代理开发)

hibernate.zzh

ORM基础

hibernate 通用 dao 重载 removeById