在 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 层?的主要内容,如果未能解决你的问题,请参考以下文章