Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate 即使在提交和关闭后,交易仍处于打开状态_Hibernate_Postgresql_Transactions - Fatal编程技术网

Hibernate 即使在提交和关闭后,交易仍处于打开状态

Hibernate 即使在提交和关闭后,交易仍处于打开状态,hibernate,postgresql,transactions,Hibernate,Postgresql,Transactions,首先,我不知道这是否是解释我的问题的最佳标题,但现在我们开始:我有一个名为Product的类,它在ProductPriceHistory上有一个@OneToOne映射 @Entity(name = "product") public class Product { @Id @SequenceGenerator(name="seq_product", sequenceName="seq_product", allocationSize=1 ) @GeneratedValue

首先,我不知道这是否是解释我的问题的最佳标题,但现在我们开始:我有一个名为
Product
的类,它在
ProductPriceHistory
上有一个
@OneToOne
映射

@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中的特定异常):
错误:致命:剩余的连接插槽保留给非复制超级用户连接

我尝试过这种方法:实例化
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) {
        (...)
    }
}
公共类ProductPriceHistoryDaoImpl扩展了DefaultDaoImpl{
私有EntityManager em=HibernateManager.getEntityManager();
公共产品价格历史(){
super(ProductPriceHistory.class);
}
公共双getCurrentPriceByProductId(长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();
    }

    (...)
}
public抽象类DefaultDaoImpl{
私人实体管理者;
public void beginTx(){
em=HibernateManager.getEntityManager();
em.getTransaction().begin();
}
公共无效委员会(){
em.getTransaction().commit();
em.close();
}
(...)
}

我把它作为答案发布,因为我担心你得不到更好的答案。但请记住,我不是100%确定以下是否完全正确

Hibernate(包括其他JPA提供者)正在幕后管理一个抽象层,由创建的EntityManager使用。例如,在同一事务中可能有多个EntityManager。它至少有一部分是通过跟踪线程工作的

在您的例子中,您创建了一个新的EntityManager,同时可能在该线程中创建了另一个EntityManager,另外启动和提交事务并关闭EntityManager。我并不完全知道在这种情况下会发生什么,但你应该把它改成以下内容。 (我可能应该看看jpa规范对这种情况的说明,但我认为它没有直接涵盖)

对事务和线程的每个组合使用完全相同的EntityManager。这可能会使您自己管理变得复杂,这就是为什么越来越大的项目使用事务管理系统的原因。众所周知的例子是Spring和JavaEE。
如果你是wana,写下这个完整的管理者自己管理。有两个类可以方便地进行此操作。第一个是代理类,用于拦截调用并重定向到正确的实例。另一个是ThreadLocal,用于处理每线程状态

一个简单的想法-在
DefaultDaoImpl
方法中添加一些日志记录,以确认您的方法确实按照预期被调用

第二个观察结果是,您可能需要提供一些关于(jdbc?)驱动程序的信息:您使用的是池连接吗?你考虑过用一个吗?另外-为什么不修改您的价格DOA以获取一组项目-然后您可以为10个项目使用一个连接,而不是为每个项目使用10个连接