2014-11-24 27 views
3

編輯後myMap.size():我發現這個beeing蝕環節的錯誤:https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075的Java 8拉姆達myMap.stream()數()=合併MYMAP

原題:

在一個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; 
    } 

} 

AM:

@Entity 
public class AM { 

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

    @ManyToOne 
    private LV lv; 

    public AM() { 
    } 

} 

的persistence.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> 
+0

知道的'lv.getAbstractModules類型()'和'getKurzbezeichnung()'可能的幫助。 – Eran 2014-11-24 14:59:24

+2

當我使用這些方法名稱設置虛擬類時,您的確切代碼適用於我(在列表中顯示一致的項目數)。所以我只能建議你的'lv.getAbstractModules()'方法不會隨着時間的推移返回相同的列表。 – Boann 2014-11-24 15:00:31

+0

你有沒有機會使用自定義'List'實現,可能有一個'stream()'方法壞了? – Boann 2014-11-24 15:05:37

回答

2

由於Boann這樣做,我試圖運行你的代碼(在類的簡單實現填充您還沒有表現出對碼(LVAbstractModule)和初始化lv),我得到預期的結果:

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

所以,我的假設是問題不在於此處顯示的代碼中,而是在LV或AbstractModule的代碼中,或者您沒有導入您認爲是的類。最後,我可以假設沒有其他線程在運行,可能會改變ams集合嗎?

爲了比較,這是我的虛擬類實現。

AbstractModule:

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); 

EDIT

在看到您更新的問題並意識到所有這些類實際上都是持久性數據庫實體後,我認爲問題可能是由於延遲加載導致的。我可以建議你改變你的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一個bug報告,此問題得到解決:https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075

+0

謝謝你的回覆!沒有其他線程正在運行。原始類基本上是POJO,並標記爲由JPA/eclipselink管理的實體。我也編寫了傻瓜,無法證實我的錯誤(基本上我實現了你所展示的那些假人)。因此,我認爲必須有另一部分影響行爲,但我無法追蹤它。但我發現,使用正常for循環工作正常。這根本沒有意義。所以我很困惑,並希望有人經歷類似的事情。 – Stuck 2014-11-26 09:42:41

+2

@Stuck Step-通過代碼進行調試,包括java.util類,以瞭解發生了什麼。如果不能解決問題,請複製項目,然後刪除部分,直到問題消失,創建最小代碼,然後將其複製到此處。 – Boann 2014-11-26 11:20:36

+2

對不起,我現在找時間給一個完整的例子(見第一篇文章更新) – Stuck 2014-11-26 12:06:17