spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.19k stars 40.69k forks source link

Log a warning on startup when spring.jpa.open-in-view is enabled but user has not explicitly opted in #7107

Closed vpavic closed 7 years ago

vpavic commented 8 years ago

Considering OSIV/OEMIV is widely considered an anti-pattern, OpenEntityManagerInViewInterceptor should IMO not be enabled by default. Rather than that it should be opt-in.

If this proposal isn't accepted at the very least the default behavior should be stressed properly in the documentation. Currently the only reference is in configuration properties appendix.

wilkinsona commented 7 years ago

If you think that situation when the code works but nobody knows why is a good approach, then OSIV definitely should be enabled. However - understanding transactions is a must even for a junior developer.

When you're a beginner there are lots of things that you don't understand and lots of code that works and you don't know why. The question here is really about when we should require a beginner to understand something that's quite intricate. Gaining that understanding will undoubtedly slow them down at a time when what they would really like is to keep their momentum up by seeing something that works.

If we can guide a beginner through a smooth, quick, and easy to understand series of steps to get an app off the ground without OSIV, then we can consider it. Your suggestion above is an excellent first step, but I don't think just telling a user to set spring.jpa.open-in-view=true is the right thing to do. Almost all beginners will hit the problem and if we just tell them all to enable OSIV then I think we might as well have just done that for them in the first place.

Some options for things that we could suggest:

Excluding the nuclear option, I think loading eagerly is going to require the least effort to get an app that works.

jkubrynski commented 7 years ago

@vladmihalcea is there any feature in Hibernate that allows me to call entityManager.pleaseLoadAllProperies(entity)?

vladmihalcea commented 7 years ago

Only with join fetch

jkubrynski commented 7 years ago

But then you must know you want to fetch all when retrieving the entity. No way to do it on loaded entity?

vladmihalcea commented 7 years ago

You can use Hibernate#initialize along with some Reflection for multi-level entities.

jkubrynski commented 7 years ago

So maybe @wilkinsona we could provide a bean available in Spring Boot which will handle eager loading of a given entity?

@Transactional
@Service
public class ProductService {

  public Product findProduct(Long productId) {
    Product product = productRepository.findById(productId);
    someMagicBean.fetchProperties(product);
    return product;
  }
}

There are also two nice feature requests in Spring Data JPA ,which would be very useful in this case, and looks like quick wins. I'll also provide better performance eliminating N+1 problem:

https://jira.spring.io/browse/DATAJPA-198 https://jira.spring.io/browse/DATAJPA-208

s4gh commented 7 years ago

Frankly speaking I do not understand why some people want to force spring team to change default. Here are first two sentences from Spring Boot web page: Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".

You see the ideas of "easy" and "just run". This is absolutely fine to have the default optimized for developer productivity and ease of use. It is much more logical to require advanced users to change settings for non trivial use cases rather than make new users to make additional steps to "just run" and harder to do simple and trivial things.

And sorry but someMagicBean.fetchProperties(product); looks confusing and excessive. This is the line you will choose answering "Which One Doesn't Belong here" question.

There are no just good or bad things. Something is good for one purpose but exact same thing may be bad for other purpose.

And speaking about junior developers even if you say that they should understand the concept of transaction please don't force them to learn how to set up and configure framework so that their application just worked. And I may argue that there are many others things in spring that following same logic even junior developers have to understand. And if you change all the defaults to favor optimal or "academically right" vs "easy and simple" usage of spring boot will loose a lot of its appeal.

Please close this ticket and stop posting comments about patterns. It is not about definition of patterns and anti patterns. Use academic papers for this. Think about "Making Easy Things Easy & Hard Things Possible" principle. And again I think that it is much more logical to require advanced users to change settings for non trivial use cases rather than make new users to make additional steps to "just run" in simple and trivial situations.

vladmihalcea commented 7 years ago

@sveryovka That's what EclipseLink does. We could have done the same in Hibernate, but we didn't do that. Remember that Hibernate also provides the hibernate.enable_lazy_load_no_trans configuration property, but it's disabled by default. That's because we want our users to make the right choices from the very beginning.

Did this choice affect our user base? Not at all. Hibernate has a solid market share. So, it's not that bad to impose good practices, right?

s4gh commented 7 years ago

@vladmihalcea Frankly speaking this issue already has to many posts and I have not seen good proposal how everything (not just persistence tier) should work. What is the rerecorded best practice? Use DTOs? But I may argue that DTO which just duplicates entity is absolutely superfluous (anti-pattern) for simple apps. And DTOs where invented in times of j2ee 4 entity beans. And some main reasons for their invention no longer exist.

I am arguing that the right choice depends on what you are actually trying to do. If you are building large and complex app you have one right choice. If you are building quick proof of concept or trivial app OSIV is absolutely right choice for your task. Since in this case time to market and developer productivity is the most important factor for you.

Very famous example is facebook and their usage of php. There are many videos where they talk about it. And their message is simple - in many cases time to market is the most important thing and when you want to make everything right and take your time to do this you may just miss your opportunity and then it does not matter whether you've used good practices or not. The point I am trying to make is that in many situations usage of best practices in not most important thing. In many cases ease of use and developer productivity are much more important. So why not to force productivity? And facebook is definitely not the only example.

Regardless of what the default setting is there will be use cases where it will be wrong. So why not make default setting favor developer productivity over other factors? Few years ago common complain about spring and java was that it is much easier to develop same app using ror or node or python or whatever because spring required to much of ceremony and efforts to start and configure it to do even basic things. And unfortunately many people were not choosing java because of this (believe me I know what I am talking about). Spring boot has fixed this and it is still possible to use any approach you want. So what is the problem?

vladmihalcea commented 7 years ago

What is the rerecorded best practice? Use DTOs? But I may argue that DTO which just duplicates entity is absolutely superfluous (anti-pattern) for simple apps. And DTOs where invented in times of j2ee 4 entity beans. And some main reasons for their invention no longer exist.

Why do you think JPA offers DTO projections then? This is difference between fetching an entity and a DTO projection. Watch my High-Performance Hibernate presentation for more details.

If you are building large and complex app you have one right choice. If you are building quick proof of concept or trivial app OSIV is absolutely right choice for your task.

So, you want Spring Boot to be just a solution for rapid prototyping, and not for a serious enterprise application?

Few years ago common complain about spring and java was that it is much easier to develop same app using ror or node or python or whatever because spring required to much of ceremony and efforts to start and configure it to do even basic things.

Ruby on Rails is very convenient from a development perspective, yet, Twitter switched to Java because it scales better, especially on the back-end side, to quote this link).

s4gh commented 7 years ago

@vladmihalcea Vlad,

I thoght that I was very specific that even today with current default it is possible not to use OSIV with spring boot. Isn't it? So it is not one way or the other. It is just about default setting. Isn't it? I never wrote that it should be always OSIV. This issue is only about default value of switch: "on" or "off" and it is always possible to change the value.

For some reason from my paragraph

I am arguing that the right choice depends on what you are actually trying to do. If you are building large and complex app you have one right choice. If you are building quick proof of concept or trivial app OSIV is absolutely right choice for your task.

you chose not to copy the first sentance which is my main message:

I am arguing that the right choice depends on what you are actually trying to do.

The same statement I had in my initial comment

There are no just good or bad things. Something is good for one purpose but exact same thing may be bad for other purpose.

Are you accepting the statements that

the right choice depends on what you are actually trying to do.

?

jkubrynski commented 7 years ago

@sveryovka OSIV is like an entropy. It's very easy to enable it, and really hard to remove. People making use of OSIV without any understanding how it works will be screwed when they will realise what happened. Especially that OSIV brings some unclear backside operations, like the one described in my comment.

s4gh commented 7 years ago

@jkubrynski

Same question to you are you accepting statement that

the right choice depends on what you are actually trying to do.

?

jkubrynski commented 7 years ago

@sveryovka the problem is that when we choose to disable OSIV by default, people will make a decision if they want to use it very soon - after the first LazyInitializationException. Leaving OSIV enabled by default will cause people realising they use it after 2-3 years, when removing it will be a giant project.

s4gh commented 7 years ago

@jkubrynski

For some reason you avoid answering directly. Is this just because you don't want to agree with me on anything even if it is just some generic stetement? Or do you really don't think that

the right choice depends on what you are actually trying to do.

?

I don't want to speculate about who sees what and when. I don't want to speculate about adoption rate and so on.

I am trying to speak about basic logical stetements which can be used to dispute any value of any defelaut preference. And one of the most important from my standpoint is that

There are no just good or bad things. Something is good for one purpose but exact same thing may be bad for other purpose.

No speculations. Can you please answer "yes" or "no"?

jkubrynski commented 7 years ago

There is no "yes" or "no" answer in IT. Everything is based on the context. Spring Boot context is "enterprise application". And in this context OSIV should not be used.

s4gh commented 7 years ago

@jkubrynski I will take your

There is no "yes" or "no" answer in IT.

as you agreeing to my

There are no just good or bad things. Something is good for one purpose but exact same thing may be bad for other purpose.

Since this is basically the same. But again you decided not to admit that you agree with me at least on this basic statement even though I was not saying about "Spring Boot context".

The next logical question you have already started to talk about yourself is what you get when you just start with spring boot (start.spring.io) default project stub.

When you have on/off switch defined by some property and if the default value is a tradeoff between "enterprice readiness" and "ease of use and developer productivity" what is more impornat as default? In any case it is possible to change value manually. And again it is not one way or another it is just about what is turned on/off by default.

Your point of view is that "enterprice readiness" is more impornat to be turned on as default. My point of view is that "ease of use and developer productivity" is more impornat to be turned on by default. And again in any case it is possible to change property value in config file.

I do not know how decisions are made for spring boot. But somebody has to make this decision.

vladmihalcea commented 7 years ago

@sveryovka

the right choice depends on what you are actually trying to do.

Exactly! That's why OSIV should be disabled by default and enabled explicitly. By default, I assume that Spring Boot is meant for serious enterprise applications lead by responsible developers. If you want a throw-away prototype, you can enable OSIV explicitly and knock yourself out.

Makes sense?

andersonkyle commented 7 years ago

To get a better sense of what the developer experience would look like in practice with OSIV disabled, @jkubrynski @vladmihalcea would you be able to share an example repo that demonstrates the best practices you're advocating?

Perhaps the relationship between Movie, Theater, and Showtime where a movie can play at many theaters at many showtimes. Feel free to substitute your own domain but something that demonstrates these types of relationships.

Hopefully this will paint a clearer picture of what the startup experience will look like and could better inform the decision making process.

vladmihalcea commented 7 years ago

@andersonkyle. Sure, check out these 454 pages that show you how to design such a Persistence Layer so that it's both effective and efficient.

martin-g commented 7 years ago

@vladmihalcea I think your answer summarizes it very well why people prefer to just use open-session-in-view! 1-3 pages long blog post with a small demo app might help! But if anyone has to read 454 pages to avoid this setting then I'm pretty sure 98% of the people will skip the book!

vladmihalcea commented 7 years ago

@martin-g Well, my readers' testimonials have a different opinion on this matter.

wilkinsona commented 7 years ago

For better or worse, if a beginner is presented with a choice of reading 454 pages or setting a single property, I agree with @martin-g that the vast majority of them will set the property. That is in no way a criticism of your book, @vladmihalcea. It is, however, indicative of a rather steep learning curve with JPA and Hibernate.

In the absence of a concise, beginner-friendly explanation of what to do instead of using OSIV, I think we have no choice but to leave it enabled by default. Without it, I think the getting started experience is poor and the learning curve too steep.

vladmihalcea commented 7 years ago

@wilkinsona JPA and Hibernate, just like any data access framework, have a steep learning curve because, after all, you still need to know how RDBMS, JDBC work behind the scenes, how indexing works, how to read an Execution Plan, etc. However, I can see why you chose this property to be enabled be default. I understand that usability is a very important feature of Spring Boot.

My comment about reading my book was targeting this comment:

something that demonstrates these types of relationships.

It was not about OSIV. You don't need to read 454 pages to know how to use LAZY fetching properly. This article is enough and takes less than 5 minutes even for a junior developer.

martin-g commented 7 years ago

Well, my readers' testimonials have a different opinion on this matter.

@vladmihalcea I was not talking about the book as a whole, but about the topic in this issue - OSIV. Until someone shows a relatively small and easy to grasp example of a Spring Boot application without OSIV many new projects will be created with OSIV enabled!

vladmihalcea commented 7 years ago

Until someone shows a relatively small and easy to grasp example of a Spring Boot application without OSIV many new projects will be created with OSIV enabled!

You don't need a specific Spring Boot example. Spring Boot is just Srping after all, and OSIV hasn't been the default approach on any Spring-based project I worked on over the past 10 years. This article shows how to handle LAZY associations the right way, no matter if you're using Spring or Java EE.

martin-g commented 7 years ago

Spring Boot is just Srping after all

Yes, in plain Spring you have add the additional Servlet Filter yourself. Not as simple as in Boot but again very easy!

My experience is exactly the opposite - I haven't seen a Spring application with Hibernate that doesn't use OSIV :-/ I don't say that using OSIV is better! I just say that it is widely spread (according to my experience!). In any application that strives for performance I'd just use JdbcTemplate. Maybe org.springframework.orm.hibernate5.HibernateTemplate should be promoted ?! (I haven't used it so far).

jkubrynski commented 7 years ago

@wilkinsona Is Spring Boot targeted for beginners or to create production-ready applications? If it's a project for sandboxing and 5-minute live-coding on presentations then leaving OSIV enabled is a great idea. But deploying OSIV to production is a terrible idea.

beikov commented 7 years ago

For the read concerns you can use a projection tool like e.g. Blaze-Persistence Entity Views or if you only need simple projections Spring Data Projections should be enough too. I am currently working on also handling the write concern with Entity Views, but this is still in development. If you provide me a sample app using OSIV I can adapt it and show you how to implement a DTO approach.

wilkinsona commented 7 years ago

Is Spring Boot targeted for beginners or to create production-ready applications? @jkubrynski I'd guess that's a rhetorical question, but I think it's worth addressing anyway.

Spring Boot is obviously targeted at both, which is why this isn't an easy decision to make. There's no point in making something great for production if people give up and choose a different stack because the getting started experience is poor.

The ideal here would be for the getting started experience to have a gentle learning curve and for the curve to continue to be gentle as you move towards production. Right now, the curve either has to be really steep at the beginning (OSIV disabled by default), or potentially really steep later on (OSIV enabled by default and it causes performance problems). Potentially really steep later on is the lesser of those two evils, IMO.

Perhaps we can strike more of a balance while still leaving OSIV enabled by default? I wonder if it would be possible to detect when it's prevented a LazyInitializationException and log a warning. That way people would get an easy getting started experience, but would also be warned about potential problems.

vpavic commented 7 years ago

The ideal here would be for the getting started experience to have a gentle learning curve and for the curve to continue to be gentle as you move towards production. Right now, the curve either has to be really steep at the beginning (OSIV disabled by default), or potentially really steep later on (OSIV enabled by default and it causes performance problems). Potentially really steep later on is the lesser of those two evils, IMO.

@wilkinsona I understand and agree that Boot should target both groups, and that striking a balance is often times difficult, however I strongly disagree with the part in bold.

If you consider the topic of project's life cycle I think it should be obvious that the damage is much bigger if anyone runs into problems due to use of OSIV at later stages of the project. Especially considering the projects of enterprise-ish size, the effort to move off OSIV can be quite costly and potentially catastrophic to the project (delay of delivery dates, production issues, etc.). I don't know about others who participated in this discussion, but on every project I've worked on in my career the maintenance phase remained among my responsibilities as well so I care a lot about these things.

Regarding the concise and beginner-friendly example of OSIV-less approach, I think the 2 or 3 @vladmihalcea's blog posts that have been linked here do explain things in concise and beginner-friendly way. Do you perhaps insist on code based example that would be a part of Boot's codebase as a sample project?

Just to make it clear, I'm not trying to force anyone not to use OSIV or promote the data access approach that I use. It's just that I believe that having it enabled is a really bad default that has severe architectural implications, and as such it should be left for users to be explicit about whether they want it or not. I cannot recall any other of Boot's opinions that has such architectural impact. In fact, there are a number of other places where Boot has moved or is moving from having something on by default to requiring users to enable it using configuration property (e.g. spring.session.store-type, database initializers) and I don't believe that made Boot any less beginner friendly.

aahlenst commented 7 years ago

In my opinion having OSIV enabled without being aware of it is a problem. Why not leaving it on by default in 2.0, printing a big warning to the console that prompts the developer to explicitly opt-in? Everything accompanied by some concise docs that explain the implications of OSIV=true/false. The resulting behavior would be:

JPA is not enabled: No warning JPA is enabled, no OSIV setting declared (OSIV is on): Warning is emitted JPA is enabled, OSIV=true: No warning JPA is enabled, OSIV=false: No warning

wilkinsona commented 7 years ago

@aahlenst Thanks for the suggestion. Let's see if we can implement what you've proposed in M6.

beegor commented 7 years ago

IMHO, enabling OSIV by default does disservice to beginners. It hides the way Hibernate/JPA really works with collection mappings. one-to-many and many-to-many relations which are lazy by default will behave like eagerly fetched. Beginners who are familiar with fetching modes would be confused by absence of LazyInitializationException and maybe dig more , but many of them will be happy that things just work magically and likely pretty confused on some future project that does't have OSIV configured. I always felt about OSIV as of violation of "separation of concerns" principle, but it's not even the point here. The point is OSIV should be explicitly enabled only by someone who knows what it is and what it does. Let the beginners learn Hibernate/JPA pitfalls early, don't hide it.

vladmihalcea commented 7 years ago

It's worth adding this StackOverflow question where someone asks for explicitly disabling OSIV because the magically handling the LazyInitializationException can hide bugs.

odrotbohm commented 7 years ago

Let me use this opportunity to point out that we've now reached a point where a user has declared a class with a field and an accessor method returning that field. That user is now actually surprised that this code does what it's declared to do and does not throw an arbitrary technical exception.

And this is considered the "wrong" behavior and we use that as an argument to actually change that.

vladmihalcea commented 7 years ago

a user has declared a class with a field and an accessor method returning that field

@olivergierke Are you talking about the same StackOverflow question?

There is no mapping being shown there.

odrotbohm commented 7 years ago

There is no mapping being shown there.

Let's see if we find a Hibernate / JPA expert that can educate us on what code looks like that usually throws LIEs (funny abbreviation, eh?). Anyone?

vladmihalcea commented 7 years ago

I'm not sure if I qualify as a Hibernate / JPA expert, but I wrote my 2 cents on this article on my blog, the best way to handle the LazyInitializationException LazyInitializationException.

Let me use this opportunity to point out that we've now reached a point where a user has declared a class with a field and an accessor method returning that field. That user is now actually surprised that this code does what it's declared to do and does not throw an arbitrary technical exception.

I have a way better analogy:

  1. The user has a banking account with a balance of 50$.
  2. The user wants to withdraw 60$, and instead of getting an InsufficientFundsException, they will get the 60$ without knowing that there's an overdraft fee for the extra 10$.
  3. The longer it takes for the user to realize they have a debt to pay, the costlier it will become.

The whole point of this thread was to let the user know about this issue, as long as OSIV is still enabled by default.

Hiding a LIE (funny abbreviation, eh?) is not the same as telling the truth,

Anyway, I don't think this the discussion is going anywhere, so there is no point in continuing it. I'll focus on making people aware of this issue so that they can take the best decision whether they want to have OSIV enabled or not.

odrotbohm commented 7 years ago

That’s neither a better analogy nor an analogy at all to what the original reporter in that StackOverflow post asked. But it’s in line with a lot of the “making up things from thin air” presented in this thread. An LIE is not a business exception, it’s not triggered by any implementation of a business rule. It’s a technical distraction from your actual business problem.

My point was not about how to handle LIEs, but that code you can perfectly reason about is considered “broken” if it works the way it’d work in plain Java, without JPA in place. OEMIV is one means to solve that with well-known pros and cons. Heck, OEMIV is not even about handling exceptions, it’s about preventing them. It’s not about correctness, it’s about efficiency, convenience and optimizations. That’s a world of a difference. The thread here wants to imply something is horribly broke, where it’s actually about a trade-off between convenience and efficiency. We need proper data points to evaluate that balance but more on that below. The issue that triggered my comment was, that – I guess without a lot of people not realizing - the SO post was more proof of the underlying problem than that it was how to apply one of the solution options.

Anyway, I don't think this the discussion is going anywhere, so there is no point in continuing it.

We’ve reached said point a while ago when the proponents of the suggested change boasted that an alternative implementation to what the current default allows would be oh so very simple, but then constantly fail to provide any meaningful example of what this would look like, even after repeated requests to provide some code. However, that chance is still given. Unfortunately, so far, we’ve seen nothing but blowing smoke instead. I can point to a gazillion of SO threads in which users were caught by surprise about LIEs and where OEMIV was a decent solution for. But yeah, that’s not moving this discussion forward a bit. I guess my ironic remark was just my way of pointing out the pointlessness of that.

Shortcutting this: I guess, we should move forward by finally seeing examples what an alternative user application implementation would look like, or resolve the discussion.

vladmihalcea commented 7 years ago

finally seeing examples what an alternative user application implementation would look like.

It's simple.

Instead of:

@Transactional
public List<PostComment> getPostComments(String review) {
    return entityManager.createQuery(
        "select pc " +
        "from PostComment pc " +
        "where pc.review = :review", PostComment.class)
    .setParameter("review", review)
    .getResultList();
}

They would write:

@Transactional
public List<PostComment> getPostComments(String review) {
    return entityManager.createQuery(
        "select pc " +
        "from PostComment pc " +
        "join fetch pc.post " +
        "where pc.review = :review", PostComment.class)
    .setParameter("review", review)
    .getResultList();
}

It's just one extra JOIN FETCH for each @ManyToOne or @OneToOne associations being needed further up the call stack.

Or they can use Entity Graph, if don't write the JPQL or Criteria API query themselves and rely on Spring Data for that.

For collections, they can JOIN FETCH up to one collection, otherwise a Cartesian Product is generated.

So, any extra @OneToMany or @ManyToMany would require to be navigated before returning from the @Transactional block.

However, initializing more than one collection can easily lead to an N+1 query issue, and that's the case even if OSIV is disabled or not.

odrotbohm commented 7 years ago

And what in the world is preventing anyone from writing the query the way you suggested with the current default? I think it’s a decent way of selectively optimizing queries while still retaining the convenience of everything not explicitly optimized still working as the written code suggests (getPost() returning the Post no matter whether it’s currently loaded or not).

vladmihalcea commented 7 years ago

And what in the world is preventing anyone from writing the query the way you suggested with the current default?

Why would they if it works magically like this:

List<PostComment> findByReview(String review);

With a single Spring Data method I can:

Why would a developer want to write separate methods and think about fetching data efficiently when their priority is addressing issues from the current Sprint log?

wilkinsona commented 7 years ago

I have locked this issue, for now at least, as the discussion no longer seems to be productive. We’ll add the logging suggested above by @aahlenst.

wilkinsona commented 7 years ago

Closed by https://github.com/spring-projects/spring-boot/commit/5aa66305a80c84f0c4aab7a3058f49451ab43810.

xak2000 commented 6 years ago

Why would a developer want to write separate methods and think about fetching data efficiently when their priority is addressing issues from the current Sprint log?

Yes, and they shouldn't! There is profiling, logging and monitoring for this.

If it is a not a high load service, then N+1 problem can never be noticed. Yes, it can work suboptimal, but who cares if it runs 10 queries/hour (1 main query and another 9 because of N+1 "problem" :smile:)?

If it is a high load service, than it should have a profiling, monitoring, logging etc, so this performance degradation will be noticed, then SQL log will be enabled and N+1 problem will be noticed. And only then some decision will be made:

And all of them are possible without disabling OSIV. I prefer optimizing the bottlenecks, not all possible paths. Or else why should I use ORM in first place if I would always manually craft explicit queries for each and every use-case? Even these cases, when optimization is not required at all and lazy fetching is acceptable.

Maybe it will be more convinient to use something like JOOQ than JPA then?


Another concern is what to return from these "specialized" methods? Like in getPostComments example above. If this is the only method returning List<PostComment> then we can just make post field EAGER. If not, then there is another method without join fetch pc.post, like getPostCommentsWithoutPost, right?

Should we really return List<PostComment> then? If we get the list using getPostComments, then we can call list.get(0).getPost() method. If we get the list using getPostCommentsWithoutPost, then (without OSIV) we can't do this (LIE) despite the fact that both methods return the same models. So as a developer I should always be aware that PostComment can containt the post or not contain the post. :man_facepalming: And I can never be sure if I can call getPost() method on it. It could be not clear where this list comes from in the code, so sometimes it could be very hard to understand what kind of PostComments (with or without post) in the concrete list. Partially filled models are more evil then OSIV IMHO.

So to prevent this we forced to always use DTOs then. Different DTOs of same model for different use-cases (feel the pain :imp: ).

And if we decide to do this, then OSIV just does nothing. Nothing good, but also nothing bad. Lazy loading will not happen anyway. Open session will still be open, but DTOs doing nothing with it.

So, my opinion is that, there is no one and only one "right" way to do the things. All have its drawbacks.

And if we want totally ignore the ORM's ability to lazily load relations, then maybe we should introduce a hibernate.use-the-joins-luke flag. :) and throw LIE on any not loaded field access attempt even when em is still open. :)