java - Google Cloud SQL - 无法连接到 MySQL 数据库
问题描述
我正在尝试使用 Java 和 HikariConfig API(如 Google 教程中所示)连接到托管在 Google Cloud Platform 上的 MySQL 数据库。我正在 Eclipse 中构建我的代码,但尽管做了我能想到的一切,但我的连接不起作用。我可以使用 Mysql 工作台(使用公共 api)和使用 localhost(代替 Google App Engine)连接到同一个数据库。我想我的项目中缺少一个 jar 文件。我正在添加我的 jar 库的代码和屏幕截图。
我得到的错误如下:
java.lang.AbstractMethodError: Method com/google/cloud/sql/mysql/SocketFactory.connect(Ljava/lang/String;ILcom/mysql/cj/conf/PropertySet;I)Ljava/io/Closeable; is abstract
at com.google.cloud.sql.mysql.SocketFactory.connect (SocketFactory.java)
at com.mysql.cj.protocol.a.NativeSocketConnection.connect (NativeSocketConnection.java:65)
at com.mysql.cj.NativeSession.connect (NativeSession.java:152)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly (ConnectionImpl.java:955)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO (ConnectionImpl.java:825)
at com.mysql.cj.jdbc.ConnectionImpl.<init> (ConnectionImpl.java:455)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance (ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect (NonRegisteringDriver.java:199)
at com.zaxxer.hikari.util.DriverDataSource.getConnection (DriverDataSource.java:117)
at com.zaxxer.hikari.util.DriverDataSource.getConnection (DriverDataSource.java:123)
at com.zaxxer.hikari.pool.PoolBase.newConnection (PoolBase.java:365)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry (PoolBase.java:194)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry (HikariPool.java:460)
at com.zaxxer.hikari.pool.HikariPool.checkFailFast (HikariPool.java:534)
at com.zaxxer.hikari.pool.HikariPool.<init> (HikariPool.java:115)
at com.zaxxer.hikari.HikariDataSource.<init> (HikariDataSource.java:81)
at com.x.d3sols.web.ConnectionPoolContextListener.createConnectionPool (ConnectionPoolContextListener.java:51)
at com.x.d3sols.web.ConnectionPoolContextListener.contextInitialized (ConnectionPoolContextListener.java:71)
at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized (ContextHandler.java:843)
at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized (ServletContextHandler.java:533)
at org.eclipse.jetty.server.handler.ContextHandler.startContext (ContextHandler.java:816)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext (ServletContextHandler.java:345)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp (WebAppContext.java:1406)
at com.google.apphosting.runtime.jetty9.AppEngineWebAppContext.startWebapp (AppEngineWebAppContext.java:175)
at org.eclipse.jetty.webapp.WebAppContext.startContext (WebAppContext.java:1368)
at org.eclipse.jetty.server.handler.ContextHandler.doStart (ContextHandler.java:778)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart (ServletContextHandler.java:262)
at org.eclipse.jetty.webapp.WebAppContext.doStart (WebAppContext.java:522)
at com.google.apphosting.runtime.jetty9.AppEngineWebAppContext.doStart (AppEngineWebAppContext.java:120)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start (AbstractLifeCycle.java:68)
at com.google.apphosting.runtime.jetty9.AppVersionHandlerMap.createHandler (AppVersionHandlerMap.java:240)
at com.google.apphosting.runtime.jetty9.AppVersionHandlerMap.getHandler (AppVersionHandlerMap.java:178)
at com.google.apphosting.runtime.jetty9.JettyServletEngineAdapter.serviceRequest (JettyServletEngineAdapter.java:120)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchServletRequest (JavaRuntime.java:722)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchRequest (JavaRuntime.java:685)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run (JavaRuntime.java:655)
at com.google.apphosting.runtime.JavaRuntime$NullSandboxRequestRunnable.run (JavaRuntime.java:847)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run (ThreadGroupPool.java:270)
at java.lang.Thread.run (Thread.java:748)
这对我来说非常重要,任何帮助都将不胜感激。谢谢 :)
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
/**
* Servlet implementation class ConnectionPoolContextListener
*/
@WebListener("Creates a connection pool that is stored in the Servlet's context for later use.")
public class ConnectionPoolContextListener implements ServletContextListener {
// Saving credentials in environment variables is convenient, but not secure - consider a more
// secure solution such as https://cloud.google.com/kms/ to help keep secrets safe.
private static final String DB_USER = "<user>";
private static final String DB_PASS = "<password>";
private static final String CLOUD_SQL_CONNECTION_NAME = "<Connection_Name>";
private static final String DB_NAME = "<DB_Name>";
private DataSource createConnectionPool() {
// [START cloud_sql_mysql_servlet_create]
// The configuration object specifies behaviors for the connection pool.
HikariConfig config = new HikariConfig();
//For Localhost - IT WORKS
/*String url = "jdbc:mysql://<IP_Address>/<DB_NAME>";
config.setJdbcUrl(url);
config.setUsername(DB_USER);
config.setPassword(DB_PASS);
config.setDriverClassName("com.mysql.jdbc.Driver");
config.addDataSourceProperty("useSSL", "false");*/
//For APP ENGINE - IT DOESNT WORKS
String url = "jdbc:mysql://google/<DB_NAME>";
config.setJdbcUrl(url);
config.setUsername(DB_USER);
config.setPassword(DB_PASS);
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);
config.addDataSourceProperty("useSSL", "false");
config.setDriverClassName("com.mysql.jdbc.Driver");
config.setMaximumPoolSize(5);
config.setMinimumIdle(5);
config.setConnectionTimeout(60000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000); // 30 minutes
DataSource pool = new HikariDataSource(config);
return pool;
}
@Override
public void contextDestroyed(ServletContextEvent event) {
// This function is called when the Servlet is destroyed.
HikariDataSource pool = (HikariDataSource) event.getServletContext().getAttribute("my-pool");
if (pool != null) {
pool.close();
}
}
@Override
public void contextInitialized(ServletContextEvent event) {
// This function is called when the application starts and will safely create a connection pool
// that can be used to connect to.
DataSource pool = (DataSource) event.getServletContext().getAttribute("my-pool");
if (pool == null) {
pool = createConnectionPool();
event.getServletContext().setAttribute("my-pool", pool);
}
}
}
解决方案
我终于在评论的帮助下设法解决了这个问题。显然,我添加的 appengine-web.xml 文件中缺少一个字符串,它得到了修复。我还替换了类路径中的一些 jar 文件。
appengine-web.xml 中要添加的字符串是:
<use-google-connector-j>true</use-google-connector-j>
您的库将如下所示:
请注意您使用的所有库的版本,我使用的是 v8。为此,除 Gson 之外的所有库都是必需的。
推荐阅读
- c++ - c ++:程序崩溃,参数(按值)传递给lambda
- javascript - ngClass 不会根据变量值改变颜色
- ruby-on-rails - Rails 选择选项根据另一个选择动态变化(没有 ajax)
- parity - 获取最终区块数据
- spring - Spring Boot 谷歌云秘密管理器
- html - Blazor 双向绑定
- hive - Hive SQL - 在没有 `chr()` 的情况下测试 \u0000 (ascii 00)
- airflow - Airflow dag 未按计划运行(而其他计划同时运行)?
- c# - 从控制器操作返回 File(MemoryStream) 时出现内部 nlog 异常
- algorithm - 非退化多边形输出的 Sutherland-Hodgman 算法变体