杰瑞科技汇

SQLServer与Java链接如何实现?

目录

  1. 第一步:准备工作

    SQLServer与Java链接如何实现?-图1
    (图片来源网络,侵删)
    • 安装 SQL Server
    • 安装 Java 开发环境
    • 下载 SQL Server JDBC 驱动
    • 准备数据库和表
  2. 第二步:使用 JDBC 驱动连接 (传统方法)

    • 添加驱动到项目
    • 编写 Java 连接代码
    • 代码解析
    • 完整示例
  3. 第三步:使用连接池 (推荐方法)

    • 什么是连接池?
    • 常用连接池库
    • 使用 HikariCP 连接 SQL Server
    • 连接池配置示例
  4. 第四步:现代方法:使用 JPA / Hibernate

    • 简介
    • 依赖配置
    • 配置文件示例
    • 简单的实体类和测试
  5. 第五步:常见问题与最佳实践

    SQLServer与Java链接如何实现?-图2
    (图片来源网络,侵删)
    • 常见错误及解决方法
    • 最佳实践总结

第一步:准备工作

在开始编码之前,请确保你已经完成了以下准备工作:

  1. 安装 SQL Server

    • 确保你的机器上安装了一个可运行的 SQL Server 实例(可以是本地开发版、Express 版或 Docker 容器)。
    • 记下你的服务器名称、端口号(默认为 1433)、用户名和密码。
  2. 安装 Java 开发环境

    • 确保你已经安装了 JDK(建议 JDK 8 或更高版本)。
    • 配置好 JAVA_HOME 环境变量。
    • 你可以使用任何 IDE,如 IntelliJ IDEA、Eclipse 或 VS Code。
  3. 下载 SQL Server JDBC 驱动

    SQLServer与Java链接如何实现?-图3
    (图片来源网络,侵删)
    • 这是 Java 连接 SQL Server 的核心库。
    • 访问微软官方下载页面:Microsoft JDBC Driver for SQL Server
    • 下载与你的 JDK 版本和 SQL Server 版本相匹配的驱动包(通常是一个 .jar 文件)。
    • 注意:从 JDBC 4.0 开始,驱动支持自动加载,但显式加载仍然是好习惯。
  4. 准备数据库和表

    • 在你的 SQL Server 实例中创建一个数据库和一个用于测试的表。
    • 创建一个名为 TestDB 的数据库,并在其中创建一个 Employees 表。
    -- 创建数据库
    CREATE DATABASE TestDB;
    GO
    -- 使用新数据库
    USE TestDB;
    GO
    -- 创建员工表
    CREATE TABLE Employees (
        id INT PRIMARY KEY IDENTITY(1,1),
        name NVARCHAR(50) NOT NULL,
        department NVARCHAR(50),
        salary DECIMAL(10, 2)
    );
    GO
    -- 插入一些测试数据
    INSERT INTO Employees (name, department, salary) VALUES
    ('张三', '研发部', 8000.00),
    ('李四', '市场部', 7500.00),
    ('王五', '研发部', 9000.00);
    GO

第二步:使用 JDBC 驱动连接 (传统方法)

这是最基础、最直接的方式,适合学习和理解连接原理。

添加驱动到项目

你需要将下载的 JDBC 驱动 JAR 文件添加到你的 Java 项目的类路径中。

  • 在 Maven 项目中:将 JAR 文件安装到本地 Maven 仓库,或在 pom.xml 中直接指定,推荐使用 Maven,因为它可以自动管理依赖。

    <!-- 在 pom.xml 中添加依赖 -->
    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>
        <version>11.2.1.jre8</version> <!-- 请使用最新版本 -->
    </dependency>
  • 在 Gradle 项目中

    // 在 build.gradle 中添加依赖
    implementation 'com.microsoft.sqlserver:mssql-jdbc:11.2.1.jre8' // 请使用最新版本
  • 在普通 Java 项目中:将 JAR 文件复制到项目的 lib 目录,并将其添加到 IDE 的库或构建路径中。

编写 Java 连接代码

下面是一个完整的 Java 类,演示了如何连接到 SQL Server,执行查询,并处理结果。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcSqlServerExample {
    // 数据库连接信息
    private static final String DB_URL = "jdbc:sqlserver://localhost:1433;databaseName=TestDB;encrypt=false;trustServerCertificate=true;";
    // 如果你的 SQL Server 使用了 Windows 身份验证,用户名和密码可以省略或使用如下格式
    // private static final String DB_URL = "jdbc:sqlserver://localhost:1433;databaseName=TestDB;integratedSecurity=true;encrypt=false;trustServerCertificate=true;";
    private static final String USER = "sa"; // 你的数据库用户名
    private static final String PASS = "your_password"; // 你的数据库密码
    public static void main(String[] args) {
        // try-with-resources 语句,确保资源被自动关闭
        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT id, name, department, salary FROM Employees")) {
            if (conn != null) {
                System.out.println("成功连接到数据库!");
            }
            System.out.println("员工列表:");
            System.out.println("---------------------------------");
            // 遍历结果集
            while (rs.next()) {
                // 通过列名获取数据,更安全且可读性高
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String department = rs.getString("department");
                double salary = rs.getDouble("salary");
                System.out.printf("ID: %d, 姓名: %s, 部门: %s, 薪资: %.2f%n", id, name, department, salary);
            }
        } catch (SQLException e) {
            System.err.println("数据库连接或查询失败!");
            e.printStackTrace();
        }
    }
}

代码解析

  • DB_URL: 这是连接字符串,格式为 jdbc:sqlserver://[server_name][:port];databaseName=[db_name];[other_properties]
    • encrypt=false;trustServerCertificate=true;: 这两个参数在本地开发时非常有用,它们可以避免 SSL/TLS 证书验证的麻烦,在生产环境中,你应该配置正确的 SSL 证书。
  • DriverManager.getConnection(): 这是建立连接的核心方法,它接收 URL、用户名和密码。
  • try-with-resources: 这是一个 Java 7+ 的特性,它会自动在 try 代码块执行完毕后关闭 Connection, Statement, 和 ResultSet,防止资源泄漏。
  • Statement: 用于执行静态 SQL 语句。
  • ResultSet: 代表 SQL 查询返回的结果集,你可以通过 next() 方法遍历它,并用 getXXX() 方法获取数据。

第三步:使用连接池 (推荐方法)

在真实的应用程序中,频繁地创建和销毁数据库连接是非常消耗资源的。连接池应运而生,它预先创建一组数据库连接,并将其保存在池中,当需要连接时,从池中获取,用完后归还给池,而不是关闭。

什么是连接池?

连接池是一个管理数据库连接的缓存对象,它可以显著提高应用程序的性能和稳定性。

常用连接池库

  • HikariCP: 目前性能最好的连接池,被誉为“连接池之王”,Spring Boot 2.x 默认使用它。
  • Apache DBCP: 一个老牌的连接池实现。
  • C3P0: 另一个流行的连接池,功能强大。

使用 HikariCP 连接 SQL Server

第一步:添加 HikariCP 依赖

<!-- 在 pom.xml 中添加 HikariCP 依赖 -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version> <!-- 请使用最新版本 -->
</dependency>

第二步:编写连接池代码

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class HikariCPExample {
    private static HikariDataSource dataSource;
    // 静态代码块,在类加载时初始化连接池
    static {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:sqlserver://localhost:1433;databaseName=TestDB;encrypt=false;trustServerCertificate=true;");
        config.setUsername("sa");
        config.setPassword("your_password");
        // 连接池配置
        config.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        config.setMaximumPoolSize(10); // 最大连接数
        config.setMinimumIdle(5);       // 最小空闲连接数
        config.setConnectionTimeout(30000); // 连接超时时间 (ms)
        config.setIdleTimeout(600000);  // 空闲连接超时时间 (ms)
        config.setMaxLifetime(1800000); // 连接最大存活时间 (ms)
        config.setLeakDetectionThreshold(15000); // 连接泄漏检测时间 (ms)
        dataSource = new HikariDataSource(config);
    }
    public static void main(String[] args) {
        // 从连接池获取一个连接
        try (Connection conn = dataSource.getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT name, department FROM Employees WHERE department = '研发部'")) {
            System.out.println("成功从连接池获取连接!");
            System.out.println("研发部员工:");
            System.out.println("---------------------------------");
            while (rs.next()) {
                String name = rs.getString("name");
                String department = rs.getString("department");
                System.out.printf("姓名: %s, 部门: %s%n", name, department);
            }
        } catch (Exception e) {
            System.err.println("获取连接或查询失败!");
            e.printStackTrace();
        }
    }
}

第四步:现代方法:使用 JPA / Hibernate

对于企业级应用,直接使用 JDBC 会写大量重复的样板代码。JPA (Java Persistence API) 是 Java EE 规范中用于对象/关系映射的标准,而 Hibernate 是 JPA 最流行的实现,它允许你用 Java 对象来操作数据库,而无需编写 SQL 语句。

简介

  • ORM (Object-Relational Mapping): 将 Java 对象映射到数据库表。
  • JPA: 规范/标准。
  • Hibernate: JPA 规范的具体实现。

依赖配置

除了 JDBC 驱动和连接池,你还需要添加 JPA/Hibernate 的依赖。

<!-- 在 pom.xml 中添加 JPA / Hibernate 依赖 -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.6.15.Final</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 连接池 (HikariCP) -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version>
</dependency>
<!-- JDBC 驱动 -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>11.2.1.jre8</version>
</dependency>

配置文件示例 (persistence.xml)

src/main/resources/META-INF/persistence.xml 文件中配置数据库连接和 Hibernate 设置。

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.example.Employee</class> <!-- 指定要管理的实体类 -->
        <properties>
            <!-- 数据库连接信息 (使用 HikariCP) -->
            <property name="javax.persistence.jdbc.url" value="jdbc:sqlserver://localhost:1433;databaseName=TestDB;encrypt=false;trustServerCertificate=true;"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value="your_password"/>
            <property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
            <!-- Hibernate 特定属性 -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/> <!-- 自动更新表结构 -->
        </properties>
    </persistence-unit>
</persistence>

简单的实体类和测试

实体类 Employee.java

import javax.persistence.*;
@Entity
@Table(name = "Employees")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(nullable = false, length = 50)
    private String name;
    @Column(length = 50)
    private String department;
    @Column(precision = 10, scale = 2)
    private double salary;
    // Getters and Setters
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getDepartment() { return department; }
    public void setDepartment(String department) { this.department = department; }
    public double getSalary() { return salary; }
    public void setSalary(double salary) { this.salary = salary; }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", department='" + department + '\'' +
                ", salary=" + salary +
                '}';
    }
}

测试类 HibernateExample.java

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.List;
public class HibernateExample {
    public static void main(String[] args) {
        // 创建 EntityManagerFactory,这会启动 Hibernate 并初始化连接池
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
        // 创建 EntityManager
        EntityManager em = emf.createEntityManager();
        try {
            // 开始事务
            em.getTransaction().begin();
            // --- 查询示例 ---
            List<Employee> employees = em.createQuery("SELECT e FROM Employee e WHERE e.department = '研发部'", Employee.class).getResultList();
            System.out.println("研发部员工 (JPA/Hibernate):");
            employees.forEach(System.out::println);
            // --- 插入示例 ---
            // Employee newEmployee = new Employee();
            // newEmployee.setName("赵六");
            // newEmployee.setDepartment("财务部");
            // newEmployee.setSalary(6500.00);
            // em.persist(newEmployee); // 将对象持久化
            // 提交事务
            em.getTransaction().commit();
        } catch (Exception e) {
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback(); // 出错则回滚
            }
            e.printStackTrace();
        } finally {
            // 关闭资源
            em.close();
            emf.close(); // 关闭 EntityManagerFactory,销毁连接池
        }
    }
}

第五步:常见问题与最佳实践

常见错误及解决方法

  1. com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host has failed.

    • 原因: SQL Server 服务未启动,或防火墙阻止了端口(1433)。
    • 解决: 检查 SQL Server 服务状态,确保端口 1433 开放。
  2. com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user 'sa'.

    • 原因: 用户名或密码错误,或者 SQL Server 未启用 "SQL Server 身份验证"。
    • 解决: 检查密码,在 SQL Server Management Studio (SSMS) 中,右键点击服务器 -> "属性" -> "安全性",确保 "服务器身份验证" 设置为 "SQL Server 和 Windows 身份验证模式"。
  3. java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver

    • 原因: JDBC 驱动 JAR 文件没有被正确添加到项目的类路径中。
    • 解决: 检查 Maven/Gradle 依赖是否正确,或手动添加的 JAR 文件是否在 lib 目录中并已添加到构建路径。
  4. Connection is closedConnection leak detected

    • 原因: 在使用完连接后没有正确关闭,尤其是在没有使用 try-with-resources 的情况下。
    • 解决: 始终使用 try-with-resources 或在 finally 块中手动关闭 Connection, Statement, ResultSet,使用连接池可以更好地检测泄漏。
  1. 总是使用连接池:在生产环境中,绝对不要直接使用 DriverManager 创建连接,HikariCP 是首选。
  2. 总是关闭资源:使用 try-with-resourcesfinally 块确保 Connection, Statement, ResultSet 被正确关闭,防止资源泄漏。
  3. 使用 PreparedStatement:对于动态 SQL(带参数的查询),始终使用 PreparedStatement 而不是 Statement,它可以防止 SQL 注入攻击,并且通常性能更好。
  4. 使用连接字符串中的列名:在 ResultSet 中,使用 rs.getString("column_name") 而不是 rs.getString(1),这样代码更健壮、可读性更高。
  5. 处理异常:妥善处理 SQLException,不要简单地 printStackTrace() 后就忽略它,至少要记录日志。
  6. 考虑使用 ORM 框架:对于复杂的应用程序,使用 JPA/Hibernate 等框架可以极大地提高开发效率和代码的可维护性。
  7. 配置 SSL/TLS:在生产环境中,务必在数据库连接字符串中启用 encrypt=true 并配置正确的 trustServerCertificate 或提供服务器证书,以确保数据传输安全。
分享:
扫描分享到社交APP
上一篇
下一篇