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 推荐使用 MySQL5Dialect
或 MySQL8Dialect
。
初始化 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
每种方案都有其适用场景,关键是根据团队技术栈和项目需求做出合理选择。