当前位置: 首页 > 面试题库 >

用更简单的解决方案代替完整的ORM(JPA /休眠):推荐的加载/保存模式?

郝承悦
2023-03-14
问题内容

我正在开发一个新的Java
Web应用程序,并且正在探索保存数据的新方法(对我来说是新的!)。我大多数都具有JPA和Hibernate的经验,但是,除了简单的情况之外,我认为这种完整的ORM可能会变得非常复杂。另外,我不太喜欢和他们一起工作。我正在寻找一个新的解决方案,可能更接近SQL。

我目前正在研究的解决方案:

  • MyBatis
  • jooq
  • 纯 SQL / JDBC,可能带有DbUtils或其他一些基本实用程序库。

但是,与Hibernate相比,我担心的是这些解决方案有两个用例。我想知道这些用例的推荐模式是什么。

用例1-获取实体并访问其某些关联的子代和孙代实体。

  • 假设我有一个Person实体。
    • Person具有关联的Address实体。
    • Address具有关联的City实体。
      • City实体具有name属性。

从人员实体开始,访问城市名称的完整路径为:

person.address.city.name

现在,假设我PersonService使用以下方法从加载了Person实体:

public Person findPersonById(long id)
{
    // ...
}

使用Hibernate,Person可以根据需要延迟加载与关联的实体,因此可以访问person.address.city.name并确保我可以访问此属性(只要该链中的所有实体都不为空)。

但是使用我正在研究的3个解决方案中的任何一个,它都更加复杂。使用这些解决方案,建议使用哪种模式来处理该用例?首先,我看到3种可能的模式:

  1. 所需要的所有关联的子代和孙代实体都可以通过所使用的SQL查询来快速加载。

但是我看到的这个解决方案的问题是,可能还有一些其他代码需要访问来自该实体的 其他
实体/属性路径Person。例如,也许某些代码需要访问person.job.salary.currency。如果要重用findPersonById()已有的方法,则SQL查询将需要加载更多信息!不仅关联address->city实体,而且关联job->salary实体。

现在,如果还有其他 10 个地方需要从人员实体开始访问其他信息,该怎么办?我是否应该始终热切地加载 所有
可能需要的信息?或者也许有12种不同的服务方法来加载人实体?:

    findPersonById_simple(long id)

findPersonById_withAdressCity(long id)

findPersonById_withJob(long id)

findPersonById_withAdressCityAndJob(long id)

...

但是,每当我使用一个Person实体时,我就必须知道它已经加载了什么,没有加载了什么……可能会很麻烦,对吧?

  1. 在实体的getAddress()getter方法中Person,是否可以进行检查以查看地址是否已经加载,如果没有,则延迟加载它?这是现实生活中经常使用的模式吗?

  2. 还有其他模式可用于确保我可以从加载的模型访问所需的实体/属性吗?

用例2-保存实体,并确保还保存了其关联的和修改的实体。

我希望能够Person使用此PersonService方法保存实体:

public void savePerson(Person person)
{
    // ...
}

如果我有一个Person实体并且要更改person.address.city.name为其他实体,那么City当我保存该实体时,如何确保该实体的修改将得以保留Person?使用Hibernate,可以很容易地将保存操作
级联 到关联的实体。我正在研究的解决方案如何?

  1. 我应该使用某种 肮脏的 标记来知道在保存人时还必须保存哪些关联的实体吗?

  2. 还有其他已知模式可用于处理此用例吗?

更新 :有一个讨论有关在JOOQ论坛这个问题。


问题答案:

当不使用真正的ORM时,这种问题很典型,并且没有灵丹妙药。对于使用iBatis(myBatis)的(不是很大的)Web应用程序来说,一种对我有用的简单设计方法是使用两层持久性:

  • 愚蠢的底层:每个表都有其Java类(POJO或DTO),其 字段直接映射到表的column 。假设我们有一个PERSON表,其中的一个ADDRESS_ID字段指向一个ADRESS表;然后,我们将有一个PersonDb仅包含addressId(整数)字段的类;我们没有 personDb.getAdress()办法,只有平原personDb.getAdressId()。因此,这些Java类非常笨拙(它们对持久性或相关类一无所知)。相应的PersonDao类知道如何加载/持久化此对象。使用iBatis + iBator(或MyBatis + MYBatisGenerator)之类的工具可以轻松创建和维护该层。

  • 包含 丰富域对象的 更高层:这些 对象 通常是上述POJO 的 图形 。这些类还具有通过调用相应的DAO来加载/保存图形(可能很懒惰,可能带有一些脏标志)的智能。但是,重要的是,这些丰富的域对象不是一对一地映射到POJO对象(或DB表),而是使用 域用例 。确定每个图的“大小”(它不会无限增长),并且像特定类一样从外部使用。因此,并不是说您有一个丰富的Person类(带有一些不确定的相关对象图)被用于多个用例或服务方法。相反,您有几个丰富的类PersonWithAddresesPersonWithAllData…每个人都包装了一个特定的,受限制的图,并具有自己的持久逻辑。这似乎效率低下或笨拙,在某些情况下可能是这样,但是经常发生这种情况,当您需要保存完整的对象图时,用例实际上受到限制。

  • 另外,对于表格报告之类的东西((特定的SELECTS返回一堆要显示的列)),您将不会使用上述内容,而会使用直截了当的POJO(甚至可能是Maps)



 类似资料:
  • 问题内容: 什么是最佳解决方案? 制作视频的人相信 在许多情况下,hibernate过大 基本的sql是一种很好的语言,它可以使hibernate抽象化 我听说过其他一些ORM实现,例如 https://github.com/rufiao/persist http://ormlite.com/ http://www.simpleorm.org/ 我想听听他们如何比较,以及每个人的优缺点。 问题答案

  • 问题内容: 我需要能够在内存中的HSQL数据库中每5秒以至少8000个对象的一致速率插入/更新对象。 我已经在Spring / Hibernate / JPA和纯JDBC之间进行了一些比较性能测试。我发现使用HSQL的性能存在显着差异。通过Spring / Hib / JPA,我可以在5秒钟内插入3000-4000个1.5 KB对象(具有一对多和多对多关系),而直接JDBC调用我可以插入10,00

  • 由于类:org.springframework.web.util.ExpressionEvaluationUtils自Spring3.x发行版以来就不推荐使用了,所以我正在java代码中寻找EL表达式求值的另一种替代方法。 你能提出更多的替代方案来代替我的实施吗?

  • [1]http://springfox.github.io/springfox/javadoc/2.7.0/springfox/documentation/swagger/web/classorapiannotationresourcegrouping.html [2]https://github.com/springfox/springfox/issues/1307

  • 最近,我从使用RESTEasy 2.3.6.final更新到了最新的版本,结果发现org.jboss.RESTEasy.spi.NotFoundException和org.jboss.RESTEasy.spi.unauthorizedException是不推荐的。这些有替代品吗?

  • 我在一本书中发现了一个“用餐哲学家问题”的替代解决方案,用Java编写: 解决方案的文本是: 或者,我们可以给筷子贴上从e到N-1的标签。每个哲学家都试图先拿起编号较低的筷子。这基本上意味着每个哲学家都会先选择左边的筷子,再选择右边的筷子(假设你是这样给它贴标签的),除了最后一位哲学家会选择相反的方式。有了这个解决方案,哲学家不可能拿着大筷子而不拿着小筷子。这就阻止了循环的能力,因为循环意味着较高