Я создаю приложение с Hibernate JPA, и я использую c3p0 для объединения пулов с MySQL. У меня проблема с количеством подключений к базе данных MySQL, поскольку она попадает в 152 открытых соединения, это не требуется, поскольку я определяю в моем конфигурационном файле c3p0 максимальный размер пула до 20 и, конечно же, я закрываю каждый менеджер объектов, который я получаю из EntityManagerFactory
после совершения каждой транзакции.
За каждый раз, когда выполняется контроллер, я замечаю, что открыто более 7 подключений, и если я обновляюсь, то 7 подключений снова открываются без закрытия закрытых прошлых подключений. И в каждой функции DAO, которую я вызываю, выполняется em.close(). Я признаю, что проблема в моем коде, но я не знаю, что я делаю неправильно здесь.
Это объект Sondage.java:
@Entity
@NamedQuery(name="Sondage.findAll", query="SELECT s FROM Sondage s")
public class Sondage implements Serializable {
private static final long serialVersionUID = 1L;
public Sondage() {}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private byte needLocation;
//bi-directional many-to-one association to ResultatSondage
@OneToMany(mappedBy = "sondage", cascade = CascadeType.ALL)
@OrderBy("sondage ASC")
private List<ResultatSondage> resultatSondages;
//bi-directional many-to-one association to SondageSection
@OneToMany(mappedBy = "sondage", cascade = CascadeType.ALL)
private List<SondageSection> sondageSections;
}
И вот мой класс DAO:
@SuppressWarnings("unchecked")
public static List<Sondage> GetAllSondage() {
EntityManager em = PersistenceManager.getEntityManager();
List<Sondage> allSondages = new ArrayList<>();
try {
em.getTransaction().begin();
Query query = em.createQuery("SELECT s FROM Sondage s");
allSondages = query.getResultList();
em.getTransaction().commit();
} catch (Exception ex) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
allSondages = null;
} finally {
em.close();
}
return allSondages;
}
Как видите, em
закрывается. В моем JSP я делаю это: я знаю, что это не лучший способ сделать что-то в стороне зрения.
<body>
<div class="header">
<%@include file="../../../Includes/header.jsp" %>
</div>
<h2 style="color: green; text-align: center;">الاستمارات</h2>
<div id="allsurveys" class="pure-menu custom-restricted-width">
<%
List<Sondage> allSondages = (List<Sondage>) request.getAttribute("sondages");
for (int i = 0; i < allSondages.size(); i++) {
%>
<a href="${pageContext.request.contextPath }/auth/dosurvey?id=<%= allSondages.get(i).getId()%>"><%= allSondages.get(i).getName()%></a>
<%
if (request.getSession().getAttribute("user") != null) {
Utilisateur user = (Utilisateur) request.getSession().getAttribute("user");
if (user.getType().equals("admin")) {
%>
<a href="${pageContext.request.contextPath }/aauth/editsurvey?id=<%= allSondages.get(i).getId()%>">تعديل</a>
<%
}
}
%>
<br />
<%
}
%>
</div>
</body>
Я предполагаю, что каждый раз, когда я звоню user.getType()
, устанавливается запрос? Если да, как я могу это предотвратить?
Для конфигурационного файла c4p0 я включил его в файл persistence.xml, я увидел несколько сообщений, в которых говорится, что мне нужно поставить конфигурационный файл c3p0 в c3p0-config.xml, но с моей настройкой c3p0 инициализируется значениями, которые я передаю в файле persistence.xml также соединения mysql достигают 152 соединений, а maxpoolsize
- в 20, здесь файл persistence.xml
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="CAOE" transaction-type="RESOURCE_LOCAL">
<class>com.caoe.Models.ChoixQuestion</class>
<class>com.caoe.Models.Question</class>
<class>com.caoe.Models.Reponse</class>
<class>com.caoe.Models.ResultatSondage</class>
<class>com.caoe.Models.Section</class>
<class>com.caoe.Models.Sondage</class>
<class>com.caoe.Models.SondageSection</class>
<class>com.caoe.Models.SousQuestion</class>
<class>com.caoe.Models.Utilisateur</class>
<properties>
<property name="hibernate.connection.provider_class"
value=" org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/caoe?useUnicode=yes&characterEncoding=UTF-8"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.c3p0.max_size" value="50" />
<property name="hibernate.c3p0.min_size" value="3" />
<property name="hibernate.c3p0.max_statements" value="20" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="30" />
<property name="hibernate.c3p0.timeout" value="35" />
<property name="hibernate.c3p0.checkoutTimeout" value="60000" />
<property name="hibernate.connection.release_mode" value="after_statement" />
<property name="debugUnreturnedConnectionStackTraces"
value="true" />
</properties>
</persistence-unit>
</persistence>
EDIT: я развертываю приложение на сервере Red Hat с Tomcat и MySQL Installed. Мне просто интересно, почему Hibernate открывает слишком много связей с MySQL, при этом все руководители сущностей закрыты, соединение не останется открытым, но это не так. Я догадываюсь и исправляю, если я прав, что соединения открываются, когда я делаю что-то вроде этого:
List<Sondage> allSondages = SondageDao.getAllSondages();
for (Sondage sondage : allSondages) {
List<Question> questions = sondage.getQuestions();
//code to display questions for example
}
Здесь, когда я использую sondage.getQuestions()
, Hibernate открывает соединение с базой данных и не закрывает его после этого, я что-то пропускаю в файле конфигурации, который закрывает или возвращает соединение с пулом, когда это делается с ним. Заранее благодарим за любую помощь.
EDIT2: Поскольку люди просят версии, вот они: JAVA jre 1.8.0_25 Apache Tomcat v7.0 Зимуют-ядро-4.3.10 hibernate c3p0 4.3.10.финал hibernate-jpa 2.1 Спасибо заранее
Версия mysql - это Mysql 5.6.17, если это может помочь...
EDIT 4: по мере того, как люди путаются с версией кода, которую я опубликовал, я ошибаюсь, позвольте мне изменить это, чтобы вы знали, что именно происходит:
Сначала я начну с отображения кода ошибки, так как вам, ребята, все равно, что работает:
@SuppressWarnings("unchecked")
public static List<Sondage> GetAllSondage() {
EntityManager em = PersistenceManager.getEntityManager();
List<Sondage> allSondages = new ArrayList<>();
try {
em.getTransaction().begin();
Query query = em.createQuery("SELECT s FROM Sondage s");
allSondages = query.getResultList();
em.getTransaction().commit();
} catch (Exception ex) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
allSondages = null;
} finally {
em.close();
}
return allSondages;
}
Итак, это в основном то, что я сделал для всех своих функций dao, я знаю, что транзакция здесь не нужна, так как я видел вопросы, указывающие на то, что транзакции важны для подключения к закрытию. кроме этого, я получаюEntityManager из класса PersistenceManager, который имеет объект Singleity Object EntityManagerFactory, поэтому getEntityManager создает entityManager из одноэлементного объекта EntityManagerFactory. Object: = > код лучше 1000 слов: PesistenceManager.java:
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class PersistenceManager
{
private static EntityManagerFactory emf = null;
public static EntityManager getEntityManager()
{
return getEntityManagerFactory().createEntityManager();
}
public static EntityManagerFactory getEntityManagerFactory()
{
if(emf == null) {
emf = Persistence.createEntityManagerFactory("CAOE");
return emf;
}
else
return emf;
}
}
Да, это круто и все хорошо, но где проблема?
Проблема заключается в том, что эта версия открывает соединения и никогда не закрывает их, em.close() не имеет никакого эффекта, он держит соединение открытым для базы данных.
Исправление noob:
Что я сделал, чтобы исправить эту проблему, так это создать EntityManagerFactory для каждого запроса, это значит, что dao выглядит примерно так:
@SuppressWarnings("unchecked")
public static List<Sondage> GetAllSondage() {
//this is the method that return the EntityManagerFactory Singleton Object
EntityManagerFactory emf = PersistenceManager.getEntitManagerFactory();
EntityManager em = emf.createEntityManager();
List<Sondage> allSondages = new ArrayList<>();
try {
em.getTransaction().begin();
Query query = em.createQuery("SELECT s FROM Sondage s");
allSondages = query.getResultList();
em.getTransaction().commit();
} catch (Exception ex) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
allSondages = null;
} finally {
em.close();
emf.close();
}
return allSondages;
}
Теперь это плохо, и я просто сохраню его, пока у меня нет ответа на этот вопрос (похоже, это forver: D). Таким образом, с этим кодом в основном все соединения закрываются после того, как спящий режим им не нужен. Заранее благодарю за любые усилия, поставленные вами в этом вопросе:)