JPA/Hibernate 选择性刷新

发布于 2024-12-05 14:12:48 字数 845 浏览 1 评论 0原文

我想我将从

问题

开始:是否有一种方法可以确保只有以某种方式明确“标记”的实体才会刷新到数据库?

环境

我们正在使用 Java EE 5、Seam 2、JBoss AS 6 和 Hibernate(尽管我们尝试尽量减少对 Hibernate 的直接依赖)。

目标

目前,我们拥有映射到瞬态 DTO 对象的实体,然后在业务层中使用这些实体并绑定到 Facelet 进行表示。当我们需要保存数据时,我们将 DTO 映射回实体并保留它们。我想用包装实体的包装业务对象替换 DTO,以便:

  • 不需要映射,因为业务对象将调用包装实体上的 getter 和 setter,而不是存储它自己的数据副本。
  • 创建业务对象提示时可以指定,但如果未获取某些内容,则稍后可以根据 JPA 延迟自动获取。这是我最讨厌的事。我讨厌每次需要时都必须手动获取额外的东西。它通常会导致过于复杂的“业务”代码,尤其是当存在大量数据并且预先获取所有数据的速度太慢时。当我调用 getRelatedStuff() 时,它应该就在那里。
  • 保存就像“标记”相关业务对象并调用刷新一样简单(我正在考虑使用 带有手动刷新功能的 Seam 对话范围事务)。

问题

这种模式的问题在于,JPA 愿意并且渴望在刷新期间将所有内容刷新到数据库。我宁愿明确告诉 JPA 我想要刷新哪些实体。我没有指定的任何内容都不应该被刷新。

作为次要问题,这种模式是个好主意吗?

I guess I'll start with

The Question

Is there a way to ensure that only entities that have been explicitly 'marked' in some way are flushed to the database?

The Environment

We are using Java EE 5, Seam 2, JBoss AS 6 and Hibernate (although we try to keep direct Hibernate dependencies minimal).

The Goal

Currently we have entities that are mapped to transient DTO objects which are then used in the business layer and bound to facelets for presentation. When we need to save data we map the DTOs back to entities and persist them. I'd like to replace the DTO with a wrapper business object that wraps an entity so that:

  • No mapping is required as the business object will call getters and setters on the wrapped entity instead of storing it's own copy of the data.
  • Upon creation of the business object hints can be specified but if something is not fetched then it can be automatically fetched later on lazily as per JPA. This is my pet peeve. I hate having to manually fetch something extra every time I need it. It often results in over-complicated 'business' code, especially when there is lots of data and it is too slow to fetch it all up-front. When I call getRelatedStuff() it should just be there.
  • Saving is as simple as 'marking' the relevant business object(s) and calling flush (I was thinking of using Seam conversation scoped transactions with manual flushing).

The Problem

The problem with this pattern is that JPA is willing and eager to flush everything to the database during a flush. I would rather tell JPA explicitly which entities I want flushed. Any I didn't specify should not be flushed.

As a secondary question, is this pattern even a good idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傲影 2024-12-12 14:12:48

这不是一个好主意。在 ORM 中,不刷新数据库更改的方法是不对对象进行更改。如果您需要对框架进行如此细粒度的控制,就像您想要的那样,那么您就错误地使用了它。使用 Hibernate,您的业务逻辑应该几乎不会注意到某个地方有一个数据库。您将 Hibernate 视为 RDBMS 之上的一层。相反,你可以将其想象为一个容量近乎无限的 Map,您可以在其中通过 id 存储和获取对象。与 Map 一样,当您从中获取对象并对该对象进行更改时,这些更改也会反映在 Map 中,并且 Map 上的其他获取将看到更新后的对象状态。当然,对于 Hibernate,更改必须在事务中发生,但请考虑这是内存事务,这是必需的,因为 Map 是由多个线程并发访问的。

Not a good idea. In an ORM, the way to not flush changes to the database is to not make the changes to the objects. If you need such fine-grained control of the framework as you're trying to get, then you're using it wrong. With Hibernate, your business logic should be all but oblivious of there being a database back there somewhere. You're thinking of Hibernate as a layer over an RDBMS. Instead, think of it more like a Map with near-unlimited capacity, where you can store and get objects by id. As with a Map, when you get an object out of it and make changes to the object, those changes are also reflected in the Map, and other gets on the Map will see the updated object state. Of course with Hibernate, changes have to occur in a transaction, but consider that to be a memory transaction, required because the Map is accessed concurrently by multiple threads.

那些过往 2024-12-12 14:12:48

当然可以。

只需致电

em.clear();

em.merge();

这将导致任何对象分离。
然后,您只需将要合并/保留的每个对象作为方法的参数传递即可。这将仅将您想要的对象刷新到数据库。

请注意,在调用 em.clear() 后,唯一持久化的对象将是合并/持久化的对象。

Sure you can.

Just call

em.clear();

before

em.merge();

This will cause any object to be detached.
Then you simply pass every object you want to merge/persist as parameters of your method. This will flush to the database only the object you want.

Be careful that, after having called em.clear(), the only persisted object will be the one merged/persisted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文