Прежде всего, я не знаю, является ли это лучшим заголовком, чтобы объяснить, в чем моя проблема, но здесь мы идем: у меня есть класс под названием 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
, чтобы получить текущую цену на продукт. Это работает нормально несколько раз, но после вызова его как 10x, похоже, что транзакции все еще открыты, потому что я получаю это исключение (я предполагаю, что это специфично для PostgreSQL): ERROR: FATAL: remaining connection slots are reserved for non-replication superuser connections
.
Я пробовал этот подход: создавал экземпляр ProductPriceHistoryDaoImpl productPriceHistoryDaoImpl
, открывая транзакцию и закрывая ее ВНЕ кода, который вызывает getPrice()
, и просто передайте его по параметру, чтобы вызвать запрос, и это работает отлично (слоты не перегружены, как в 1-м подход), но мне не нравится этот подход, потому что я использую getPrice()
внутри .jsp
страниц, и я не могу передать 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();
}
(...)
}