在视图模式中打开会话[英] Open Session In View Pattern

本文是小编为大家收集整理的关于在视图模式中打开会话的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

鉴于我选择的JPA开发框架(Hibernate的实现),Spring和.

,我正在问这个问题.

我一直在考虑我的实体层中的关系 - 例如,我有一个有很多订单行的订单实体.我已经设置了我的应用程序,以便为每个订单急切地加载订单行.您是否认为这是解决懒惰初始化问题的懒惰方式,如果我将提取策略设置为False?

我看到的方式,在检索实体及其关联时,我有以下替代方案:

  1. 在查看模式中使用"打开会话"在每个请求上创建会话,并在返回响应之前提交交易.

  2. 实现一个DTO(数据传输对象)层,以便我执行每个DAO查询都为我的目的返回正确初始化的DTO.我真的不太喜欢这个选项,因为根据我的经验,我发现它创建了很多样板复制代码并变得凌乱.

  3. 不要绘制JPA中的任何关联首先拥有ORM的目的.

  4. 热切获取所有(或大多数关联) - 在上面的示例中,当我检索订单时,请始终获取所有订单行.

所以我的问题是,您将在什么情况下和在什么情况下使用以下哪些选项?您总是坚持一种方法吗?

我会问一位同事,但我认为,如果我什至提到"公开会议"一词,我会被空白的凝视打招呼:(我真正在这里寻找的是高级或经验丰富的一些建议开发人员.

谢谢大家!

推荐答案

我已经成功地解决了所有懒惰的初始化问题,即" view -pattern"(即春季实现).我使用的技术与您完全一样.

使用这种模式使我能够完全绘制实体关系,而不必担心在DAO中获取儿童实体.大多.在90%的情况下,模式在视图中解决了懒惰初始化的需求.在某些情况下,您必须"手动"初始化关系.这些情况很少见,在我的情况下总是非常非常复杂.

在视图模式中使用开放实体管理器时,正确定义实体关系,尤其是正确的传播和交易设置很重要.如果这些配置未正确配置,则当某些实体在视图中懒惰初始初始化并且由于已经关闭而失败时,将出现与封闭会话有关的错误.

.

我一定会选择选项1.有时可能需要选项2,但是我认为绝对没有理由使用选项3.选项4也是否.急切地获取所有内容都会杀死只需要列出某些父实体的几个属性的任何视图的性能(在案例中的订单).

n+1选择

在开发过程中,由于在视图中初始化了一些关系,因此将有n+1选择.但这不是丢弃模式的原因.只需解决这些问题,然后将代码交付到生产之前.使用其他模式与其他模式一样,可以很容易地解决这些问题:添加正确的DAO或服务方法,修复控制器以调用其他查找器方法,也许在数据库中添加视图等.

其他推荐答案

开放会话中有一些问题.

例如,如果交易失败,您可能会在提交时间太晚,一旦您几乎完成了页面(可能已经提交了响应,所以您就无法更改页面!

另一个示例,按需阅读数据可能会变成许多" n+1选择"问题,可以杀死您的性能.


许多项目使用以下路径:

  1. 在业务层保持交易;那时加载您应该需要的一切.
  2. 演示层承担着懒惰感的风险:每个都被视为一个编程错误,在测试中被捕获,并通过在业务层中加载更多数据来纠正(您有机会有效地进行操作,避免" n+1选择"问题).

要避免为DTO创建额外的类,您可以将数据加载到实体对象内部内.这是POJO方法的全部要点(现代数据访问层的使用,甚至是春季等集成技术).

其他推荐答案

我已经成功地使用了项目上的开放式观察模式.但是,我最近在"春季"中阅读了一个有趣的潜在问题,如果您在较低的层管理交易,同时保持冬眠层的打开.

.

.

我们在服务层管理了大多数交易,但在视图层中保持了休眠会话的打开.这意味着在视图中懒读是导致单独的读取交易.

我们在服务层管理交易,以最大程度地减少交易持续时间.例如,我们的某些服务调用导致数据库事务和Web服务调用到外部服务.我们不希望我们的交易在等待网络服务呼叫响应时开放.

由于我们的系统从未进行过生产,我不确定是否有任何真正的问题,但我怀疑有可能试图懒惰地加载其他人删除的对象.

本文地址:https://www.itbaoku.cn/post/627518.html

问题描述

I'm asking this question given my chosen development frameworks of JPA (Hibernate implementation of), Spring, and <insert MVC framework here - Struts 1, Struts 2, Spring MVC, Stripes...>.

I've been thinking a bit about relationships in my entity layer - for example I have an order entity that has many order lines. I've set up my app so that it eagerly loads the order lines for every order. Do you think this is a lazy way to get around the lazy initialization problems that I would come across if I was to set the fetch strategy to false?

The way I see it, I have the following alternatives when retrieving entities and their associations:

  1. Use the Open Session In View pattern to create the session on each request and commit the transaction before returning the response.

  2. Implement a DTO (Data Transfer Object) layer such that every DAO query I execute returns the correctly initialized DTO for my purposes. I don't really like this option much because in my experience I've found that it creates a lot of boilerplate copying code and becomes messy to maintain.

  3. Don't map any associations in JPA so that every query I execute returns only the entities I'm interested in - this will probably require me to have DTOs anyway and will be a pain to maintain and I think defeats the purpose of having an ORM in the first place.

  4. Eagerly fetch all (or most associations) - in the example above, always fetch all order lines when I retrieve an order.

So my question is, when and under what circumstances would you use which of these options? Do you always stick with one way of doing it?

I would ask a colleague but I think that if I even mentioned the term 'Open Session in View' I would be greeted with blank stares :( What I'm really looking for here is some advice from a senior or very experienced developer.

Thanks guys!

推荐答案

I've successfully solved all my lazy initialization problems with Open Session In View -pattern (ie. the Spring implementation). The technologies I used were the exact same as you have.

Using this pattern allows me to fully map the entity relationships and not worry about fetching child entities in the dao. Mostly. In 90% of the cases the pattern solves the lazy initialization needs in the view. In some cases you'll have to "manually" initialize relationships. These cases were rare and always involved very very complex mappings in my case.

When using Open Entity Manager In View pattern it's important to define the entity relationships and especially propagation and transactional settings correctly. If these are not configured properly, there will be errors related to closed sessions when some entity is lazily initialized in the view and it fails due to the session having been closed already.

I definately would go with option 1. Option 2 might be needed sometimes, but I see absolutely no reason to use option 3. Option 4 is also a no no. Eagerly fetching everything kills the performance of any view that needs to list just a few properties of some parent entities (orders in tis case).

N+1 Selects

During development there will be N+1 selects as a result of initializing some relationships in the view. But this is not a reason to discard the pattern. Just fix these problems as they arise and before delivering the code to production. It's as easy to fix these problems with OEMIV pattern as it's with any other pattern: add the proper dao or service methods, fix the controller to call a different finder method, maybe add a view to the database etc.

其他推荐答案

Open Session in View has some problems.

For example, if the transaction fails, you might know it too late at commit time, once you are nearly done rendering your page (possibly the response already commited, so you can't change the page !) ... If you had know that error before, you would have followed a different flow and ended up rendering a different page...

Other example, reading data on-demand might turn to many "N+1 select" problems, that kill your performance.


Many projects use the following path:

  1. Maintain transactions at the business layer ; load at that point everything you are supposed to need.
  2. Presentation layer runs the risk of LazyExceptions : each is considered a programming error, caught during tests, and corrected by loading more data in the business layer (you have the opportunity to do it efficiently, avoiding "N+1 select" problems).

To avoid creating extra classes for DTOs, you can load the data inside the entity objects themselves. This is the whole point of the POJO approach (uses by modern data-access layers, and even integration technologies like Spring).

其他推荐答案

I have successfully used the Open-Session-in-View pattern on a project. However, I recently read in "Spring In Practice" of an interesting potential problem with non-repeatable reads if you manage your transactions at a lower layer while keeping the Hibernate session open in the view layer.

We managed most of our transactions in the service layer, but kept the hibernate session open in the view layer. This meant that lazy reads in the view were resulting in separate read transactions.

We managed our transactions in our service layer to minimize transaction duration. For instance, some of our service calls resulted in both a database transaction and a web service call to an external service. We did not want our transaction to be open while waiting for a web service call to respond.

As our system never went into production, I am not sure if there were any real problems with it, but I suspect that there was the potential for the view to attempt to lazily load an object that has been deleted by someone else.