- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
当使用标准 JPA 注释时,您可以在非集合字段(即 @ManyToOne
和 @OneToOne
)上指定 FetchType.LAZY
。在这种情况下,Hibernate 似乎在内部使用“代理”获取。但是代理抓取在继承方面存在问题,我认为最好将无代理抓取与字节码检测结合使用。不幸的是,Hibernate 仍然要求您在 hbm
文件中指定“no-proxy”或使用特定于 Hibernate 的 @LazyToOne
注释。
我的问题是:Hibernate 是否支持对所有非集合字段(即 FetchType.LAZY
)使用无代理提取策略的配置选项?
这就是我需要它的原因:一方面,我想在大多数情况下只使用 JPA 注释。另一方面,我想避免继承和惰性字段的问题。而且我不喜欢将所有内容都包装在接口(interface)中的想法,因为我在当前项目中使用 DDD,所以我认为我的域模型中不应该存在样板垃圾,只有纯业务逻辑。
我有一个糟糕的解决方法:通过使用字节码修改,我在所有出现 @ManyToOne
的地方添加了 @LazyToOne
注释。但我更喜欢内置的 Hibernate 功能(如果存在的话)。
这是代理获取的(众所周知的)问题,让事情更清楚一点:
@Entity @DiscriminatorColumn("t") @DiscriminatorValue("")
public abstract class A {
@Id private Integer id;
}
@Entity @DiscriminatorValue("B")
public abstract class B extends A {
}
@Entity @DiscriminatorValue("C")
public abstract class C extends A {
}
@Entity public class D {
@Id private Integer id;
@ManyToOne(fetch = FetchType.LAZY) private A a;
public A getA() {
return a;
}
}
准备:
D d = new D();
C c = new C();
d.setA(c);
em.persist(d);
断言失败(在另一个 EM 中,另一个事务):
D d = em.createQuery("select d from D d", D.class).getSingleResult();
List<C> cs = em.createQuery("select c from C c", C.class).getResultList();
assert d.getA() instanceof C;
assert d.getA() == cs.get(0);
以下是我要修复上述断言的方法:
@Entity public class D {
@Id private Integer id;
@ManyToOne(fetch = FetchType.LAZY) @LazyToOne(LazyToOneOption.NO_PROXY)
private A a;
public A getA() {
return a;
}
}
而且我不希望在没有 @LazyToOne
注释的情况下默认启用相同的功能。
最佳答案
好吧,我放弃接收答案。我仔细检查了 Hibernate 源代码并得出结论,Hibernate 本身没有属性来实现我想要的。但是我想出了一个小黑点,这正是我想要的。所以,这里是:
public class DirtyHackedHibernatePersistence extends HibernatePersistence {
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName,
Map properties) {
properties.put(AvailableSettings.PROVIDER, HibernatePersistence.class.getName());
Ejb3Configuration cfg = new Ejb3Configuration().configure(persistenceUnitName, properties);
if (cfg == null) {
return null;
}
cfg.buildMappings();
hackConfiguration(cfg);
return cfg.buildEntityManagerFactory();
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info,
Map properties) {
properties.put(AvailableSettings.PROVIDER, HibernatePersistence.class.getName());
Ejb3Configuration cfg = new Ejb3Configuration().configure(info, properties);
if (cfg == null) {
return null;
}
cfg.buildMappings();
hackConfiguration(cfg);
return cfg.buildEntityManagerFactory();
}
private void hackConfiguration(Ejb3Configuration cfg) {
System.out.println("Hacking configuration");
String noProxyByDefault = cfg.getProperties().getProperty("hibernate.hack.no-proxy-by-default", "false");
if (Boolean.parseBoolean(noProxyByDefault)) {
Iterator<?> iter = cfg.getClassMappings();
while (iter.hasNext()) {
hackClass((PersistentClass)iter.next());
}
}
}
private void hackClass(PersistentClass classMapping) {
Iterator<?> iter = classMapping.getPropertyIterator();
while (iter.hasNext()) {
Property property = (Property)iter.next();
if (property.getValue() instanceof ToOne) {
ToOne toOne = (ToOne)property.getValue();
if (toOne.isLazy()) {
toOne.setUnwrapProxy(true);
}
}
}
}
}
还必须有一个名为 META-INF/services/javax.persistence.spi.PersistenceProvider
的资源,其中包含一行类名。
要使用此 hack,您应该在 persistence.xml
中指定以下内容:
<provider>packagename.DirtyHackedHibernatePersistence</provider>
<properties>
<property name="hibernate.hack.no-proxy-by-default" value="true"/>
</properties>
完整示例可用here .
请注意,如果您删除 hibernate.hack.no-proxy-by-default
属性并重建项目,两个断言都会被破坏。
我还将向 Hibernate 团队提交功能请求。
关于java - 在 Hibernate 中默认为所有 FetchType.LAZY 非集合启用无代理行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19928411/
我想知道如何首先检测 Javascript 是否启用/禁用。在此站点上禁用 javascript 表明 stackoverflow 使用了称为标签的东西。 这是标准的做法吗?它适用于所有浏览器吗?它不
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: How to enable PHP short tags ? Enable short open tags
在 VSTS (Azure DevOps) 上拥有私有(private)存储库我尝试通过将以下内容添加到 .csproj 文件来启用 SourceLink:https://github.com/dot
我创建了一个 wx.Frame(我们称之为 mainFrame)。该框架上包含一个按钮,当单击该按钮时,会创建一个新框架(我们称之为 childFrame)。 我想知道如何在创建 childFrame
当我禁用 WPF 中的控件时,比如说一个菜单项 MenuItem aMenuItem = ... aMenuItem.IsEnabled = false; MenuItem 中的文本仍然处于事件状态,
我想在我的 nginx 服务器上启用 gzip 压缩。 nginx.conf 文件在这里: http { # Enable Gzip server { location ~* \.(?
我正在使用免费的 heroku 附加 PG 备份并遵循这些 instructions .我找到了安装应用程序的命令:heroku addons:add pgbackups:auto-week。但是我想
我想知道脚本是否可以使用某种切换按钮启用/禁用页面上的所有输入元素。 我用谷歌搜索了它,但除了这个之外没有发现任何有用的东西: http://www.codetoad.com/javascript/e
在我的 php 文件中,我想使用 jQuery Datepicker。 当我的文件加载时,我创建了禁用的日期选择器。 然后,当我的 php 文件(它是一个表单)中的一个特殊字段被填充时,我想启用日期选
我有一个按钮,如下所示: RadButton lnkAdd = new RadButton(); lnkAdd.ID = "BtnAdd"; lnkAdd.CommandName = RadGrid.
public static void ToggleTaskManager(string keyValue) { RegistryKey objRegistryK
我正在 Azure 中使用事件网格订阅,该订阅在创建 Blob 时触发。然而,我们有很多文件进入这个 blob,比如说 1000 多个。 如果我发现任何文件有任何错误,我想做的是禁用事件订阅。 最佳答
我的网站上有几个使用 HTML5 contentEditable 属性的 div。目标是让用户能够开始编写日记条目,并将保存按钮从禁用更改为启用。 这是我目前拥有的 HTML: Write
我有一个范围输入,其定义如下: @Html.LabelFor(m => Model.Quality, Resources.CompressionQuality) 和一个下拉菜单: @Html.Lab
我正在尝试创建一个启用/禁用按钮的下拉菜单,并且我正在关注此 example 但它已经有 4 年历史了,而且该功能似乎无法在我的 xhtml 页面上运行。 任何帮助都将被适当 最佳答案 这是一个现场演
我正在 Azure 中使用事件网格订阅,该订阅在创建 Blob 时触发。然而,我们有很多文件进入这个 blob,比如说 1000 多个。 如果我发现任何文件有任何错误,我想做的是禁用事件订阅。 最佳答
我在这里遇到一个非常奇怪的情况:我编写了一个应用程序,除其他外,将连接的代理从打开切换到关闭,反之亦然。通过更改注册表中的值来完成此操作: public void SetUpProxy(string
我需要调整一堆 PVC 的大小。似乎最简单的方法是通过ExpandPersistentVolumes 功能。但是我无法获得配置合作。 ExpandPersistentVolumes feature g
如果我的TextField为空,则应禁用该按钮,并且该按钮的textColor和borderColor应该为灰色。但是,启用按钮后,颜色应为蓝色。 更改textColor很容易: button.Set
您好,我的问题是:我无法从另一个类启用表单的按钮。我的表单类是 public class FileSending { //Function for enabling the button
我是一名优秀的程序员,十分优秀!