我正在使用Google Cloud SQL在应用中工作。我正在使用Hibernate 4.2.0.Final,我注意到在8小时不活动后我的连接已关闭。我一直在互联网上搜索,我找不到任何有效的方法来解决这个问题。我发现的所有信息都汇总在这些项目中:
这是我在DBCP 2.1.1(http://xx.xxx.xxx.xxx:8200/v1/post/wikipedia)中所做的。问题是,当我尝试在ExceptionInInitializerError
中使用findAll
时,Goggle App Engine日志会显示PersistenceService
。日志还显示我的DataSource
(见下文)无法转换为String
。我不明白为什么。
这是我现在正在使用的PersistenceService
package co.peewah.ems.utils;
import com.google.appengine.api.utils.SystemProperty;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.AbstractMap.SimpleEntry;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.hibernate.cfg.AvailableSettings;
/**
*
* @author Muacito
*/
public class PersistenceService
{
private static final EntityManagerFactory EMF = createEntityManagerFactory();
private static EntityManager entityManager = EMF.createEntityManager();
private static EntityManagerFactory createEntityManagerFactory()
{
//String mode = "";
/*
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Development)
{
mode = "dev.";
}
*/
Map<String, Object> properties = new HashMap<>();
//Properties properties = new Properties();
//properties.put("javax.persistence.jdbc.driver", System.getProperty("persistence." + mode + "db.driver"));
//properties.put("javax.persistence.jdbc.url", System.getProperty("persistence." + mode + "db.url"));
//properties.put("javax.persistence.jdbc.user", System.getProperty("persistence." + mode + "db.user"));
//properties.put("javax.persistence.jdbc.password", System.getProperty("persistence." + mode + "db.password"));
try
{
properties.put(AvailableSettings.DATASOURCE, DataSource.getInstance());
} catch (IOException | SQLException | PropertyVetoException e)
{
e.printStackTrace();
}
System.out.println("----------------------------");
System.out.println("----------------------------");
System.out.println(properties);
System.out.println("----------------------------");
System.out.println("----------------------------");
return Persistence.createEntityManagerFactory("Demo", properties);
}
private static EntityManager getEntityManager()
{
if (!PersistenceService.entityManager.isOpen())
{
PersistenceService.entityManager = PersistenceService.EMF.createEntityManager();
}
return PersistenceService.entityManager;
}
public static <T> void create(T entity)
{
try
{
if (entity.getClass().getMethod("getId").invoke(entity) == null)
{
entity.getClass().getMethod("setId", String.class).invoke(entity,
UUID.randomUUID().toString().replace("-", ""));
}
if (entity.getClass().getMethod("getCreated").invoke(entity) == null)
{
entity.getClass().getMethod("setCreated", Date.class).invoke(entity,
GregorianCalendar.getInstance().getTime());
}
getEntityManager().getTransaction().begin();
getEntityManager().persist(entity);
getEntityManager().flush();
getEntityManager().getTransaction().commit();
} catch (Exception ex)
{
Logger.getLogger(PersistenceService.class.getName()).log(Level.SEVERE, null, ex);
getEntityManager().getTransaction().rollback();
}
}
public static <T> void edit(T entity)
{
try
{
if (entity.getClass().getMethod("getUpdated").invoke(entity) == null)
{
entity.getClass().getMethod("setUpdated", Date.class).invoke(entity,
GregorianCalendar.getInstance().getTime());
}
getEntityManager().getTransaction().begin();
getEntityManager().merge(entity);
getEntityManager().flush();
getEntityManager().getTransaction().commit();
} catch (Exception ex)
{
Logger.getLogger(PersistenceService.class.getName()).log(Level.SEVERE, null, ex);
getEntityManager().getTransaction().rollback();
}
}
public static <T> void remove(T entity)
{
try
{
getEntityManager().getTransaction().begin();
getEntityManager().remove(entity);
getEntityManager().flush();
getEntityManager().getTransaction().commit();
} catch (Exception ex)
{
Logger.getLogger(PersistenceService.class.getName()).log(Level.SEVERE, null, ex);
getEntityManager().getTransaction().rollback();
}
}
public static <T> List<T> filter(Class<T> entityClass, String query, SimpleEntry<String, Object>... parameters)
{
TypedQuery<T> typedQuery = getEntityManager().createQuery(query, entityClass);
for (SimpleEntry<String, Object> param : parameters)
{
typedQuery.setParameter(param.getKey(), param.getValue());
}
return typedQuery.getResultList();
}
public static <T> T find(Class<T> entityClass, Object id)
{
T entity = getEntityManager().find(entityClass, id);
return entity;
}
public static <T> List<T> findBy(Class<T> entityClass, String criteria, Object value)
{
String c = criteria.replaceFirst(criteria.charAt(0) + "", (criteria.charAt(0) + "").toLowerCase());
TypedQuery<T> query = getEntityManager().createNamedQuery(entityClass.getSimpleName() + ".findBy" + criteria,
entityClass);
query.setParameter(c, value);
return query.getResultList();
}
public static <T> List<T> findAll(Class<T> entityClass)
{
CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public static <T> List<T> findRange(Class<T> entityClass, int[] range)
{
CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0] + 1);
q.setFirstResult(range[0]);
return q.getResultList();
}
public static <T> int count(Class<T> entityClass)
{
CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}
这是我的DataSource
package co.peewah.ems.utils;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
import com.google.appengine.api.utils.SystemProperty;
/**
*
* @author csacanam
*
*/
public class DataSource
{
private static DataSource datasource;
private BasicDataSource ds;
private DataSource() throws IOException, SQLException, PropertyVetoException
{
ds = new BasicDataSource();
String mode = "";
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Development)
{
mode = "dev.";
}
String user = System.getProperty("persistence." + mode + "db.user");
String password = System.getProperty("persistence." + mode + "db.password");
String address = System.getProperty("persistence." + mode + "db.url");
String driver = System.getProperty("persistence." + mode + "db.driver");
// Create and configure DBCP DataSource
ds.setDriverClassName(driver);
ds.setUrl(address);
ds.setUsername(user);
ds.setPassword(password);
ds.setMinIdle(5);
ds.setMaxIdle(20);
ds.setMaxOpenPreparedStatements(180);
}
public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException
{
if(datasource == null)
{
datasource = new DataSource();
}
return datasource;
}
public Connection getConnection() throws SQLException
{
return this.ds.getConnection();
}
}
答案 0 :(得分:0)
为mysql连接添加autoReconnect=true
选项。最简单的方法是将其添加到连接URL本身:
persistence.db.url=jdbc:mysql://x.x.x.x:3306/y?autoReconnect=true
答案 1 :(得分:0)
8小时空闲连接超时来自mysql服务器,而不是客户端,因此更改客户端上的超时时间不会太大。可以通过更改wait_timeout
标志在服务器上调整此设置。 8小时是默认值。
您应该将连接池配置为在一段时间后自动删除空闲连接。在DBCP中,您可以通过timeBetweenEvictionRunsMillis
选项启用空闲连接逐出器。
答案 2 :(得分:0)
在Vadim的答案中添加一点,在CloudSQL上,您可以通过云控制台Edit实例设置标志。在Google上,您无法通过运行类似SET GLOBAL wait_timeout=60;
的内容来执行此操作,因为它不支持SUPER权限。
我花了一段时间才找到这个,所以我想这可能会帮助其他人在这里添加它。