簡體   English   中英

帶有@OneToMany的隨機LazyInitializationException

[英]Random LazyInitializationException with @OneToMany

我有一個具有以下表的舊數據庫:

Police
 id (PK)
 data...

Contract
 id(PK)
 version(PK)
 type


Code
 tab(PK)
 code(PK)
 name

我有一個JPA實體警察

@Entity
public class Police implements Serializable {


@Id
private long id

@OneToMany(fetch = FetchType.LAZY)
@JoinColumns(value = { @JoinColumn(name = "id", referencedColumnName = "id") })
private Set<Contract> contracts;

}

合同實體看起來像這樣:

@Entity
public class Contract implements Serializable {


@Id
private long id;

@Id
private long version;


private String type;



@OneToMany(fetch = FetchType.LAZY)
@JoinColumns({ @JoinColumn(name = "code", referencedColumnName = "type") })
@Where(clause = "tab = 'Type'")
private Set<Code> type;
}

碼:

@Entity
public class Code implements Serializable {


    @Id
    private String tab;
    @Id
    private String code;

    private String name;
}

在代碼表中,有許多用於不同應用程序的不同鍵/值。 在我的情況下,我需要一個,其中“ tab ='Type'”和代碼=我合同中的類型。

我的問題是,如果我與警察有多個合同,我會隨意嗎? 獲取org.hibernate.LazyInitializationException。

在我的測試用例中,我執行以下操作:

public static void main(String[] args) {

    int countErrors = 0;

    for (int i = 0; i < 15; i++) {
        try {
            readPolice();
        } catch (Exception e) {
            e.printStackTrace();
            countErrors++;
        }
    }

    System.err.println("errors: " + countErrors);

}

private static void readPolice() throws Exception {
  EntityManagerFactory factory =     EntityManagerFactoryHelper.getFactory(PersistenceUnitsEnum.TEST_STAGE);
  EntityManager em = factory.createEntityManager();
  TypedQuery<Police> namedQuery = em.createNamedQuery(...);
  Police result = namedQuery.getSingleResult();
  Set<Contract> contracts = result.getContract();
  Contract contract = contracts.iterator().next();
  Set<Code> type = contract.getType(); //should be a set with one Entry

  System.out.println(type.size()); //<--- Chance for Exception!!
  em.close();
}

我將整個過程循環嘗試15次。 在大約5-8次嘗試中,我得到了LazyInitializationException。 其他時間它起作用。

有什么想法嗎? 為什么它不會一直失敗?

剛遇到這個。 關鍵字是“隨機”。 我的一位同事在她的筆記本電腦上始終遇到這種異常,而我從未遇到過。 她只能在IE&Edge上重現異常。

最終意識到它與Tomcat版本有關。 她運行的是舊版本,而我的運行是8.5.8。 她將本地Tomcat升級到此版本,並且不再遇到例外。

確保帶有println的代碼在事務中。

LazyInitializationException意味着您已在某個事務中加載了實體,退出該實體,然后嘗試使用此實體的某些延遲加載的屬性。

由於您的整個代碼不在此處,因此我假設您的姓名查詢並不總是返回相同的實體,並且當返回的實體包含某些Code它將引發錯誤。

您的交易必須關閉,否則您將不會收到懶惰的初始化問題。

您應該檢查EntityManagerFactory的創建僅執行一次。 例如:

public static void main(String[] args) {
  EntityManagerFactory emf = EntityManagerFactoryHelper.getFactory(PersistenceUnitsEnum.TEST_STAGE);
  for (int i = 0; i < 15; i++) {
    readPolice(emf);
  }
}

private static void readPolice(EntityManagerFactory emf) throws Exception {
  EntityManager em = emf.createEntityManager();
  ...
}

如果您在EntityManagerFactoryHelper.getFactory()使用某種單例模式,請確保它是線程安全的。

您也可以嘗試通過調用em.getTransaction().begin()em.getTransaction().commit()readPolice()包裝在事務中。 例如:

private static void readPolice(EntityManagerFactory emf) throws Exception {
   EntityManager em = emf.createEntityManager();
   em.getTransaction().begin();
   ...
   em.getTransaction().commit();
   em.close();
}

如果我在Contract實體中覆蓋了equals / hashcode,它將起作用。 為什么問題是隨機發生的...我不明白...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM