1. 概述

在 Java 中连接 MySQL 数据库的方式多种多样。本文将系统性地梳理主流方案,帮助你在不同场景下做出合理选择。

我们首先从最基础的 JDBC 开始,然后深入探讨主流 ORM 框架如 Hibernate。
✅ 接着还会覆盖 MyBatis、Apache Cayenne 等第三方库,以及 Spring 生态中的 Spring Data JPA 和 Spring Data JDBC。

通过实际代码示例,带你避开常见“坑点”,掌握每种方案的核心配置与使用方式。


2. 前置条件

假设你本地已运行 MySQL 服务(默认端口 3306),并创建了名为 test 的数据库,其中包含如下表结构:

CREATE TABLE person 
( 
    ID         INT, 
    FIRST_NAME VARCHAR(100), 
    LAST_NAME  VARCHAR(100)  
);

同时,需要引入 MySQL 官方 JDBC 驱动:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>

⚠️ 注意:MySQL 8.x 驱动类为 com.mysql.cj.jdbc.Driver,若使用旧版本驱动可能导致连接失败。


3. 使用 JDBC 连接

JDBC(Java Database Connectivity)是 Java 访问数据库的标准 API,直接操作底层连接,灵活性高但样板代码较多。

3.1 常用连接参数

连接 MySQL 时,以下参数是关键:

  • 连接 URL:指定数据库地址与配置
    格式如下:

    jdbc:mysql://[host][:port]/[database][?propertyName=value&...]
    

    示例:

    jdbc:mysql://localhost:3306/test?serverTimezone=UTC
    

    ⚠️ serverTimezone=UTC 在 MySQL 8.x 中强烈建议显式设置,避免时区问题导致数据异常。

  • 驱动类名com.mysql.cj.jdbc.Driver

  • 用户名/密码:如 root / password123

3.2 JDBC 连接示例

使用 try-with-resources 自动管理资源,简洁又安全:

String sqlSelectAllPersons = "SELECT * FROM person";
String connectionUrl = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";

try (Connection conn = DriverManager.getConnection(connectionUrl, "root", "password123"); 
     PreparedStatement ps = conn.prepareStatement(sqlSelectAllPersons); 
     ResultSet rs = ps.executeQuery()) {

    while (rs.next()) {
        long id = rs.getLong("ID");
        String name = rs.getString("FIRST_NAME");
        String lastName = rs.getString("LAST_NAME");

        // 处理查询结果...
    }
} catch (SQLException e) {
    // 异常处理,建议记录日志
    e.printStackTrace();
}

✅ 推荐使用 PreparedStatement 而非 Statement,防止 SQL 注入。


4. 使用 ORM 框架连接

实际项目中,几乎不会直接使用原生 JDBC。ORM 框架能显著减少模板代码,提升开发效率。

4.1 Hibernate(原生 API)

Hibernate 是最老牌的 ORM 框架之一,功能强大,支持 HQL、缓存、延迟加载等高级特性。

添加依赖

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.4.10.Final</version>
</dependency>

实体类定义

@Entity
@Table(name = "Person")
public class Person {
    @Id
    Long id;
    
    @Column(name = "FIRST_NAME")
    String firstName;

    @Column(name = "LAST_NAME")
    String lastName;
    
    // getters & setters
}

配置文件 hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test?serverTimezone=UTC</property>
        <property name="connection.username">root</property>
        <property name="connection.password">password123</property>

        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hbm2ddl.auto">validate</property>

        <mapping class="Person"/>
    </session-factory>
</hibernate-configuration>

📌 dialect 非常关键,它告诉 Hibernate 生成对应数据库的 SQL 语法。MySQL 推荐使用 MySQL5DialectMySQL8Dialect

初始化 SessionFactory

SessionFactory sessionFactory;
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build(); 
try {
    sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory(); 
} catch (Exception e) {
    e.printStackTrace();
}

⚠️ SessionFactory 是线程安全的,应用启动时初始化一次即可。

执行查询

Session session = sessionFactory.openSession();
session.beginTransaction();

List<Person> result = session.createQuery("from Person", Person.class).list();
        
result.forEach(person -> {
    // 处理 Person 对象
});
        
session.getTransaction().commit();
session.close();

✅ 使用 HQL(Hibernate Query Language)可实现数据库无关性。


4.2 MyBatis

MyBatis 是一个“半自动化”ORM 框架,主打 SQL 与代码分离,适合对 SQL 有强控制需求的场景。

添加依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

Mapper 接口定义

public interface PersonMapper {
    String selectAll = "SELECT * FROM Person"; 
    
    @Select(selectAll)
    @Results(value = {
       @Result(property = "id", column = "ID"),
       @Result(property = "firstName", column = "FIRST_NAME"),
       @Result(property = "lastName", column = "LAST_NAME")
    })
    List<Person> selectAll();
}

📌 注解方式适合简单场景,复杂 SQL 建议使用 XML 配置。

手动配置 MyBatis

Configuration initMybatis() throws SQLException {
    DataSource dataSource = getDataSource();
    TransactionFactory trxFactory = new JdbcTransactionFactory();
    
    Environment env = new Environment("dev", trxFactory, dataSource);
    Configuration config = new Configuration(env);
    TypeAliasRegistry aliases = config.getTypeAliasRegistry();
    aliases.registerAlias("person", Person.class);

    config.addMapper(PersonMapper.class);
    return config;
}

DataSource getDataSource() throws SQLException {
    MysqlDataSource dataSource = new MysqlDataSource();
    dataSource.setDatabaseName("test");
    dataSource.setServerName("localhost");
    dataSource.setPort(3306);
    dataSource.setUser("root");
    dataSource.setPassword("password123");
    dataSource.setServerTimezone("UTC");
    
    return dataSource;
}

使用 SqlSession 执行查询

Configuration configuration = initMybatis();
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
try (SqlSession session = sqlSessionFactory.openSession()) {
    PersonMapper mapper = session.getMapper(PersonMapper.class);
    List<Person> persons = mapper.selectAll();
    
    // 处理结果...
}

✅ MyBatis 简单粗暴,适合需要精细控制 SQL 的项目。


4.3 Apache Cayenne

Cayenne 是一个老牌 ORM,支持可视化建模,适合遗留系统迁移或需要图形化设计的场景。

添加依赖

<dependency>
    <groupId>org.apache.cayenne</groupId>
    <artifactId>cayenne-server</artifactId>
    <version>4.0.2</version>
</dependency>

配置 cayenne-project.xml

<?xml version="1.0" encoding="utf-8"?>
<domain project-version="9"> 
    <map name="datamap"/> 
    <node name="datanode" 
        factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory" 
        schema-update-strategy="org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy"> 
        <map-ref name="datamap"/> 
        <data-source>
            <driver value="com.mysql.cj.jdbc.Driver"/> 
            <url value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"/> 
            <connectionPool min="1" max="1"/> 
            <login userName="root" password="password123"/> 
        </data-source> 
    </node> 
</domain>

执行查询

ServerRuntime cayenneRuntime = ServerRuntime.builder()
    .addConfig("cayenne-project.xml")
    .build();

ObjectContext context = cayenneRuntime.newContext();
List<Person> persons = ObjectSelect.query(Person.class).select(context);

// 处理 persons...

⚠️ Cayenne 需要生成 datamap.map.xml 和实体类,建议使用其建模工具。


5. 使用 Spring Data 连接

Spring Data 极大简化了数据访问层开发,是现代 Spring 项目的首选方案。

5.1 Spring Data JPA

基于 JPA 的封装,提供 CrudRepository 接口,自动生成基本 CRUD 方法。

添加依赖

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>

配置类

@Configuration
@EnableJpaRepositories("com.example.repository")
public class JpaConfiguration {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("password123");
        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
      return new JpaTransactionManager(emf);
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
      HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
      jpaVendorAdapter.setDatabase(Database.MYSQL);
      jpaVendorAdapter.setGenerateDdl(true);
      return jpaVendorAdapter;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean lemfb = new LocalContainerEntityManagerFactoryBean();
      lemfb.setDataSource(dataSource());
      lemfb.setJpaVendorAdapter(jpaVendorAdapter());
      lemfb.setPackagesToScan("com.example.entity");
      return lemfb;
    }
}

Repository 接口

@Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
}

查询示例

personRepository.findAll().forEach(person -> {
    // 处理每个 person
});

✅ 开箱即用,适合快速开发,支持分页、排序、自定义查询等。


5.2 Spring Data JDBC

轻量级替代方案,不支持缓存、延迟加载等 JPA 特性,但更简单透明。

添加依赖

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jdbc</artifactId>
    <version>1.1.4.RELEASE</version>
</dependency>

配置类

@Configuration
@EnableJdbcRepositories("com.example.repository")
public class JdbcConfiguration extends AbstractJdbcConfiguration {
    @Bean
    NamedParameterJdbcOperations operations() {
        return new NamedParameterJdbcTemplate(dataSource());
    }

    @Bean
    PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("password123");
        return dataSource;
    }
}

实体类(需加 Spring 注解)

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

@Table(value = "Person")
public class Person {
    @Id
    Long id;

    @Column(value = "FIRST_NAME")
    String firstName;

    @Column(value = "LAST_NAME")
    String lastName;

    // getters and setters
}

📌 Spring Data JDBC 要求实体类使用其注解进行映射,不再依赖 JPA。

使用方式与 JPA 一致

personRepository.findAll().forEach(person -> {
    // 处理数据
});

✅ 适合不想引入 JPA 复杂性的项目,性能更可控。


6. 总结

本文系统梳理了 Java 连接 MySQL 的主流方案:

方案 优点 缺点 适用场景
✅ JDBC 灵活、无依赖 样板代码多 学习基础、极简场景
✅ Hibernate 功能全、生态成熟 配置复杂 传统企业应用
✅ MyBatis SQL 可控、灵活 需手动写 SQL 对 SQL 有强需求项目
⚠️ Apache Cayenne 支持图形化建模 社区小、文档少 遗留系统迁移
✅ Spring Data JPA 开发快、功能多 抽象层厚 Spring 项目首选
✅ Spring Data JDBC 轻量、透明 功能少 想避开 JPA 复杂性

📌 选型建议

  • 新项目优先考虑 Spring Data JPA
  • 需要精细控制 SQL 用 MyBatis
  • 追求轻量可用 Spring Data JDBC
  • 学习原理或写脚本可直接用 JDBC

每种方案都有其适用场景,关键是根据团队技术栈和项目需求做出合理选择。


原始标题:Connect Java to a MySQL Database