Red*_*eda 22 java mysql hibernate jpa c3p0
我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)
这是我的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;
}
Run Code Online (Sandbox Code Playgroud)
如你所见,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>
Run Code Online (Sandbox Code Playgroud)
我猜每次打电话user.getType()
都会建立一个请求?如果是这样,我该如何防止这种情况?
对于c4p0配置文件,我将它包含在persistence.xml中,我看到几个帖子说我需要将c3p0配置文件放在c3p0-config.xml中,但是在我的设置中,c3p0被初始化为我在持久性中传递的值.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>
Run Code Online (Sandbox Code Playgroud)
编辑:我正在使用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
}
Run Code Online (Sandbox Code Playgroud)
在我使用的时候sondage.getQuestions()
,Hibernate是否打开了与数据库的连接并且之后没有关闭它,我错过了配置文件中关闭或返回池连接的东西.在此先感谢您的帮助.
EDIT2:由于人们要求版本,这里它们是:JAVA jre 1.8.0_25 Apache Tomcat v7.0 hibernate-core-4.3.10 hibernate c3p0 4.3.10.final hibernate-jpa 2.1在此先感谢
mysql版本是Mysql 5.6.17,如果这可以帮助...
编辑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;
}
Run Code Online (Sandbox Code Playgroud)
所以这基本上就是我为所有dao函数所做的事情,我知道这里不需要事务,因为我看到了一些问题,指出事务对于关闭连接很重要.除此之外,我从PersistenceManager类获取了EntityManager,它具有EntityManagerFactory单例对象,因此getEntityManager从EntityManagerFactory单例对象创建一个entityManager:=>代码优于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;
}
}
Run Code Online (Sandbox Code Playgroud)
是的,这很酷,一切都很好,但问题出在哪里?
这里的问题是这个版本打开连接并且从不关闭它们,em.close()没有效果,它保持连接对数据库开放.
菜鸟修复:
我为解决这个问题所做的是为每个请求创建一个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;
}
Run Code Online (Sandbox Code Playgroud)
现在这很糟糕,我会保留它而我没有回答这个问题(似乎是forver:D).所以使用这段代码基本上所有连接都在hibernate不需要它们之后关闭.在此问题中提出的任何努力都要提前感谢:)
Ale*_*nes 11
我认为Hibernate和C3P0在这里表现正常.事实上,您应该看到根据您的C3P0配置始终至少有三个连接到数据库.
当您执行查询时,Hibernate将使用池中的连接,然后在完成后返回它.它不会关闭连接.如果超过最小值并且某些连接超时,C3P0可能会缩小池.
在最后一个示例中,您会看到连接已关闭,因为您已关闭实体管理器工厂,因此也关闭了连接池.
你Persistence.createEntityManagerFactory("CAOE")
每次都打电话.这是错误的.每次调用createEntityManagerFactory
都会创建新的(独立的)连接池.您应该在某处缓存EntityManagerFactory对象.
编辑:
您还应该手动关闭EntityManagerFactory.你可以在@WebListener中完成:
@WebListener
public class AppInit implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {}
public void contextDestroyed(ServletContextEvent sce) {
PersistenceManager.closeEntityMangerFactory();
}
}
Run Code Online (Sandbox Code Playgroud)
否则,每次重新部署都是泄漏连接的来源.
小智 -4
看起来问题与Hibernate bug有关。请尝试在 OneToMany 注释中指定获取策略 EAGER。
@OneToMany(mappedBy = "sondage", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
39081 次 |
最近记录: |