对于Java开发人员来说,什么比Hibernate更好?

时间:2023-01-15 12:50:19

I am unsure if there is a better way to develop database-backed applications in Java, but I thought I would ask.

我不确定是否有更好的方法来开发Java中的数据库支持的应用程序,但我想我会问。

There is a lot I like about Hibernate, but there are lots of problems too. Most of them are not that big of deal when you have as much experience with it as I have, but I think the biggest problem that I run into is one-size fits all lazy-loading model. Absolutely hate it - there has to be something better out there... no?

我喜欢Hibernate,但也有很多问题。当你拥有和我一样多的经验时,他们中的大多数并不是那么重要,但我认为我遇到的最大问题是一个适合所有延迟加载模型。绝对讨厌它 - 那里必须有更好的东西......不是吗?

The reason I hate the lazy-loading model is that while it's convenient to specify what is lazy and not lazy in the configuration file, there are many parts of an application that would prefer lazy-loading in one area and no lazy loading in another. If you want to satisfy both parts of the program, you need put up with lazy-loading and manually load entities and their children... and their children... and so on. This is just bloat that doesn't do anything to solve the real programming problems - like the features that get the project done.

我讨厌延迟加载模型的原因是虽然在配置文件中指定什么是惰性而不是惰性是方便的,但是应用程序的许多部分更喜欢在一个区域中进行延迟加载而在另一个区域中没有延迟加载。如果你想要满足程序的两个部分,你需要忍受延迟加载并手动加载实体及其子代......以及他们的孩子......等等。这只是膨胀,无法解决真正的编程问题 - 比如完成项目的功能。

It seems that the loading strategy that you want to use should be independent of the mapping information, but this is not possible (as far as I know) with hibernate other than writing the loading inside of your java code.

看来你想要使用的加载策略应该独立于映射信息,但是除了在java代码中编写加载之外,这对hibernate来说是不可能的(据我所知)。

Another problem I have with the lazy-loading is that it's not easily predictable when you are going to have problems. I often don't discover lazyloadexceptions until I deploy my application into Tomcat.

我对延迟加载的另一个问题是,当你遇到问题时,它不容易预测。在将应用程序部署到Tomcat之前,我经常不会发现lazyloadexceptions。

It feels even more bloated when these exceptions occur from frameworks - like by Jackson calling into a collection that hasn't loaded yet. Or maybe Spring is accessing a property I never asked it to, so it throws a LazyInitializationException anyway - for no reason other than that their framework touches all of my bean properties.

当这些异常发生在框架中时,感觉更加臃肿 - 就像杰克逊调用尚未加载的集合一样。或者Spring可能正在访问我从未问过的属性,所以无论如何都会抛出一个LazyInitializationException - 除了他们的框架触及我的所有bean属性之外没有任何理由。

Anyway, because I can't discover these problems during integration tests... when I discover them in Tomcat, I often have to shut down tomcat, make the changes, recompile, reload tomcat, relogin to my application, go back to the page I was at to see if it's fixed - this is truly a massive pain. It takes so long to fix one of these errors. I feel like it's just getting in the way of what I am actually doing.

无论如何,因为我在集成测试期间无法发现这些问题...当我在Tomcat中发现它们时,我经常要关闭tomcat,进行更改,重新编译,重新加载tomcat,重新登录到我的应用程序,返回页面我在看它是否已修复 - 这确实是一次巨大的痛苦。修复其中一个错误需要很长时间。我觉得这只是妨碍我实际做的事情。

In the end, I just feel that details like this really weigh me down. When I look at my day and ask, "What did I produce today?" - I find problems like this really get in the way of me feeling like I accomplished something.

最后,我觉得这样的细节真的让我失望。当我看着我的日子并问:“我今天生产了什么?” - 我发现这样的问题确实让我觉得我觉得自己有所成就。

Of course, I can just turn off lazyloading... but then I get absolutely dreadful performance.

当然,我可以关闭延迟加载......但是后来我的表现非常糟糕。

Is there a better way? Something that "just does the right thing", performs well and easier to reason about?

有没有更好的办法? “只是做正确的事情”,表现良好,更容易推理?

Thanks

7 个解决方案

#1


0  

One person already mentioned Open Session in View, which will eliminate most if not all of your lazy loading problems (but it brings its own problems).

一个人已经在视图中提到了Open Session,这将消除大部分(如果不是全部)延迟加载问题(但它带来了自己的问题)。

Open JPA has something called 'fetch groups'. This is basically a named set of fetch settings that you can set before running queries, etc. You would then select the appropriate fetch strategy before running the query (presumably in your service impl). This way, the fetch plan is separate from the mapping. You can configure as many fetch plans as you have use cases. In one fetch plan, a particular association is lazy, but in another, it is eager / JOIN. Seems awesome.

Open JPA有一个名为'fetch groups'的东西。这基本上是一组命名的提取设置,您可以在运行查询之前设置它们等。然后在运行查询之前选择适当的提取策略(可能在您的服务impl中)。这样,获取计划与映射是分开的。您可以根据用例配置任意数量的提取计划。在一个获取计划中,一个特定的关联是懒惰的,但在另一个,它是渴望/ JOIN。看起来很棒。

If you've been coding to the JPA spec instead of native Hibernate, the switch to Open JPA could be easy.

如果您已经编写了JPA规范而不是本机Hibernate,那么切换到Open JPA可能很容易。

If I'm not mistaken, some work is being done to implement fetch groups in Hibernate, but I'm too lazy to google that right now.

如果我没弄错的话,正在做一些工作来实现Hibernate中的获取组,但我现在懒得谷歌。

#2


3  

First of, this has nothing to do with Hibernate. Pretty much any ORM (certainly any JPA provider) implements lazy loading in a similar fashion.

首先,这与Hibernate无关。几乎任何ORM(当然任何JPA提供程序)都以类似的方式实现延迟加载。

As far as "would prefer lazy-loading in one area and no lazy loading in another" goes, you can override lazy fetching via HQL fetch join if you're using queries. For straight up session.get() there's usually no need to do so (Note - see below), you can just let lazy loading do its magic for you. For that to happen you need to ensure your session stays alive until all requests to entity (its properties / collections / etc...) are done, which is typically achieved via Open Session in View pattern. Spring has a corresponding interceptor as well.

至于“更喜欢在一个区域中进行延迟加载而在另一个区域中没有延迟加载”,如果您正在使用查询,则可以通过HQL提取连接覆盖延迟提取。对于直接的session.get(),通常没有必要这样做(注意 - 见下文),你可以让延迟加载为你做出魔力。为此,您需要确保您的会话保持活动状态,直到完成对实体的所有请求(其属性/集合/等...),这通常通过View模式中的Open Session实现。 Spring也有相应的拦截器。

Note: One case where you have to load all entity's dependencies is when you're going to ship it to a remote system (thus making original session unavailable). This is typically handled by marshaller, though.

注意:您必须加载所有实体的依赖关系的一种情况是您要将其发送到远程系统(从而使原始会话不可用)。但这通常由marshaller处理。

#3


3  

I agree with others that the notion of better is subjective and context-dependent. True alternatives to JPA / Hibernate are:

我同意其他人认为更好的概念是主观的和依赖于背景的。 JPA / Hibernate的真正替代品是:

MyBatis

It is the most popular SQL templating engine in Java. It externalises SQL statements into XML files, from where they can be loaded by ID or by other means. As a templating engine, MyBatis also supports SQL composition and a slim templating language for loops and branch statements.

它是Java中最流行的SQL模板引擎。它将SQL语句外部化为XML文件,可以通过ID或其他方式从中加载它们。作为模板引擎,MyBatis还支持SQL组合和用于循环和分支语句的简洁模板语言。

jOOQ

This is a popular SQL DSL allowing for typesafe construction of SQL statements directly in Java. Unlike MyBatis, this library encourages embedding SQL in Java, instead of externalising it.

这是一种流行的SQL DSL,允许直接在Java中进行SQL语句的类型安全构造。与MyBatis不同,这个库鼓励在Java中嵌入SQL,而不是将其外化。

Other alternatives...

... include SQL-string-centric libraries that ease some of the pain when operating with JDBC directly:

...包括以SQL字符串为中心的库,可以在直接使用JDBC时减轻一些痛苦:

#4


2  

Hibernate and other ORMs are designed to make RDBMSs work with object oriented applications. If you are not forced to use an RDBMS I would simply use an ODBMS.

Hibernate和其他ORM旨在使RDBMS与面向对象的应用程序一起工作。如果您不*使用RDBMS,我只需使用ODBMS。

Many ODBMS support implicit lazy-loading via byte-code enhancement, so it is almost impossible to write code that accesses an object that is not properly loaded. You can usually also specify (per code-path) closures that load objects not one-by-one but in batches, which improves performance.

许多ODBMS通过字节码增强支持隐式延迟加载,因此编写访问未正确加载的对象的代码几乎是不可能的。您通常还可以指定(每个代码路径)闭包,这些闭包不是逐个加载对象,而是批量加载,这样可以提高性能。

Some ODBMS are:

一些ODBMS是:

  • db4o (free, pure Java, but less powerful)
  • db4o(免费,纯Java,但功能不强)

  • Versant (powerful, commercial, Java frontend, C/C++ backend)
  • Versant(功能强大,商业化,Java前端,C / C ++后端)

  • ObjectStore (commercial)
  • Objectivity (commercial)

ODBMS are sometimes frowned upon, but (in my experience) never by people that have actually used them. I have ODBMS in small and large projects (up to 10TB and 2.000.000.000 objects) and I would never go back to RDBMS.

ODBMS有时不受欢迎,但(根据我的经验)从来没有实际使用它们的人。我在小型和大型项目中有ODBMS(高达10TB和2.000.000.000个对象),我永远不会回到RDBMS。

#5


1  

I don't know about "better" than Hibernate, but if you don't like it there are other alternatives to try:

我不知道“比Hibernate更好”,但是如果你不喜欢它,还有其他的尝试:

  1. TopLink (similar to Hibernate)
  2. TopLink(类似于Hibernate)

  3. iBatis
  4. Spring JDBC support (makes JDBC pretty easy, especially if you're already using Spring)
  5. Spring JDBC支持(使JDBC变得非常简单,特别是如果你已经使用了Spring)

#6


1  

Another ORM library to consider is www.sormula.org. It supports relationships but lazy loading is optional. It was designed to be a simple alternative to the world of complex ORM solutions. I am the author.

另一个需要考虑的ORM库是www.sormula.org。它支持关系,但延迟加载是可选的。它旨在成为复杂ORM解决方案世界的简单替代方案。我是作者。

#7


0  

Some of the classical ODBMS have also implemented the JPA standard like Versant. So it is easy to try it out. If you want to know how fast they are have a look into the Polepos Benchmark which compares different persistence API's with different implementations with different RDBMS/ODBMS. You can also extend the benchmark easily with your own usecases and run them with all the different persistence technologies.

一些经典的ODBMS也实现了像Versant这样的JPA标准。所以很容易尝试一下。如果你想知道他们有多快查看Polepos Benchmark,它将不同的持久性API与不同的实现与不同的RDBMS / ODBMS进行比较。您还可以使用自己的用例轻松扩展基准测试,并使用所有不同的持久性技术运行它们。

#1


0  

One person already mentioned Open Session in View, which will eliminate most if not all of your lazy loading problems (but it brings its own problems).

一个人已经在视图中提到了Open Session,这将消除大部分(如果不是全部)延迟加载问题(但它带来了自己的问题)。

Open JPA has something called 'fetch groups'. This is basically a named set of fetch settings that you can set before running queries, etc. You would then select the appropriate fetch strategy before running the query (presumably in your service impl). This way, the fetch plan is separate from the mapping. You can configure as many fetch plans as you have use cases. In one fetch plan, a particular association is lazy, but in another, it is eager / JOIN. Seems awesome.

Open JPA有一个名为'fetch groups'的东西。这基本上是一组命名的提取设置,您可以在运行查询之前设置它们等。然后在运行查询之前选择适当的提取策略(可能在您的服务impl中)。这样,获取计划与映射是分开的。您可以根据用例配置任意数量的提取计划。在一个获取计划中,一个特定的关联是懒惰的,但在另一个,它是渴望/ JOIN。看起来很棒。

If you've been coding to the JPA spec instead of native Hibernate, the switch to Open JPA could be easy.

如果您已经编写了JPA规范而不是本机Hibernate,那么切换到Open JPA可能很容易。

If I'm not mistaken, some work is being done to implement fetch groups in Hibernate, but I'm too lazy to google that right now.

如果我没弄错的话,正在做一些工作来实现Hibernate中的获取组,但我现在懒得谷歌。

#2


3  

First of, this has nothing to do with Hibernate. Pretty much any ORM (certainly any JPA provider) implements lazy loading in a similar fashion.

首先,这与Hibernate无关。几乎任何ORM(当然任何JPA提供程序)都以类似的方式实现延迟加载。

As far as "would prefer lazy-loading in one area and no lazy loading in another" goes, you can override lazy fetching via HQL fetch join if you're using queries. For straight up session.get() there's usually no need to do so (Note - see below), you can just let lazy loading do its magic for you. For that to happen you need to ensure your session stays alive until all requests to entity (its properties / collections / etc...) are done, which is typically achieved via Open Session in View pattern. Spring has a corresponding interceptor as well.

至于“更喜欢在一个区域中进行延迟加载而在另一个区域中没有延迟加载”,如果您正在使用查询,则可以通过HQL提取连接覆盖延迟提取。对于直接的session.get(),通常没有必要这样做(注意 - 见下文),你可以让延迟加载为你做出魔力。为此,您需要确保您的会话保持活动状态,直到完成对实体的所有请求(其属性/集合/等...),这通常通过View模式中的Open Session实现。 Spring也有相应的拦截器。

Note: One case where you have to load all entity's dependencies is when you're going to ship it to a remote system (thus making original session unavailable). This is typically handled by marshaller, though.

注意:您必须加载所有实体的依赖关系的一种情况是您要将其发送到远程系统(从而使原始会话不可用)。但这通常由marshaller处理。

#3


3  

I agree with others that the notion of better is subjective and context-dependent. True alternatives to JPA / Hibernate are:

我同意其他人认为更好的概念是主观的和依赖于背景的。 JPA / Hibernate的真正替代品是:

MyBatis

It is the most popular SQL templating engine in Java. It externalises SQL statements into XML files, from where they can be loaded by ID or by other means. As a templating engine, MyBatis also supports SQL composition and a slim templating language for loops and branch statements.

它是Java中最流行的SQL模板引擎。它将SQL语句外部化为XML文件,可以通过ID或其他方式从中加载它们。作为模板引擎,MyBatis还支持SQL组合和用于循环和分支语句的简洁模板语言。

jOOQ

This is a popular SQL DSL allowing for typesafe construction of SQL statements directly in Java. Unlike MyBatis, this library encourages embedding SQL in Java, instead of externalising it.

这是一种流行的SQL DSL,允许直接在Java中进行SQL语句的类型安全构造。与MyBatis不同,这个库鼓励在Java中嵌入SQL,而不是将其外化。

Other alternatives...

... include SQL-string-centric libraries that ease some of the pain when operating with JDBC directly:

...包括以SQL字符串为中心的库,可以在直接使用JDBC时减轻一些痛苦:

#4


2  

Hibernate and other ORMs are designed to make RDBMSs work with object oriented applications. If you are not forced to use an RDBMS I would simply use an ODBMS.

Hibernate和其他ORM旨在使RDBMS与面向对象的应用程序一起工作。如果您不*使用RDBMS,我只需使用ODBMS。

Many ODBMS support implicit lazy-loading via byte-code enhancement, so it is almost impossible to write code that accesses an object that is not properly loaded. You can usually also specify (per code-path) closures that load objects not one-by-one but in batches, which improves performance.

许多ODBMS通过字节码增强支持隐式延迟加载,因此编写访问未正确加载的对象的代码几乎是不可能的。您通常还可以指定(每个代码路径)闭包,这些闭包不是逐个加载对象,而是批量加载,这样可以提高性能。

Some ODBMS are:

一些ODBMS是:

  • db4o (free, pure Java, but less powerful)
  • db4o(免费,纯Java,但功能不强)

  • Versant (powerful, commercial, Java frontend, C/C++ backend)
  • Versant(功能强大,商业化,Java前端,C / C ++后端)

  • ObjectStore (commercial)
  • Objectivity (commercial)

ODBMS are sometimes frowned upon, but (in my experience) never by people that have actually used them. I have ODBMS in small and large projects (up to 10TB and 2.000.000.000 objects) and I would never go back to RDBMS.

ODBMS有时不受欢迎,但(根据我的经验)从来没有实际使用它们的人。我在小型和大型项目中有ODBMS(高达10TB和2.000.000.000个对象),我永远不会回到RDBMS。

#5


1  

I don't know about "better" than Hibernate, but if you don't like it there are other alternatives to try:

我不知道“比Hibernate更好”,但是如果你不喜欢它,还有其他的尝试:

  1. TopLink (similar to Hibernate)
  2. TopLink(类似于Hibernate)

  3. iBatis
  4. Spring JDBC support (makes JDBC pretty easy, especially if you're already using Spring)
  5. Spring JDBC支持(使JDBC变得非常简单,特别是如果你已经使用了Spring)

#6


1  

Another ORM library to consider is www.sormula.org. It supports relationships but lazy loading is optional. It was designed to be a simple alternative to the world of complex ORM solutions. I am the author.

另一个需要考虑的ORM库是www.sormula.org。它支持关系,但延迟加载是可选的。它旨在成为复杂ORM解决方案世界的简单替代方案。我是作者。

#7


0  

Some of the classical ODBMS have also implemented the JPA standard like Versant. So it is easy to try it out. If you want to know how fast they are have a look into the Polepos Benchmark which compares different persistence API's with different implementations with different RDBMS/ODBMS. You can also extend the benchmark easily with your own usecases and run them with all the different persistence technologies.

一些经典的ODBMS也实现了像Versant这样的JPA标准。所以很容易尝试一下。如果你想知道他们有多快查看Polepos Benchmark,它将不同的持久性API与不同的实现与不同的RDBMS / ODBMS进行比较。您还可以使用自己的用例轻松扩展基准测试,并使用所有不同的持久性技术运行它们。