0

0

使用Java和Android连接PostgreSQL数据库:常见问题与最佳实践

聖光之護

聖光之護

发布时间:2025-12-04 19:02:01

|

607人浏览过

|

来源于php中文网

原创

使用Java和Android连接PostgreSQL数据库:常见问题与最佳实践

本文旨在解决android应用通过java直接连接postgresql数据库时遇到的常见问题。我们将探讨android模拟器中`127.0.0.1`与`10.0.2.2`的区别,并深入分析为何直接jdbc连接在android环境下并非最佳实践。最终,文章将推荐使用web服务(rest api)作为android应用与postgresql数据库进行安全、高效交互的优选方案,并简要提及gradle构建错误的处理方法。

在Android应用开发中,直接通过Java的JDBC(Java Database Connectivity)接口连接外部关系型数据库(如PostgreSQL)是一个常见的尝试,但往往伴随着一系列挑战和不推荐的实践。本教程将深入分析这些问题,并提供更健壮、安全的解决方案。

1. Android模拟器中的网络连接问题:127.0.0.1 vs 10.0.2.2

当你在Android模拟器中运行应用并尝试连接到与你的开发机器在同一台物理机上运行的PostgreSQL数据库时,使用127.0.0.1作为数据库主机地址是错误的。

  • 127.0.0.1 (localhost):在Android模拟器内部,127.0.0.1指向的是模拟器自身的环回地址,而非宿主机器。这意味着,如果你在模拟器中使用127.0.0.1,它会尝试连接模拟器内部的数据库服务,而你的PostgreSQL服务通常运行在宿主机器上。
  • 10.0.2.2:这是Android模拟器为访问宿主机器(Host Machine)提供的特殊IP地址。当你需要从模拟器连接到运行在宿主机器上的服务(如PostgreSQL数据库、Web服务器等)时,应使用此IP地址。

修正后的连接字符串示例:

在你的ConnectPG类中,连接URL应修改为:

立即学习Java免费学习笔记(深入)”;

package com.example.a112new;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException; // 导入SQLException

public class ConnectPG {
    Connection connect = null;
    public Connection connectBD(){
        try{
            Class.forName("org.postgresql.Driver");
            // 修正后的连接字符串,使用10.0.2.2 连接宿主机器上的PostgreSQL
            connect = DriverManager.getConnection( "jdbc:postgresql://10.0.2.2:5432/112", "postgresql",  "430890");
            System.out.println("数据库连接成功!"); // 添加成功提示
        } catch (ClassNotFoundException e) { // 捕获驱动未找到异常
            System.err.println("PostgreSQL JDBC 驱动未找到: " + e.getMessage());
        } catch (SQLException e) { // 捕获SQL连接异常
            System.err.println("数据库连接失败: " + e.getMessage());
        }
        return connect;
    }

    protected void disconnection(Connection con) throws SQLException { // 修正异常类型
        if (con != null && !con.isClosed()) { // 检查连接是否为空且未关闭
            con.close();
            System.out.println("数据库连接已关闭。");
        }
    }
}

同样,在InsertRecordExample类中,如果它被设计为在Android环境中运行,也需要进行类似的修改:

// ... (其他导入和类定义)
public class InsertRecordExample {
    // localhost 修正为 10.0.2.2
    private final String url = "jdbc:postgresql://10.0.2.2:5432/112";
    private final String user = "postgres";
    private final String password = "111111"; // 假设这是正确的密码
    // ... (其他代码)
}

2. Android应用中直接JDBC连接的局限性与风险

尽管修正了IP地址,但直接在Android应用中使用JDBC连接数据库仍然不是推荐的做法,主要原因如下:

  • 安全性风险: 数据库凭据(用户名、密码)直接硬编码或存储在客户端应用中,极易被反编译获取,导致数据库面临严重的安全威胁。
  • 性能问题: 移动网络环境复杂,直接进行数据库连接可能导致延迟高、连接不稳定。同时,JDBC驱动本身可能不针对移动设备进行优化,资源消耗较大。
  • 网络策略限制: 许多企业或公共Wi-Fi网络可能限制或阻止直接的数据库端口连接。
  • 维护与扩展性差: 数据库模式变更时,需要更新所有客户端应用。同时,直接连接使得数据库难以进行负载均衡、缓存等优化。
  • 驱动兼容性: 某些JDBC驱动可能在Android运行时环境中表现不佳或存在兼容性问题。

3. 最佳实践:使用Web服务(REST API)作为中间层

连接Android应用与PostgreSQL数据库的最佳实践是引入一个后端Web服务(通常是RESTful API)作为中间层。

工作原理:

  1. 后端服务: 使用一种后端技术(如Java Spring Boot、Node.js Express、Python Django/Flask等)开发一个Web服务。这个服务负责与PostgreSQL数据库进行实际的交互。
  2. API接口: 后端服务暴露一系列API接口(例如,/users用于获取用户列表,/users/add用于添加用户)。
  3. Android应用: Android应用不再直接连接数据库,而是通过HTTP请求(如GET、POST、PUT、DELETE)调用后端Web服务提供的API接口。
  4. 数据传输: 数据通常以JSON或XML格式在Android应用和后端服务之间传输。

Web服务架构优势:

Picsart
Picsart

Picsart是全球最大的数字创作平台。

下载
  • 增强安全性: 数据库凭据只存在于后端服务器,不会暴露给客户端。后端可以实现更复杂的认证和授权机制。
  • 提升性能和用户体验: 后端可以优化数据库查询、实现数据缓存、压缩响应数据,从而减少网络流量和提高响应速度。
  • 解耦: Android应用和数据库之间实现解耦。数据库结构变化时,只需更新后端服务,无需修改客户端应用。
  • 可扩展性: 后端服务可以独立扩展,以应对大量用户请求。
  • 跨平台支持: 同一套API可以被iOS、Web等其他客户端复用。

示例(概念性):

假设你有一个Spring Boot后端服务,它暴露一个POST /api/users接口来插入用户数据。

后端Java代码片段 (Spring Boot):

// User entity and repository omitted for brevity
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserRepository userRepository; // Spring Data JPA repository

    @PostMapping
    public ResponseEntity createUser(@RequestBody User user) {
        User savedUser = userRepository.save(user);
        return new ResponseEntity<>(savedUser, HttpStatus.CREATED);
    }
    // Other CRUD operations (GET, PUT, DELETE)
}

Android应用中调用后端API (使用Retrofit库):

// Retrofit service interface
public interface UserService {
    @POST("api/users")
    Call createUser(@Body User user);
}

// In your Android Activity/Fragment
public void insertUserViaApi() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://10.0.2.2:8080/") // 后端服务的地址,模拟器访问宿主机器
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    UserService userService = retrofit.create(UserService.class);

    User newUser = new User(1, "FFFF", "FFFF", "FFFFF", "2005-01-12", "+79888888888", "test@example.com", "1234567");

    Call call = userService.createUser(newUser);
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            if (response.isSuccessful()) {
                System.out.println("用户插入成功: " + response.body().getFirstName());
            } else {
                System.err.println("API调用失败: " + response.code());
            }
        }

        @Override
        public void onFailure(Call call, Throwable t) {
            System.err.println("网络错误: " + t.getMessage());
        }
    });
}

注意:上述Android代码需要添加Retrofit和Gson依赖,并在AndroidManifest.xml中添加网络权限。

4. Gradle构建错误分析:SourceSet with name 'main' not found

你遇到的Gradle错误 FAILURE: Build failed with an exception. ... Could not create task ':app:InsertRecordExample.main()'. SourceSet with name 'main' not found. 提示了一个常见的误区。

这个错误通常发生在以下情况:

  1. 你正在一个Android模块中,尝试直接运行一个包含 public static void main(String[] argv) 方法的普通Java类。
  2. Android Studio的运行配置可能错误地将此视为一个Android应用组件,而不是一个独立的Java应用程序。

解释: Android模块的main源集(SourceSet)是为Android应用程序的组件(Activity, Service等)构建的,而不是为独立的Java main方法。当你尝试直接运行一个main方法时,Gradle在Android模块的上下文中找不到一个合适的“main”入口点来执行它,因为Android应用是通过其Manifest文件和Activity生命周期启动的。

解决方案:

  • 创建独立的Java模块: 如果你需要编写一个包含 main 方法的独立Java程序来测试数据库连接或执行其他非Android特定的逻辑,应该在你的项目中创建一个独立的Java模块(而非Android模块)。
    • 在Android Studio中,选择 File -> New -> New Module...,然后选择 Java Library。
    • 将你的 ConnectPG 和 InsertRecordExample 类放到这个Java模块中。这样,你就可以独立运行它们的 main 方法,而不会与Android构建系统冲突。
  • 在Android组件中调用: 如果你的数据库操作是Android应用逻辑的一部分,那么 InsertRecordExample 中的 insertRecord() 方法应该被某个Android组件(如Activity、Fragment或Service)调用,而不是通过其自身的 main 方法启动。main 方法在Android应用中没有直接的执行上下文。

总结

连接Android应用与PostgreSQL数据库时,应避免直接JDBC连接。优先采用后端Web服务(REST API)作为中间层,以确保应用的安全性、性能、可维护性和可扩展性。同时,对于开发和测试用途的纯Java代码(包含main方法),应将其置于独立的Java模块中,以避免与Android构建系统产生冲突。遵循这些最佳实践,将有助于构建更健壮、更专业的Android应用。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

774

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

684

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

767

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

719

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1425

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

570

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

579

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

751

2023.08.11

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

41

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 19.4万人学习

Django 教程
Django 教程

共28课时 | 3.5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号