我正在努力让我的数据库与我的Java程序对话。

有人能给我一个使用JDBC的快速而简单的示例程序吗?

我得到了一个相当大的错误

Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 
    The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1122)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2260)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:787)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:49)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:357)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285)
    at java.sql.DriverManager.getConnection(DriverManager.java:582)
    at java.sql.DriverManager.getConnection(DriverManager.java:207)
    at SqlTest.main(SqlTest.java:22)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
    The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1122)
    at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:344)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2181)
    ... 12 more
Caused by: java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
    at java.net.Socket.connect(Socket.java:529)
    at java.net.Socket.connect(Socket.java:478)
    at java.net.Socket.<init>(Socket.java:375)
    at java.net.Socket.<init>(Socket.java:218)
    at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:256)
    at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:293)
    ... 13 more

测试文件内容:

import com.mysql.jdbc.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SqlTest {

    public static void main(String [] args) throws Exception {
        // Class.forName( "com.mysql.jdbc.Driver" ); // do this in init
        // // edit the jdbc url 
        Connection conn = DriverManager.getConnection( 
            "jdbc:mysql://localhost:3306/projects?user=user1&password=123");
        // Statement st = conn.createStatement();
        // ResultSet rs = st.executeQuery( "select * from table" );

        System.out.println("Connected?");
    }
}

当前回答

如果Java试图通过SSL连接MySQL,但出现了错误,也可能发生此错误。(在我的例子中,我将Payara Server 5.193.1连接池配置为MySQL。)

有人建议设置useSSL=false。但是,由于Connector/J版本8.0.13,该设置已弃用。下面是MySQL连接器/J 8.0配置属性的摘录:

sslMode By default, network connections are SSL encrypted; this property permits secure connections to be turned off, or a different levels of security to be chosen. The following values are allowed: DISABLED - Establish unencrypted connections; PREFERRED - (default) Establish encrypted connections if the server enabled them, otherwise fall back to unencrypted connections; REQUIRED - Establish secure connections if the server enabled them, fail otherwise; VERIFY_CA - Like REQUIRED but additionally verify the server TLS certificate against the configured Certificate Authority (CA) certificates; VERIFY_IDENTITY - Like VERIFY_CA, but additionally verify that the server certificate matches the host to which the connection is attempted. This property replaced the deprecated legacy properties useSSL, requireSSL, and verifyServerCertificate, which are still accepted but translated into a value for sslMode if sslMode is not explicitly set: useSSL=false is translated to sslMode=DISABLED; {"useSSL=true", "requireSSL=false", "verifyServerCertificate=false"} is translated to sslMode=PREFERRED; {"useSSL=true", "requireSSL=true", "verifyServerCertificate=false"} is translated to sslMode=REQUIRED; {"useSSL=true" AND "verifyServerCertificate=true"} is translated to sslMode=VERIFY_CA. There is no equivalent legacy settings for sslMode=VERIFY_IDENTITY. Note that, for ALL server versions, the default setting of sslMode is PREFERRED, and it is equivalent to the legacy settings of useSSL=true, requireSSL=false, and verifyServerCertificate=false, which are different from their default settings for Connector/J 8.0.12 and earlier in some situations. Applications that continue to use the legacy properties and rely on their old default settings should be reviewed. The legacy properties are ignored if sslMode is set explicitly. If none of sslMode or useSSL is set explicitly, the default setting of sslMode=PREFERRED applies. Default: PREFERRED Since version: 8.0.13

因此,在我的例子中,设置sslMode=DISABLED就是解决这个问题所需要的全部内容。 这是在一台测试机器上。但是对于生产环境,安全解决方案应该正确配置Java客户机和MySQL服务器以使用SSL。


注意,通过禁用SSL,您可能还必须设置allowPublicKeyRetrieval=true。(同样,从安全角度来看,这不是一个明智的决定)。进一步的信息提供在MySQL ConnectionString选项:

AllowPublicKeyRetrieval If the user account uses sha256_password authentication, the password must be protected during transmission; TLS is the preferred mechanism for this, but if it is not available then RSA public key encryption will be used. To specify the server’s RSA public key, use the ServerRSAPublicKeyFile connection string setting, or set AllowPublicKeyRetrieval=True to allow the client to automatically request the public key from the server. Note that AllowPublicKeyRetrieval=True could allow a malicious proxy to perform a MITM attack to get the plaintext password, so it is False by default and must be explicitly enabled.

其他回答

在我的例子中,我需要将Localhost替换为实际的数据库服务器IP地址

而不是

 Connection con = DriverManager.getConnection(
 "jdbc:mysql://localhost:3306/DBname", "root", "root");

我需要

 Connection con = DriverManager.getConnection(
 "jdbc:mysql://192.100.0.000:3306/DBname", "root", "root");

如果您更改了端口,则会得到这种错误"com.mysql.jdbc.exceptions.jdbc4 "。CommunicationsException:通信链路故障 请检查你的端口号

如果有任何读者在访问远程服务器时遇到此问题:请确保端口是打开的

这com.mysql.jdbc.exceptions.jdbc4。如果数据库连接长时间空闲,将发生CommunicationsException异常。

这个空闲连接在connection. isclosed()上返回true;但如果我们尝试执行语句,它就会触发这个异常,所以我建议使用数据库池。

我解决了两件事: 1. 使用以下connads创建非root的新用户:

CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost';
FLUSH PRIVILEGES;

2. 注释mysqld.conf中的IP地址行

然后用新的用户名和密码连接。它应该会起作用。