JAVA数据库技术(一)

发布于:2025-03-17 ⋅ 阅读:(23) ⋅ 点赞:(0)

JDBC 简介

JDBC(Java Database Connectivity)是Java平台提供的一套用于执行SQL语句的Java API。它允许Java程序连接到数据库,并通过发送SQL语句来查询、更新和管理数据库中的数据。JDBC为不同的数据库提供了一种统一的访问方式,使得Java程序可以独立于特定的数据库管理系统(DBMS)进行开发。

以下是JDBC的一些关键特性和组件:

  1. 驱动管理器(DriverManager):

JDBC的入口点,用于管理数据库驱动程序。通过DriverManager.getConnection()方法,Java程序可以获取到与数据库的连接。

  2. 数据库连接(Connection):

代表Java程序与数据库之间的连接。通过这个连接,Java程序可以执行SQL语句并获取结果。

  3. 语句(Statement)和预处理语句(PreparedStatement):

用于执行SQL语句的对象。Statement对象用于执行静态SQL语句,而PreparedStatement对象则用于执行带参数的SQL语句,这有助于防止SQL注入攻击。

  4. 结果集(ResultSet):

代表数据库查询的结果。通过遍历ResultSet对象,Java程序可以获取查询返回的每一行数据。

  5. 异常处理:

JDBC API定义了一组异常类,用于处理数据库访问过程中可能发生的错误。常见的异常包括SQLException、SQLIntegrityConstraintViolationException等。

  6. 元数据(MetaData):

JDBC还提供了获取数据库、表和列等元数据的方法。通过元数据,Java程序可以在运行时动态地了解数据库的结构。

  7. 事务支持:

JDBC支持事务处理,允许Java程序在多个数据库操作之间保持数据的一致性。通过调用Connection对象的setAutoCommit(false)方法,可以关闭自动提交模式,从而开始一个事务。完成所有操作后,可以调用commit()方法提交事务,或者调用rollback()方法回滚事务。

使用JDBC时,通常需要按照以下步骤进行:

  1. 加载数据库驱动程序。

  2. 通过DriverManager获取数据库连接。

  3. 创建Statement或PreparedStatement对象。

  4. 执行SQL语句。

  5. 处理结果集(如果有的话)。

  6. 关闭ResultSet、Statement和Connection对象以释放资源。

尽管JDBC提供了强大的数据库访问能力,但它也带来了一些复杂性,比如需要手动管理资源、处理SQL注入等。因此,在实际开发中,开发者通常会使用ORM框架(如Hibernate、MyBatis等)或JDBC模板(如Spring JDBC Template)来简化数据库操作。这些工具提供了更高层次的抽象,使得开发者可以更加专注于业务逻辑的实现。

JDBC 驱动程序分类

JDBC(Java Database Connectivity)是Java与数据库的接口规范,由Java语言编写的类和接口组成。JDBC驱动程序由实施了这些接口的类组成,它实现了Java应用程序与数据库之间的连接。JDBC驱动程序主要分为以下四种类型:

1. JDBC-ODBC桥驱动程序(JDBC-ODBC Bridge)

  • 工作原理:JDBC-ODBC桥驱动程序使用ODBC驱动程序连接到数据库,它将JDBC方法调用转换为ODBC函数调用。

  • 优点:使用简单,可以轻松连接到任何已安装ODBC驱动的数据库。

  • 缺点:性能下降,因为JDBC方法调用需要被转换为ODBC函数调用。此外,由于需要在客户端安装ODBC驱动,因此不适合基于Internet的应用。自Java 8开始,Oracle不再支持JDBC-ODBC桥接,并建议使用由数据库供应商提供的JDBC驱动程序。

2. 本机API驱动程序(Native-API Partly Java Driver)

  • 工作原理:本机API驱动程序使用数据库的客户端库,将JDBC方法调用转换为数据库API的本机调用。

  • 优点:性能比JDBC-ODBC桥驱动程序有所提升。

  • 缺点:需要在每个客户端机器上安装本机驱动程序和供应商的客户端库,因此不适合基于Internet的应用。并且,尽管其性能有所提升,但相较于完全使用Java编写的驱动程序,其执行效率仍然较低。

3. 网络协议驱动程序(Network-Protocol Pure Java Driver)

  • 工作原理:网络协议驱动程序使用中间件(应用服务器),将JDBC调用直接或间接地转换为特定供应商的数据库协议。它完全使用Java编写。

  • 优点:不需要在客户端安装数据库厂商提供的代码库,因为应用服务器可以执行许多任务,如审计、负载平衡、日志记录等。同时,它在执行效率和可升级性方面表现良好。

  • 缺点:客户端机器需要网络支持,且需要在中间层中完成特定于数据库的编码,因此维护成本较高。

4. Thin驱动程序(Local-Protocol Pure Java Driver)

  • 工作原理:Thin驱动程序将JDBC调用直接转换为特定供应商的数据库协议,因此也被称为“轻量级”驱动程序。它完全使用Java语言编写。

  • 优点:执行效率高,不需要在客户端或服务器端装载任何的软件或驱动,且可以动态地被下载。由于它是完全用Java编写的,因此实现了平台独立性。

  • 缺点:对于不同的数据库需要下载不同的驱动程序。

总的来说,JDBC驱动程序的四种类型各有优缺点,适用于不同的应用场景。在选择JDBC驱动程序时,需要根据具体的应用需求、性能要求以及客户端和服务器端的配置来进行合理选择。

选择数据库连接方式

在Java中,选择数据库连接方式通常有几种方法。根据需求、开发环境和具体应用的不同,可以选择不同的数据库连接方式。以下是几种常见的数据库连接方式:
1. JDBC (Java Database Connectivity)
JDBC 是 Java 提供的一种标准 API 用于连接和操作数据库。JDBC 主要通过 DriverManager 或 DataSource 来获取数据库连接。

DriverManager方式:通过手动加载数据库驱动类来管理数据库连接。
.DataSource方式:通过配置数据源(如在应用服务器中配置),更适合生产环境,支持连接池。使用 DriverManager 连接数据库:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCExample {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            // 加载数据库驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 建立数据库连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb", "username", "password");

            System.out.println("Connected to the database successfully.");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭连接
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

使用 DataSource 连接数据库:

import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;

public class DataSourceExample {
    public static void main(String[] args) {
        DataSource dataSource = setupDataSource();

        try (Connection connection = dataSource.getConnection()) {
            System.out.println("Connected to the database using DataSource.");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static DataSource setupDataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/yourdb");
        dataSource.setUsername("username");
        dataSource.setPassword("password");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        return dataSource;
    }
}

2. JPA (Java Persistence API)
JPA 是一种对象关系映射 (ORM) 技术,它让开发者通过对象模型来操作数据库,而不需要直接编写 SQL。JPA 在后台使用 JDBC 实现数据库操作。

JPA 通过 EntityManager 来进行数据库操作,通常和 Spring 框架一起使用。
Hibernate 是 JPA 最常用的实现。

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JPAExample {
    public static void main(String[] args) {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("yourPersistenceUnit");
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        // 执行数据库操作

        entityManager.close();
        entityManagerFactory.close();
    }
}

3. Spring JDBC
Spring 提供了 JdbcTemplate 类,简化了 JDBC 操作,减少了大量的样板代码。Spring JDBC 通过 JdbcTemplate 管理数据库连接和执行 SQL 查询,通常与 Spring 框架一起使用。

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class SpringJDBCExample {
    public static void main(String[] args) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/yourdb");
        dataSource.setUsername("username");
        dataSource.setPassword("password");

        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

        String sql = "SELECT COUNT(*) FROM users";
        int rowCount = jdbcTemplate.queryForObject(sql, Integer.class);

        System.out.println("Row count: " + rowCount);
    }
}

4. Spring Data JPA
Spring Data JPA 是基于 JPA 的一个扩展,简化了数据访问层的开发。它提供了用于数据库操作的接口,通过注解自动生成 SQL 查询。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void displayUserCount() {
        long count = userRepository.count();
        System.out.println("Total users: " + count);
    }
}

interface UserRepository extends JpaRepository<User, Long> {
    // 自动生成查询方法
}

5. 数据库连接池
在生产环境中,数据库连接池(如 HikariCP、C3P0 或 Apache DBCP)通常被使用。连接池可以复用数据库连接,避免了每次数据库操作时都创建新连接的开销,提高了系统性能。HikariCP:是一个高性能的 JDBC 连接池。
C3P0:是一个传统的数据库连接池,功能全面。
Apache DBCP:也是一个常用的数据库连接池。

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class HikariCPExample {
    public static void main(String[] args) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/yourdb");
        config.setUsername("username");
        config.setPassword("password");

        HikariDataSource dataSource = new HikariDataSource(config);

        try (Connection connection = dataSource.getConnection()) {
            System.out.println("Connected using HikariCP.");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

总结:

JDBC:直接操作数据库,灵活但代码冗长。
JPA:通过 ORM 操作数据库,适合对象映射,常用于 Spring Boot 应用。
Spring JDBC:简化了 JDBC 的使用,适合复杂应用。
Spring Data JPA:在 JPA 的基础上进一步简化操作,适用于快速开发。
数据库连接池:提高性能,减少数据库连接的创建和销毁开销。

选择数据库连接方式时要根据项目的需求来决定,如果是小型应用可以选择简单的 JDBC 连接,如果是大型应用或需要更高性能的应用,则建议使用连接池或 JPA。

JDBC 装载

JDBC(Java Database Connectivity)是 Java 提供的一种用于与数据库进行交互的标准 API,它使 Java 程序能够执行 SQL 查询、更新操作以及管理数据库事务。JDBC 提供了一个标准接口来访问不同类型的数据库。装载 JDBC 主要是指通过加载 JDBC 驱动来连接数据库并执行相关的数据库操作。
JDBC 装载的步骤

1.加载 JDBC 驱动程序:
JDBC 驱动程序是实现数据库连接的核心。为了让 Java 程序与特定的数据库进行通信,我们需要加载相应的数据库驱动。


2.在早期的 JDBC 版本中,加载驱动程序的方式是使用 Class.forName() 方法:
 Class.forName("com.mysql.cj.jdbc.Driver");

这行代码会加载 MySQL 数据库的 JDBC 驱动(在这个例子中是 com.mysql.cj.jdbc.Driver)。
现代 JDBC 版本通常不需要显式地加载驱动程序,因为大多数 JDBC 驱动已经通过服务提供者接口(SPI)自动加载。你只需要在 classpath 中正确地放置 JDBC 驱动 jar 文件即可。


3.创建数据库连接:
使用 DriverManager.getConnection() 方法来创建数据库连接:

   Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");

这行代码创建了一个到 MySQL 数据库 mydatabase 的连接,用户名是 username,密码是 password。连接字符串 jdbc:mysql://localhost:3306/mydatabase 需要根据数据库类型和实际的连接信息进行修改。

4.执行 SQL 查询或更新:
创建一个 Statement 或 PreparedStatement 对象,并使用其执行 SQL 查询或更新操作。例如,查询操作如下:

   Statement statement = connection.createStatement();
   ResultSet resultSet = statement.executeQuery("SELECT * FROM users");

对于更新操作(如插入、删除、更新等),可以使用 executeUpdate() 方法:

   int rowsAffected = statement.executeUpdate("UPDATE users SET name='John' WHERE id=1");


5.处理结果集:
如果执行的是查询操作,结果将存储在 ResultSet 对象中。可以通过 ResultSet 获取查询结果:

   while (resultSet.next()) {
       String name = resultSet.getString("name");
       int age = resultSet.getInt("age");
       System.out.println("Name: " + name + ", Age: " + age);
   }


6.关闭连接:
数据库操作完成后,需要关闭数据库连接、语句和结果集,防止资源泄露:

   resultSet.close();
   statement.close();
   connection.close();

常见 JDBC 驱动类型
JDBC 驱动可以分为以下几种类型:

JDBC-ODBC 桥接驱动(Type 1): 通过 ODBC 接口连接数据库,速度较慢,已经不推荐使用。
本地客户端驱动(Type 2): 使用本地数据库驱动程序通过本地协议与数据库进行通信。效率较高,但需要安装数据库的本地驱动。
网络协议驱动(Type 3): 使用网络协议(如 TCP/IP)与数据库进行通信。可以支持多种数据库,不需要安装本地客户端。
纯 Java 驱动(Type 4): 完全用 Java 实现,直接通过网络协议与数据库通信。速度较快,跨平台支持好。示例代码
以下是一个简单的 JDBC 示例,展示如何加载驱动、连接数据库并执行查询操作:

import java.sql.*;

public class JDBCExample {
    public static void main(String[] args) {
        // 1. 加载 JDBC 驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. 建立数据库连接
            Connection connection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/mydatabase", "username", "password");

            // 3. 创建 Statement 对象
            Statement statement = connection.createStatement();

            // 4. 执行查询操作
            ResultSet resultSet = statement.executeQuery("SELECT * FROM users");

            // 5. 处理查询结果
            while (resultSet.next()) {
                String name = resultSet.getString("name");
                int age = resultSet.getInt("age");
                System.out.println("Name: " + name + ", Age: " + age);
            }

            // 6. 关闭资源
            resultSet.close();
            statement.close();
            connection.close();

        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }
}

小结

JDBC 装载的核心是通过加载数据库的驱动程序,让 Java 应用能够连接和操作数据库。
使用 JDBC 时,我们通常需要加载驱动、创建连接、执行 SQL 操作、处理结果,并最终关闭数据库连接。
现代 JDBC 驱动通常会通过服务提供者接口(SPI)自动加载,不再需要手动使用 Class.forName()。

希望这能帮助你更好地理解 JDBC 装载的过程。如果有其他问题或需要进一步的讲解,随时告诉我!

拓展JDBC API 

JDBC (Java Database Connectivity) 是一个用于在 Java 应用程序中与数据库进行交互的标准 API。它允许开发人员通过标准的接口来执行 SQL 查询、更新数据以及管理数据库连接等。
拓展 JDBC API 主要是指如何在基础 JDBC 的基础上,增强或自定义功能,使得其更加符合某些特定需求或提供更高效、更安全的数据库操作。
下面是一些常见的扩展 JDBC API 的方式和方法:
1. 使用数据源(DataSource)替代 DriverManager
在传统的 JDBC 编程中,数据库连接是通过 DriverManager 获取的。但是,DataSource 提供了一种更灵活的方式,它支持连接池等特性,能够提高应用的性能。
示例代码:

import javax.sql.DataSource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.sql.Connection;
import java.sql.SQLException;

public class DataSourceExample {
    public static void main(String[] args) throws SQLException, NamingException {
        // 假设数据源已经在 JNDI 中注册
        InitialContext ctx = new InitialContext();
        DataSource ds = (DataSource) ctx.lookup("jdbc/myDataSource");

        try (Connection conn = ds.getConnection()) {
            // 执行数据库操作
            System.out.println("Connected to the database successfully!");
        }
    }
}

2. 使用连接池
通过扩展 JDBC API,开发者可以实现自定义的数据库连接池。连接池允许多个连接共享,减少了频繁创建和销毁连接的性能开销。常用的连接池实现库有 Apache Commons DBCP, HikariCP 和 C3P0 等。
示例代码:

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.Connection;
import java.sql.SQLException;

public class HikariCPExample {
    public static void main(String[] args) throws SQLException {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        config.setUsername("root");
        config.setPassword("password");

        HikariDataSource dataSource = new HikariDataSource(config);

        try (Connection conn = dataSource.getConnection()) {
            // 执行数据库操作
            System.out.println("Connected to the database with HikariCP!");
        }
    }
}

3. 批量处理和批量插入
JDBC 允许执行批量操作,通过 Statement 或 PreparedStatement 来进行批量插入、更新或删除操作。这对于提高大量数据操作的性能非常重要。
示例代码:

import java.sql.*;

public class BatchInsertExample {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";

        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            String sql = "INSERT INTO employees (name, age) VALUES (?, ?)";
            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                conn.setAutoCommit(false);

                pstmt.setString(1, "Alice");
                pstmt.setInt(2, 30);
                pstmt.addBatch();

                pstmt.setString(1, "Bob");
                pstmt.setInt(2, 25);
                pstmt.addBatch();

                pstmt.executeBatch();

                conn.commit();
                System.out.println("Batch insert executed successfully.");
            }
        }
    }
}

4. JDBC 中的事务管理
JDBC 提供了事务管理机制,开发人员可以通过 Connection 对象管理事务的开始、提交和回滚。事务管理是确保数据库操作一致性和完整性的关键。
示例代码:

import java.sql.*;

public class TransactionManagementExample {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";

        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            conn.setAutoCommit(false);  // 禁用自动提交

            try {
                String sql1 = "UPDATE account SET balance = balance - 100 WHERE id = 1";
                String sql2 = "UPDATE account SET balance = balance + 100 WHERE id = 2";

                try (Statement stmt = conn.createStatement()) {
                    stmt.executeUpdate(sql1);
                    stmt.executeUpdate(sql2);
                }

                conn.commit();  // 提交事务
                System.out.println("Transaction committed successfully.");
            } catch (SQLException e) {
                conn.rollback();  // 回滚事务
                System.out.println("Transaction rolled back due to an error.");
                e.printStackTrace();
            }
        }
    }
}

5. 自定义 ResultSet 和 RowMapper
JDBC 的 ResultSet 提供了从查询中提取数据的功能,但有时我们希望将结果集映射到自定义对象中。这时可以使用 RowMapper 模式来扩展 JDBC API。
示例代码:

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class RowMapperExample {
    public static class Employee {
        private int id;
        private String name;
        private int age;

        public Employee(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Employee{id=" + id + ", name='" + name + "', age=" + age + '}';
        }
    }

    public static List<Employee> getEmployees(Connection conn) throws SQLException {
        List<Employee> employees = new ArrayList<>();
        String sql = "SELECT id, name, age FROM employees";

        try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                employees.add(new Employee(id, name, age));
            }
        }
        return employees;
    }

    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";

        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            List<Employee> employees = getEmployees(conn);
            employees.forEach(System.out::println);
        }
    }
}

6. JDBC 异常处理与日志记录
为了在数据库操作中更好地捕获错误,很多开发人员会使用日志记录工具(如 Log4j、SLF4J 等)来记录 SQL 错误、执行时间等信息。此外,处理 SQLException 时,我们可以根据错误代码或 SQLState 进行细致的错误处理。
示例代码:

import java.sql.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JdbcExceptionExample {
    private static final Logger logger = LoggerFactory.getLogger(JdbcExceptionExample.class);

    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";

        try (Connection conn = DriverManager.getConnection(url, username, password)) {
            String sql = "SELECT * FROM non_existent_table";
            try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
                while (rs.next()) {
                    System.out.println(rs.getString("name"));
                }
            }
        } catch (SQLException e) {
            logger.error("Database error occurred: ", e);
        }
    }
}

总结
扩展 JDBC API 的方式有很多,可以通过使用连接池、事务管理、批量操作、日志记录、映射工具等来增强功能。通过这些扩展,开发者能够提升应用的性能、灵活性以及易用性。


网站公告

今日签到

点亮在社区的每一天
去签到