首先,我不知道这是否是解释我的问题的最佳标题,但我们走了:我有一个名为Product
的班级,其中有一个{{ 1}} @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()
来检索产品的当前价格。这样可以正常工作几次,但在调用它之后就像10x一样,看起来事务仍然是开放的,因为我得到了这个异常(我猜它是PostgreSQL特有的):Dao
。
我尝试过这种方法:实例化ERROR: FATAL: remaining connection slots are reserved for non-replication superuser connections
,打开事务并将其关闭到调用ProductPriceHistoryDaoImpl productPriceHistoryDaoImpl
的代码外面,然后通过参数传递它来调用查询,这很有效(插槽没有像第1种方法那样过载,但我不喜欢这种方法,因为我在getPrice()
页面内使用getPrice()
,我不能通过参数传递.jsp
这些案例。
添加更多代码只是为了更清楚
ProductPriceHistoryDaoImpl
DefaultDaoImpl.java
public class ProductPriceHistoryDaoImpl extends DefaultDaoImpl<ProductPriceHistory>{
private EntityManager em = HibernateManager.getEntityManager();
public ProductPriceHistory() {
super(ProductPriceHistory.class);
}
public double getCurrentPriceByProductId(long productId) {
(...)
}
}
答案 0 :(得分:0)
我发布它作为答案,因为我担心你没有得到更好的答案。但请记住,如果以下内容完全正确,我不能100%确定。
Hibernate(包括其他JPA提供者)正在幕后管理一个抽象层,由创建的EntityManagers使用。例如,可以在同一事务中拥有多个EntityManager。至少它的一部分是通过跟踪线程来工作的。
在您的情况下,您创建一个新的EntityManager,同时可能还有另一个在该线程中创建的并且另外启动&amp;提交事务并关闭EntityManager。在这种情况下发生的事情并不完全为我所知,但您应该将其更改为以下内容。 (我可能应该查看jpa规范对该案例的说法,但我认为它没有直接涵盖)
对事务和线程的每个组合使用完全相同的EntityManager。这可能很难自行管理,这就是几乎所有大型项目都使用事务管理系统的原因。众所周知的例子是Spring和JavaEE。 如果你是wana写这个EntityManager自己管理。有两个类可以方便地执行此操作。第一个是Proxy类来拦截调用并重定向到正确的实例。另一个是ThreadLocal,用于处理每线程状态。
答案 1 :(得分:0)
快速思考一下 - 在DefaultDaoImpl
方法中添加一些日志记录,以确认您的方法实际上是按预期调用的。
第二个观察结果是您可能需要提供有关您的(jdbc?)驱动程序的一些信息:您使用的是池化连接吗?你考虑过用过吗?另外 - 为什么不修改你的价格DOA来收集物品 - 然后你可以使用一个连接10个项目而不是每个项目10个连接。