- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在我的一个 Web 服务中检测到缺陷后,我将错误追踪到以下单行:
return this.getTemplate().getDomains().stream().anyMatch(domain -> domain.getName().equals(name));
当我确定域列表包含一个名称等于提供的 name
的域时,此行返回 false。因此,在摸索了一会儿之后,我最终拆分了整条线以查看发生了什么。我在调试 session 中得到以下信息:
请注意以下行:
List<Domain> domains2 = domains.stream().collect(Collectors.toList());
根据调试器,domains
是一个包含两个元素的列表。但是在应用 .stream().collect(Collectors.toList())
之后,我得到了一个完全空的列表。如果我错了,请纠正我,但据我了解,这应该是身份操作并返回相同的列表(如果我们严格的话,或者返回它的副本)。那么这里发生了什么???
在你问之前:不,我根本没有操纵那个屏幕截图。
为了说明这一点,这段代码在有状态请求范围内的 EJB 中执行,使用 JPA 管理的实体,在扩展的持久性上下文中进行字段访问。这里有一些与手头问题相关的代码部分:
@Stateful
@RequestScoped
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class DomainResources {
@PersistenceContext(type = PersistenceContextType.EXTENDED) @RequestScoped
private EntityManager entityManager;
public boolean templateContainsDomainWithName(String name) { // Extra code included to diagnose the problem
MetadataTemplate template = this.getTemplate();
List<Domain> domains = template.getDomains();
List<Domain> domains2 = domains.stream().collect(Collectors.toList());
List<String> names = domains.stream().map(Domain::getName).collect(Collectors.toList());
boolean exists1 = names.contains(name);
boolean exists2 = this.getTemplate().getDomains().stream().anyMatch(domain -> domain.getName().equals(name));
return this.getTemplate().getDomains().stream().anyMatch(domain -> domain.getName().equals(name));
}
@POST
@RolesAllowed({"root"})
public Response createDomain(@Valid @EmptyID DomainDTO domainDTO, @Context UriInfo uriInfo) {
if (this.getTemplate().getLastVersionState() != State.DRAFT) {
throw new UnmodifiableTemplateException();
} else if (templateContainsDomainWithName(domainDTO.name)) {
throw new DuplicatedKeyException("name", domainDTO.name);
} else {
Domain domain = this.getTemplate().createNewDomain(domainDTO.name);
this.entityManager.flush();
return Response.created(uriInfo.getAbsolutePathBuilder().path(domain.getId()).build()).entity(new DomainDTO(domain)).type(MediaType.APPLICATION_JSON).build();
}
}
}
@Entity
public class MetadataTemplate extends IdentifiedObject {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "metadataTemplate", orphanRemoval = true) @OrderBy(value = "creationDate")
private List<Version> versions = new LinkedList<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) @OrderBy(value = "name")
private List<Domain> domains = new LinkedList<>();
public List<Version> getVersions() {
return Collections.unmodifiableList(versions);
}
public List<Domain> getDomains() {
return Collections.unmodifiableList(domains);
}
}
我包含了 getVersions
和 getDomains
方法,因为我有类似的操作在版本上完美运行。我能找到的唯一显着区别是 versions
是急切获取的,而 domains
是延迟获取的。但据我所知,代码正在事务中执行,并且正在加载域列表。如果不是,我会得到一个惰性初始化异常,不是吗?
更新:根据@Ferrybig 的建议,我进一步调查了这个问题,似乎与不正确的延迟加载没有任何关系。如果我以经典方式遍历集合,我仍然无法使用流获得正确的结果:
boolean found = false;
for (Domain domain: this.getTemplate().getDomains()) {
if (domain.getName().equals(name)) {
found = true;
}
}
List<Domain> domains = this.getTemplate().getDomains();
long estimatedSize = domains.spliterator().estimateSize(); // This returns 0!
domains.spliterator().forEachRemaining(domain -> {
// Execution flow never reaches this point!
});
所以看起来即使集合已加载,您仍然会有这种奇怪的行为。这似乎是用于管理惰性集合的代理中缺少或空的拆分器实现。你怎么看?
顺便说一句,这是部署在 Glassfish/EclipseLink 上
最佳答案
这里的问题来自其他人在几个地方的错误的组合。所有这些错误的总和引发了这种错误行为。
第一个错误:可疑的继承。 EclipseLink 似乎创建了一个代理来管理 org.eclipse.persistence.indirection.IndirectList
类型的惰性集合.此类扩展 java.util.Vector
尽管它覆盖了除 removeRange
之外的所有内容.亲爱的 Eclipse 开发人员,到底为什么要扩展一个类来覆盖父类中的几乎所有内容,而不是声明该类来实现合适的接口(interface)(Iterable<E>
、Collection<E>
或 List<E>
)?
第二个错误:嘿,我继承了你的东西,但我对你的内部结构不屑一顾。所以IndirectList
使用 delegate 来实现延迟加载的魔力。但是,天哪!我如何计算大小?我是否使用(并保持更新) parent 的 elementCount
属性(property)?不,当然,我只是将该任务委托(delegate)给我的委托(delegate)...所以如果父类需要做任何与大小相关的事情,那么,运气不好。无论如何,我已经覆盖了所有内容...他们不会向该类添加任何新内容,对吗?
第三个错误:封装破损。输入 Vector
.在 Java 1.8 中,此类得到了扩充,现在提供了一个 spliterator
。支持新流功能的方法。他们创建了一个静态内部类 (VectorSpliterator
),允许客户端使用 Shiny 的新 API 遍历 vector 。一切正常,直到您注意到为了知道何时完成遍历,他们使用了 protected 实例变量 elementCount
而不是使用公共(public) API 方法 size()
.因为谁会扩展非最终类并返回不基于 elementCount
的大小?你看到灾难来临了吗?
我们到了,IndirectList
无意中继承了 Vector
的新功能(请记住,它一开始可能不应该从它继承),并用这种错误组合破坏事物。
总而言之,当使用 EclipseLink(Glassfish 中的默认 JPA 提供程序)时,似乎惰性集合的流遍历即使对于已经加载的集合也不起作用。请记住,这些产品来自同一供应商。万岁!
解决方法:如果您遇到此问题但仍想利用 stream()
提供的函数式编程风格您可以制作集合的副本,以便构建适当的迭代器。在我的例子中,我能够将域的所有类似用途保留为修改 getDomains
的单行代码。方法。在这种情况下,我更喜欢代码的可读性(具有函数式风格)而不是性能:
public List<Domain> getDomains() {
return Collections.unmodifiableList(new ArrayList<>(domains));
}
读者须知:抱歉讽刺,但我不想在这些事情上浪费我宝贵的开发时间。
感谢@Ferrybig 提供的初步线索
更新:错误报告。如果这对您有影响,您可以在 https://bugs.eclipse.org/bugs/show_bug.cgi?id=487799 关注它的进展。
关于java - Stream API 不适用于 EclipseLink/Glassfish 中的延迟加载集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35362581/
我在为 MacOSX 构建的独立包中添加 DMG 背景的自定义图标时遇到问题。我在项目的根目录中添加了一个包。正在从中加载自定义图标,但没有加载 DMG 背景图标。我正在使用 Java fx 2.2.
Qt for Symbian 和 Qt for MeeGo 有什么区别?我知道 Qt 是一个交叉编译平台。这是否意味着如果我使用来自 Qt 的库,完全相同的库可以在所有支持 Qt 的设备(例如 Sym
我正在尝试使用 C# .NET 3.5/4.0 务实地运行 SQL Server 数据库的备份。我已经找到了如何完成此操作,但是我似乎找不到用于备份的命名空间库。 我正在寻找 Microsoft.Sq
我最近在疯狂学习 Java,但我通常是一名 .NET 开发人员。 (所以请原谅我的新手问题。) 在 .Net 中,我可以在不使用 IIS 的情况下开发 ASP.Net 页面,因为它有一个简化的 Web
这post仅当打印命令中有字符串时才有用。现在我有大量的源代码,其中包含一条声明,例如 print milk,butter 应该格式化为 print(milk,butter) 用\n 捕获行尾并不成功
所以我的问题是: https://gist.github.com/panSarin/4a221a0923927115584a 当我保存这个表格时,我收到了标题中的错误 NoMethodError (u
如何让 Html5 音频在点击时播放声音? (ogg 用于 Firefox 等浏览器,mp3 用于 chrome 等浏览器) 到目前为止,我可以通过 onclick 更改为单个文件类型,但我无法像在普
如果it1和it2有什么区别? std::set s; auto it1 = std::inserter(s, s.begin()); auto it2 = std::inserter(s, s.en
4.0.0 com.amkit myapp SpringMVCFirst
我目前使用 Eclipse 作为其他语言的 IDE,而且我习惯于不必离开 IDE 做任何事情 - 但是我真的很难为纯 ECMAScript-262 找到相同或类似的设置。 澄清一下,我不是在寻找 DO
我想将带有字符串数组的C# 结构发送到C++ 函数,该函数接受void * 作为c# 结构和char** 作为c# 结构字符串数组成员。 我能够将结构发送到 c++ 函数,但问题是,无法从 c++ 函
我正在使用动态创建的链接: 我想为f:param附加自定义转换器,以从#{name}等中删除空格。 但是f:param中没有转换器
是否可以利用Redis为.NET创建后写或直写式缓存?理想情况下,透明的高速缓存是由单个进程写入的,并且支持从数据库加载丢失的数据,并每隔一段时间持久保存脏块? 我已经搜查了好几个小时,也许是goog
我正在通过bash执行命令的ssh脚本。 FILENAMES=( "export_production_20200604.tgz" "export_production_log_2020060
我需要一个正则表达式来出现 0 到 7 个字母或 0 到 7 个数字。 例如:匹配:1234、asdbs 不匹配:123456789、absbsafsfsf、asf12 我尝试了([a-zA-Z]{0
我有一个用于会计期间的表格,该表格具有期间结束和开始的开始日期和结束日期。我使用此表来确定何时发生服务交易以及何时在查询中收集收入,例如... SELECT p.PeriodID, p.FiscalY
我很难为只接受字符或数字的 Laravel 构建正则表达式验证。它是这样的: 你好<-好的 123 <- 好的 你好123 <-不行 我现在的正则表达式是这样的:[A-Za-z]|[0-9]。 reg
您实际上会在 Repeater 上使用 OnItemDataBound 做什么? 最佳答案 “此事件为您提供在客户端显示数据项之前访问数据项的最后机会。引发此事件后,数据项将被清空,不再可用。” ~
我有一个 fragment 工作正常的项目,我正在使用 jeremyfeinstein 的 actionbarsherlock 和滑动菜单, 一切正常,但是当我想自定义左侧抽屉列表单元格时,出现异常
最近几天,我似乎平均分配时间在构建我的第一个应用程序和在这里发布问题!! 这是我的第一个应用程序,也是我们的设计师完成的第一个应用程序。我试图满足他所做的事情的外观和感觉,但我认为他没有做适当的事情。
我是一名优秀的程序员,十分优秀!