java - Android Studio 中与 Azure 的 JDBC 连接失败

标签 java sql-server azure android-studio jdbc

所以我已经为此开/关奋斗了几天,感觉好像我已经用尽了所有相关的搜索词。首先我要说的是,我对此进行了大量研究,但毫无结果;我得出的结论是,这要么是非常异常的事情(不太可能),要么是我不知何故忽略了一些微小的细节。让我也立即说,是的,我知道直接从应用程序连接到数据库并不理想,我应该使用网络服务器,但就我的意图和目的而言,这个解决方案不是一个问题。

我知道这篇文章非常长,但我非常感谢大家的时间。如果不出意外的话,至少它可以帮助其他最近开始使用 JDBC 并开始遇到问题的人。 “我尝试过的方法”部分概述了您可以在网上找到的绝大多数可以尝试的方法。

我正在尝试做什么:

使用 JDBC 驱动程序,通过 Android Studio 连接到我的 Azure 托管的 SqlServer 数据库。

我遇到的错误:

W/System.err: com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host vet-to-go.database.windows.net, port 1433 has failed. Error: "Connection timed out: no further information. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".

我尝试/验证的内容(简短列表):

-连接代码发生在 Activity 类中,但它位于 AsyncTask 中。

-uses-permission android:name="android.permission.INTERNET"

-Azure 防火墙已配置为允许我的 IP 连接。

-Windows 防火墙已制定规则,允许端口 1433 上的传入和传出流量。

-从 SQLServer 配置管理器中,我启用了命名管道和 TCP/IP。在“IP 地址”选项卡上,我已启用所有端口并将 TCP 端口设置为 1433。已尝试使用和关闭 TCP 动态端口。

-已尝试使用 SQL Server Browser 运行和停止(另一篇文章提到这样做)。

-已尝试使用 jre7 和 jre8 JDBC 驱动程序。

-sourceCompatibility 和 targetCompatibility 在各自的 1_7 或 1_8 版本中设置。

-编译文件('libs/sqljdbc41.jar') [或 42 for jre8]

-更绝望的是,为了确保它们不是问题,在完全关闭 Windows 防火墙并允许任何 IP 通过 Azure 防火墙连接(起始/结束 IP 为 0.0.0.0 - 255.255)后,我也无法连接。 255.255)

-我可以 ping 和 telnet 到 (mydbname).database.windows.net 1433(DNS 和实际 IP)

考虑到上述所有内容,我只能假设错误发生在我的代码中的某个地方,但我绝对无法弄清楚在哪里。为了给棺材上钉上钉子,应该提到的是,我能够能够成功查询数据库并在我的项目中返回一个值,但仅在静态、非 Activity 类。当添加到实际 Activity 类时,几乎完全复制代码没有产生任何结果。

这是工作代码:

import java.sql.*;

public class DatabaseHelper {

public static void main(String[] args) throws Exception {
    String custID = "1";
    String connectionString = "jdbc:sqlserver://vet-to-go.database.windows.net:1433;database=Vet To Go DB;user=myLogin@vet-to-go;password=myPass;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;";
    String queryString = "SELECT FirstName, LastName FROM Tbl_Customer WHERE CustomerID = " + custID;

    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    Connection myConnection = DriverManager.getConnection(connectionString);
    Statement myStatement = myConnection.createStatement();
    ResultSet myResultSet = myStatement.executeQuery(queryString);

    myResultSet.next();
    String firstName = myResultSet.getString("FirstName");
    String lastName = myResultSet.getString("LastName");

    System.out.println(firstName);
    System.out.println(lastName);

    myStatement.close();
    myConnection.close();
}

}

我知道其中一些代码看起来很奇怪,这只是因为我希望将其合并到另一个类中。这是我最近的尝试(正如我提到的,我已经这样做了一段时间,所以我尝试了几种不同的组合)

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

import java.sql.*;

public class LandingPage extends AppCompatActivity {

TextView txtFirst, txtLast;
String firstName, lastName, customerID;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_landing_page);
    txtFirst = (TextView)findViewById(R.id.txtFirstName);
    txtLast = (TextView)findViewById(R.id.txtLastName);

    customerID = getIntent().getStringExtra("custID");

    new myAsyncTask(LandingPage.this).execute();

    txtFirst.setText(firstName);
    txtLast.setText(lastName);
}

public class myAsyncTask extends AsyncTask<Void, Void, String> {
    String connectionString = "jdbc:sqlserver://vet-to-go.database.windows.net:1433;database=Vet To Go DB;user=myLogin@vet-to-go;password=myPass;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;";
    String queryString = "SELECT FirstName, LastName FROM Tbl_Customer WHERE CustomerID = " + customerID;
    Context context;


    public myAsyncTask(Context context) {
        System.out.println("Async instantiated.");
        this.context = context;
    }
    protected void onPreExecute() {
        System.out.println("Pre-executing Async task.");
    }

    protected String doInBackground(Void... params) {
        try {
            System.out.println("Attempting to connect to DB...");
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            Connection con = DriverManager.getConnection(connectionString);
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(queryString);

            while (rs.next()) {
                System.out.println("Sorting through ResultSet...");
                firstName = rs.getString("FirstName");
                lastName = rs.getString("LastName");
            }

        } catch (SQLException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "Complete";
    }

    protected void onPostExecute(String result) {
        if (result.equals("Complete")) {
            System.out.println("Async task complete.");
        }
    }
}
}

运行上述代码后,我收到“与主机 vet-to-go.database.windows.net 的 TCP/IP 连接,端口 1433 失败”。此行错误:

Connection con = DriverManager.getConnection(connectionString);

我认为这不相关,但为了以防万一,以下是 MainActivity 中当前的所有内容:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etID = (EditText)findViewById(R.id.etCustID);
    btnSubmit = (Button)findViewById(R.id.btnSubmit);

    btnSubmit.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            customerID = etID.getText().toString();
            myIntent = new Intent(MainActivity.this, LandingPage.class);
            myIntent.putExtra("custID", customerID);

            startActivity(myIntent);
        }
    });
}

Android Studio 2.3

Build #AI-162.3764568, built on February 24, 2017

JRE: 1.8.0_112-release-b06 amd64

JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

Gradle version 3.3

Target API 22: Android 5.1

Min Sdk V 21

Build tools v 25.0.0

最佳答案

首先,在Android上直接连接Azure SQL数据库并不是一个好主意。通常,推荐的方法是通过调用一些 REST API 来访问数据库,这些 API 在 Azure 上创建为 Web 应用程序或移动应用程序。

其次,许多现有的 SO 线程与您有类似的问题,解决方法是使用 jTDS驱动程序而不是 Android 上的 MS SQL Server 驱动程序 sqljdbc 进行连接,因为 Android 上似乎不完全支持 sqljdbc 驱动程序。作为引用,请参阅以下已解决的这些线程。

  1. https://social.msdn.microsoft.com/forums/sqlserver/en-US/4799819a-27fd-4292-a3d8-f114207c20b2/using-the-jdbc-driver-with-android
  2. Sql Database connect Using the JDBC Driver with android
  3. how to connect sql server using JTDS driver in Android

希望有帮助。

关于java - Android Studio 中与 Azure 的 JDBC 连接失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43199830/

相关文章:

java - 如何创建spring cas登录链接

sql-server - 使用 CONTAINSTABLE 转义 SQL Server 全文搜索查询中的符号

c# - 可以应用什么设计模式来构建需要来自两个数据读取器的数据的对象?

azure - Azure ServiceBus QueueClient.OnMessage 是否在不同的线程上执行

json - 嵌套 json 的 Azure JMESPATH 查询

c# - 如何获取 webjob 内 azure 托管的 asp .net core 应用程序的 wwwroot 文件夹中图像文件的路径

java - 如何在android中的可扩展 ListView 组和 subview 中加载json数据?

java - JLabel 的 KeyListener 不适合我

java - Eclipse 上的 Glassfish 。收集要安装的项目时发生错误

sql - 按组和总计数提取计数