gpt4 book ai didi

合并 myMap 后的 java 8 lambda myMap.stream().count() != myMap.size()

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:22:35 26 4
gpt4 key购买 nike

编辑:我发现这是 eclipse 链接的错误:https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075

原始问题:

在 JUnit 测试中,我发现了意外行为。如您所见,最后一个断言失败了,因为流似乎不包含任何数据,而映射不为空?!我发现,它与 jpa/eclipselink 有关。

public class MyTest {
private EntityManager em;

@Before
public void setUp() throws IOException {
String dbFileName = "testDb.db";
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(PersistenceUnitProperties.JDBC_URL, "jdbc:sqlite:"
+ dbFileName);
EntityManagerFactory factory = Persistence.createEntityManagerFactory("pul", properties);
this.em = factory.createEntityManager();
}

@Test
public void testStrange() {
LV lv = new LV();
// em.persist(lv); // this would work
// em.merge(lv); // this would work as well
lv = em.merge(lv); // this leads to the assertionError
lv.getAms().add(new AM());
assertEquals(1, lv.getAms().size()); // ok
assertEquals(1, lv.getAms().stream().count()); // java.lang.AssertionError: expected:<1> but was:<0>
}
}

LV:

@Entity
public class LV {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long _id;

@OneToMany(mappedBy = "lv", cascade = CascadeType.ALL)
private Collection<AM> ams = new HashSet<AM>();

public LV() {
}

public Collection<AM> getAms() {
return ams;
}

}

上午:

@Entity
public class AM {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long _id;

@ManyToOne
private LV lv;

public AM() {
}

}

持久性.xml

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="pul" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.sqlite.JDBC" />
<!-- url is set during runtime -->
<!-- <property name="javax.persistence.jdbc.url" value="jdbc:sqlite:sample.db"
/> -->
<property name="javax.persistence.jdbc.user" value="" />
<property name="javax.persistence.jdbc.password" value="" />

<!-- EclipseLink should create the database schema automatically -->
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
</properties>
</persistence-unit>
</persistence>

pom.xml 依赖

    <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.8.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.0-M3</version>
</dependency>

最佳答案

正如 Boann 所做的那样,我尝试运行您的代码(为您尚未显示 (LV, AbstractModule) 代码的类填写简单实现并初始化 lv),我得到了预期的结果:

2
before:short2
2
in map:short2, in map:short1
short2, short1
2

因此,我的假设是问题不在您在此处显示的代码中,而是在 LV 或 AbstractModule 的代码中,或者您可能没有导入您认为是的类。最后,我是否可以假设没有其他正在运行的线程可能会更改 ams 集合?

为了比较,这是我对您的类的虚拟实现。

抽象模块:

public class AbstractModule {

String kurzbezeichnung;

public AbstractModule(String desc) {
this.kurzbezeichnung = desc;
}

public String getKurzbezeichnung() {
return this.kurzbezeichnung;
}

}

LV:

public class LV {
HashSet<AbstractModule> ams;

public LV(HashSet<AbstractModule> abstractModules) {
this.ams = abstractModules;
}

public Collection<AbstractModule> getAbstractModules() {
return ams;
}
}

初始化:

HashSet<AbstractModule> initialAms = new HashSet<AbstractModule>();
AbstractModule short1 = new AbstractModule("short1");
AbstractModule short2 = new AbstractModule("short2");
initialAms.add(short2);
initialAms.add(short1);
LV lv = new LV(initialAms);

编辑:

在看到您更新的问题并意识到所有这些类实际上都是持久数据库实体之后,我认为问题可能是由于延迟加载引起的。我可以建议您将 ams 的定义更改为

@OneToMany(mappedBy = "lv", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Collection<AM> ams = new HashSet<AM>();

从下面的讨论中可以看出,EclipseLink 将 ams 集合实现为 org.eclipse.persistence.indirection.IndirectSet,这是一个延迟加载的实现。但是那个类没有实现 stream() 方法。

正如 OP 所指出的,有一个针对 EclipseLink 的错误报告来修复此问题:https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075

关于合并 myMap 后的 java 8 lambda myMap.stream().count() != myMap.size(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27107595/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com