0

我正在使用Google Cloud SQL的應用程序。我正在使用Hibernate 4.2.0.Final,並且我注意到,在閒置8小時後,我的連接已關閉。我一直在互聯網上搜索,找不到有效解決這個問題的東西。我發現的所有信息總結如下:如何解決Google CloudSQL 8小時超時?

  • 使用連接池,我應該指定更高的超時時間。我已經嘗試過c3p0和DBCP 2.1.1庫,但他們都沒有解決這個問題。
  • 在某個查詢之前打開一個連接,然後關閉它。問題是我想使用EntityManager爲了使用實體查詢。

這裏是我用DBCP 2.1.1(http://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2/2.1.1)所做的。問題是,當我嘗試在我的PersistenceService中嘗試使用findAll時,Goggle App Engine日誌顯示ExceptionInInitializerError。日誌還顯示我的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(); 
    } 
} 

這是我對MySQL連接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

添加autoReconnect=true選項。最簡單的方法是將其添加到連接URL本身:

persistence.db.url=jdbc:mysql://x.x.x.x:3306/y?autoReconnect=true 
0

8個小時空閒的連接超時來自MySQL服務器,而不是客戶端,因此更改客戶端上超時不會做太大。通過更改wait_timeout標誌,可以在服務器上調整此設置。 8小時是默認值。

您應該將連接池配置爲在一段時間後自動刪除空閒連接。在DBCP中,您可以通過timeBetweenEvictionRunsMillis選項啓用空閒連接驅逐器。

0

添加一點到Vadim的答案,在CloudSQL上,您可以通過雲控制檯編輯實例設置標誌。在Google上,您不能通過運行諸如SET GLOBAL wait_timeout=60;之類的東西來實現此目的,因爲它不支持SUPER權限。

我花了一段時間才找到這個,所以我想它可能會幫助其他人在這裏添加它。