2015-05-07 39 views
0

首先,我不知道這是否是解釋我的問題的最佳標題,但是我們在這裏:我有一個名爲Product的類,它具有@OneToOne映射ProductPriceHistory即使在提交併關閉之後,交易仍然會打開

@Entity(name = "product") 
public class Product { 
    @Id 
    @SequenceGenerator(name="seq_product", sequenceName="seq_product", allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_product") 
    private long id; 

    @Column(name="description", length=150) 
    private String description; 

    @OneToOne 
    private ProductPriceHistory price; 
    (...) 

    public double getPrice() { 
     double price = 0.0; 

     ProductPriceHistoryDaoImpl productPriceHistoryDaoImpl = new ProductPriceHistoryDaoImpl(); 

     try { 
      productPriceHistoryDaoImpl.beginTx(); 
      price = productPriceHistoryDaoImpl.getCurrentPriceByProductId(this.id); 
      productPriceHistoryDaoImpl.commitTx(); 
     } catch(Exception e) { 
      (...) 
     } 

     return price; 
    } 
} 

正如你可以在我的getPrice()方法看,我調用另一個Dao檢索當前價格的產品。這可以工作幾次,但調用它像10倍後,它看起來像交易仍然是開放的,因爲我得到這個異常(我想它是特定的從PostgreSQL):ERROR: FATAL: remaining connection slots are reserved for non-replication superuser connections

我試過這種方法:實例ProductPriceHistoryDaoImpl productPriceHistoryDaoImpl,打開事務和關閉它之外的調用getPrice(),只是它傳遞的參數來調用查詢,這完美的作品(槽沒有過載如一日的代碼方法),但我不喜歡這種方法,因爲我在.jsp頁面內使用getPrice(),在這種情況下我不能通過參數ProductPriceHistoryDaoImpl

添加一點點的代碼只是爲了更清晰

public class ProductPriceHistoryDaoImpl extends DefaultDaoImpl<ProductPriceHistory>{ 
    private EntityManager em = HibernateManager.getEntityManager(); 

    public ProductPriceHistory() { 
     super(ProductPriceHistory.class); 
    } 

    public double getCurrentPriceByProductId(long productId) { 
     (...) 
    } 
} 

DefaultDaoImpl.java

public abstract class DefaultDaoImpl<T> { 
    private EntityManager em; 

    public void beginTx() { 
     em = HibernateManager.getEntityManager(); 
     em.getTransaction().begin(); 
    } 

    public void commitTx() { 
     em.getTransaction().commit(); 
     em.close(); 
    } 

    (...) 
} 

回答

0

我張貼的答案,因爲我怕你沒有得到更好的回答。但請記住,我不是100%確定以下是完全正確的。 Hibernate(包括其他JPA提供者)在後臺管理一個抽象層,由創建的EntityManagers使用。例如,在同一個事務中可以有多個EntityManager。至少它的一部分是通過跟蹤線程工作的。

在你的情況下,你創建一個新的EntityManager,同時可能會創建另一個在該線程中創建的EntityManager,並且另外啓動提交事務並關閉EntityManager的&。在這種情況下發生的事情並不完全爲我所知,但您應該將其更改爲以下內容。 (我可能應該查看jpa規範說的那種情況,但我認爲它沒有直接覆蓋)

對於事務和線程的每個組合使用完全相同的EntityManager。這對您自己來說可能很複雜,這就是幾乎所有大型項目都使用事務管理系統的原因。衆所周知的例子是Spring和JavaEE。 如果你是wana編寫這個EntityManager自己管理。有兩個方便這樣做的類。第一個是Proxy類來攔截呼叫並重定向到正確的實例。另一個是用於處理每個線程狀態的ThreadLocal。

0

一個簡單的想法 - 將一些日誌記錄添加到您的DefaultDaoImpl方法中,以確認您的方法實際上是按照您的預期調用的。

第二個觀察結果是,您可能需要提供一些關於您的(jdbc?)驅動程序的信息:您是否使用池連接?你有沒有考慮過使用一個?另外 - 爲什麼不修改你的價格DOA來收集物品 - 然後你可以使用一個連接10個物品,而不是每個物品10個連接。