Я создаю приложение с Hibernate JPA, и я использую c3p0 для объединения пулов с MySQL. У меня проблема с количеством подключений к базе данных MySQL, поскольку она попадает в 152 открытых соединения, это не требуется, поскольку я определяю в моем конфигурационном файле c3p0 максимальный размер пула до 20 и, конечно же, я закрываю каждый менеджер объектов, который я получаю от EntityManagerFactory
после совершения каждой транзакции.Hibernate не освобождает соединения из пула соединений
За каждый раз, когда выполняется контроллер, я вижу, что открыто более 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 инициализируется значениями I передать в файле 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: Я развертывание приложения на красной шляпе с сервера Установлены Tomcat и MySQL. Мне просто интересно, почему 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 зимуют c3p0 4.3.10.final зимуют-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;
}
так что это в основном то, что я сделал для всех моих функций дао, я знаю, что сделка здесь не нужна, так как я видел вопросы, указывающие, что сделки являются важными для подключения к закрытию. кроме этого, я getEntityManager из PersistenceManager класса, который имеет EntityManagerFactory одноплодной объект, так getEntityManager создает EntityManager из EntityManagerFactory одноплодной Объект: => код лучше, чем 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() не имеет никакого эффекта, он держит соединение открытым для базы данных.
нуб фикс:
Что я сделал, чтобы исправить этот вопрос создать EntityManagerFactory для каждого запроса, это означает, что дао выглядит примерно так:
@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). Таким образом, с этим кодом в основном все соединения закрываются после того, как спящий режим им не нужен. Заранее благодарю за любые усилия, поставленные вами в этом вопросе :)
Заметил, что вы указываете режим выпуска в файле persistence.xml. Согласно этому документу: https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/transactions-connection-release.html это обычно плохой идеей. Возможно, это приведет к удалению этой строки конфигурации из вашего файла. Это больше в виде наблюдения и SWAG, чем ответа, поэтому я предлагаю это комментарий, а не ответ. –
Hi @MattCampbell, THANkS так много для ответа, я не делал этого в файле конфигурации, однако, когда я увидел свойство, которое у меня было, это может освободить некоторые подключения к пулу, но этого не произошло, поэтому ответ на ваши предположения , это не проблема. – Reda
Где и как вы получаете «Список», вызывая 'GetAllSondage()' в целевом DAO? Он доступен как атрибут HTTP-запроса на целевом JSP. Он уже выбран во включенном файле 'header.jsp' или где-то еще? –
Tiny