想象一下关系数据库中的 2 个表,例如人员和计费。这些实体之间定义了一个(非强制的)OneToOne 关联,它们共享 Person 主键(即 PERSON_ID 在 Person 和 Billing 中定义,在后者中是外键)。
当通过命名查询对 Person 进行选择时,例如:
from Person p where p.id = :id
Hibernate/JPA 生成两个选择查询,一个在 Person 表上,另一个在 Billing 表上。
上面的示例非常简单,不会导致任何性能问题,因为查询只返回一个结果。现在,想象一下 Person有n与其他实体(所有共享 Person 主键)的 OneToOne 关系(所有非强制)。
如果我错了请纠正我,但运行 select查询 Person,返回 r行,将导致 (n+1)*r选择由 Hibernate 生成,即使关联是惰性。
对于这种潜在的性能灾难是否有解决方法(除了根本不使用共享主键之外)?感谢您的所有想法。
最佳答案
Imagine 2 tables in a relational database, e.g. Person and Billing. There is a (non-mandatory) OneToOne association defined between these entities,
默认情况下,对于非强制性的 OneToOne,延迟获取在概念上是不可能的,Hibernate 必须访问数据库才能知道关联是否为 null。这个旧 wiki 页面的更多详细信息:
Some explanations on lazy loading (one-to-one)
[...]
Now consider our class B has one-to-one association to C
class B { private C cee; public C getCee() { return cee; } public void setCee(C cee) { this.cee = cee; } } class C { // Not important really }Right after loading B, you may call
getCee()to obtain C. But look,getCee()is a method of YOUR class and Hibernate has no control over it. Hibernate does not know when someone is going to callgetCee(). That means Hibernate must put an appropriate value into "cee" property at the moment it loads B from database. If proxy is enabled forC, Hibernate can put a C-proxy object which is not loaded yet, but will be loaded when someone uses it. This gives lazy loading forone-to-one.But now imagine your
Bobject may or may not have associatedC(constrained="false"). What shouldgetCee()return when specificBdoes not haveC? Null. But remember, Hibernate must set correct value of "cee" at the moment it setB(because it does no know when someone will callgetCee()). Proxy does not help here because proxy itself in already non-null object.So the resume: if your B->C mapping is mandatory (
constrained=true), Hibernate will use proxy for C resulting in lazy initialization. But if you allow B without C, Hibernate just HAS TO check presence of C at the moment it loads B. But a SELECT to check presence is just inefficient because the same SELECT may not just check presence, but load entire object. So lazy loading goes away.
所以,不可能……默认情况下。
Is there a workaround for this potential performance disaster (other than not using a shared primary key at all)? Thank you for all your ideas.
问题不是共享主键,有或没有共享主键,你会明白的,问题是nullable OneToOne。
第一个选项:使用字节码检测(参见下面的文档引用)和无代理抓取:
@OneToOne( fetch = FetchType.LAZY )
@org.hibernate.annotations.LazyToOne(org.hibernate.annotations.LazyToOneOption.NO_PROXY)
第二个选项:使用伪造的ManyToOne(fetch=FetchType.LAZY)。这可能是最简单的解决方案(据我所知,这是推荐的解决方案)。但是我没有使用共享 PK 对此进行测试。
第三个选项:使用join fetch 急切加载账单。
关于java - 具有共享主键的 OneToOne 关系生成 n+1 个选择;任何解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1002547/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案