Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring JPA存储库n+;1问题,一个替代方案_Java_Spring_Hibernate_Ebean - Fatal编程技术网

Java Spring JPA存储库n+;1问题,一个替代方案

Java Spring JPA存储库n+;1问题,一个替代方案,java,spring,hibernate,ebean,Java,Spring,Hibernate,Ebean,我正在为现有的MySQL数据库编写一个基于Java的服务器。我可以改变数据库的结构,但任何改变也意味着要挖掘一个非常古老的CakePHP项目,我希望尽可能不去触及这个项目 我对Java中的数据库访问没有太多经验,所以当我开始寻找一个好的框架时,我最终得到了Spring数据存储库(主要是因为我已经有了用于REST服务的Spring引导执行器),并且手动滚动Hibernate或其他JPA实现看起来既单调又复杂 现在的问题是,我的查询速度不是很快。例如,查询我的~200个用户,并加载他们的关联(use

我正在为现有的MySQL数据库编写一个基于Java的服务器。我可以改变数据库的结构,但任何改变也意味着要挖掘一个非常古老的CakePHP项目,我希望尽可能不去触及这个项目

我对Java中的数据库访问没有太多经验,所以当我开始寻找一个好的框架时,我最终得到了Spring数据存储库(主要是因为我已经有了用于REST服务的Spring引导执行器),并且手动滚动Hibernate或其他JPA实现看起来既单调又复杂

现在的问题是,我的查询速度不是很快。例如,查询我的~200个用户,并加载他们的关联(user.groups、user.groups.rights、user.groups.rights.permissions、user.rights、user.rights.permissions、users.nfc_密钥)。我需要所有这些数据,因为连接到Java服务器的一个客户端需要这些信息来登录用户,即使主服务器宕机,也需要这些信息来加速登录(换句话说,它会缓存信息)

问题是,执行查询需要8秒钟!我知道这些问题,具体来说是n+1问题。因为我所有的集合都是延迟加载的,所以hibernate查询组、组、权限等,。。。。为每个用户单独设置。例如,“我的组”字段如下所示:

@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
@JoinTable(
        name = "user_group_memberships",
        joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
        inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")}
)
private List<Group> groups;
@ManyToMany(fetch=FetchType.LAZY,cascade={CascadeType.ALL})
@可接合(
name=“用户\组\成员身份”,
joinColumns={@JoinColumn(name=“user\u id”,referencedColumnName=“id”)},
inverseJoinColumns={@JoinColumn(name=“group\u id”,referencedColumnName=“id”)}
)
私人名单组;
我尝试将FetchType更改为EAGER,唯一的作用是通过查询急切地获取所有组,但不是通过SQL连接,而是通过执行n查询

我在UserRepository中查看并实现了一个查询,使用左连接获取加载信息,需要从列表更改为集合,对由于我的hashCode/equals实现导致的空指针问题感到恼火,再次延迟加载/set代理,以发现查询时间缩短到2秒左右,这还不错,但与CakePHP执行相同查询的速度相比,仍然非常慢


我现在的问题主要是:是否有直接的解决方案可以使用Spring数据存储库来解决此类问题,或者我最好切换到另一个框架(这在项目的早期阶段仍然是可能的)?我专门研究了Play框架中使用的ebean,它们似乎有一个非常好的API,并且还允许定义获取路径(这将更好地解决n+1问题),但是我也了解到该项目维护不善。您的看法是什么?

查询速度与很多事情有关:

1.驱动程序-2.数据库-3.连接池配置

根据我在JPA的经验:

尝试在视图层中打开会话,并尝试使用HikariCP 加速连接速度


请注意,我有偏见,因为我是Ebean ORM的主要维护者

Ebean存在的一个主要原因是,我认为JPQL在优化ORM查询/对象图构造方面设计得很差。特别是缺少对“部分对象”和“获取路径”的支持。在某种程度上,JPA fetch组试图解决这些问题,但您注意到这两个问题都是由Ebeans查询语言直接处理的。JPA获取组不符合IMO(例如,从DB、L2和L3构建混合对象图)

请注意,在生活的繁忙时期(孩子们等),我故意保持埃比安的低调。Ebean ORM有一个赞助商,如果你看项目发布,你会发现它的健康状况良好

Eben ORM实际上已经有10年的历史了,所以它并不完全是一个新的或年轻的项目

最近,ElasticSearch集成发布了,它能够从ElasticSearch构建对象图(或对象图的路径)。这可以在不加载数据库的情况下提供读取可伸缩性

此外,您可能知道Ebean可以评测应用程序并自动调优ORM查询(如果没有,请查看视频)

希望这能有所帮助。 干杯,罗伯

更新: 添加一些链接供对细节感兴趣的人参考(并避免N+1、优化ORM查询等):

  • N+1
  • 部分对象
  • 自动查询调整
  • ElasticSearch

我们将为我的测试做一些微基准测试。JUnit测试只运行这个查询,这些问题真的可以通过使用不同的连接池来解决吗?一些使用块的连接池,使用diffirent概念,这有助于连接永不疲倦。另外,您现在使用Java for enterprice,它需要比php更多的字节码,会话也将保留im内存,php在磁盘中的每个req resp中存储会话,帮助php减少内存使用,如果您熟悉sql,也可以使用jdbctemplate使用更少的内存和更快的速度。您需要启用查询日志记录,并研究MySql创建的查询计划。如果查询没有使用预期的索引(如表扫描等),则可能需要添加索引或手工创建查询。