一、概述#
我们可以通过多种方式从 Java 连接到 MySQL 数据库,在本教程中,我们将探索几个选项来了解如何实现这一点。
我们将从使用 JDBC 和 Hibernate 可以说是最流行的选项开始。
然后,我们还将查看一些外部库,包括 MyBatis、Apache Cayenne 和 Spring Data。在此过程中,我们将提供一些实际示例。
2. 前提条件#
我们假设我们已经在 localhost(默认端口 3306)上安装并运行了 MySQL 服务器,并且我们有一个包含以下 person 表的测试模式:
CREATE TABLE person ( ID INT, FIRST_NAME VARCHAR(100), LAST_NAME VARCHAR(100) );
我们还需要mysql-connector-java工件,它一如既往地可以从Maven Central获得:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency>
3. 使用 JDBC 连接#
JDBC(Java 数据库连接)是一种用于连接和执行数据库查询的 API。
3.1 共同属性#
在本文的过程中,我们通常会使用几个常见的 JDBC 属性:
1.连接 URL – JDBC 驱动程序用于连接数据库的字符串。它可以包含诸如在哪里搜索数据库、要连接到的数据库的名称和其他配置属性等信息:
jdbc:mysql://[host][,failoverhost...] [:port]/[database] [?propertyName1][=propertyValue1] [&propertyName2][=propertyValue2]...
我们将像这样设置这个属性:jdbc:mysql://localhost:3306/test?serverTimezone=UTC
2.驱动程序类——要使用的驱动程序的完全限定类名。在我们的例子中,我们将使用 MySQL 驱动程序:com.mysql.cj.jdbc.Driver
3.用户名和密码 – MySQL 帐户的凭据
3.2. JDBC 连接示例#
让我们看看如何连接到数据库并通过try-with-multiple-resources执行简单的全选:
String sqlSelectAllPersons = "SELECT * FROM person"; String connectionUrl = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC"; try (Connection conn = DriverManager.getConnection(connectionUrl, "username", "password"); 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"); // do something with the extracted data... } } catch (SQLException e) { // handle the exception }
正如我们所见,在try体内,我们遍历结果集并从 person 表中提取值。
4. 使用 ORM 连接#
更典型的是,我们将使用对象关系映射 (ORM) 框架连接到我们的 MySQL 数据库。因此,让我们看一些使用这些框架中更流行的连接示例。
4.1。本机 Hibernate API#
在本节中,我们将看到如何使用Hibernate来管理与数据库的 JDBC 连接。
首先,我们需要添加hibernate-core Maven 依赖:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.10.Final</version> </dependency>
Hibernate 要求必须为每个表创建一个实体类。让我们继续定义Person类:
@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 资源文件,通常命名为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> <!-- Database connection settings --> <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">username</property> <property name="connection.password">password</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- Validate the database schema on startup --> <property name="hbm2ddl.auto">validate</property> <!-- Names the annotated entity class --> <mapping class="Person"/> </session-factory> </hibernate-configuration>
Hibernate 有许多配置属性。除了标准的连接属性,值得一提的是 dialect 属性,它允许我们为数据库指定 SQL 方言的名称。
框架使用此属性将Hibernate 查询语言(HQL) 语句正确转换为我们给定数据库的适当 SQL。Hibernate 附带了 40 多种SQL 方言。由于我们在本文中关注 MySQL,因此我们将坚持使用MySQL5Dialect方言。
最后,Hibernate 还需要通过映射标签知道实体类的完全限定名称。完成配置后,我们将使用SessionFactory类,该类负责创建和池化 JDBC 连接。
通常,这只需要为应用程序设置一次:
SessionFactory sessionFactory; // configures settings from hibernate.cfg.xml StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build(); try { sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory(); } catch (Exception e) { // handle the exception }
现在我们已经建立了连接,我们可以运行一个查询来从我们的人员表中选择所有人员:
Session session = sessionFactory.openSession(); session.beginTransaction(); List<Person> result = session.createQuery("from Person", Person.class).list(); result.forEach(person -> { //do something with Person instance... }); session.getTransaction().commit(); session.close();
4.2. MyBatis#
MyBatis于 2010 年推出,是一个以简单为强项的 SQL 映射器框架。在另一个教程中,我们讨论了如何将 MyBatis 与 Spring 和 Spring Boot 集成。在这里,我们将重点介绍如何直接配置 MyBatis。
要使用它,我们需要添加mybatis依赖:
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency>复制
假设我们在没有注释的情况下重用了上面的Person类,我们可以继续创建一个PersonMapper接口:
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(); }
下一步就是关于 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("username"); dataSource.setPassword("password"); dataSource.setServerTimezone("UTC"); return dataSource; }
配置包括创建一个配置对象,该对象是环境等设置的容器。它还包含数据源设置。
然后我们可以使用Configuration对象,通常为应用程序设置一次以创建SqlSessionFactory:
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(); // do something with persons list ... }
4.3. Apache Cayenne#
Apache Cayenne是一个持久性框架,其第一个版本可以追溯到 2002 年。要了解有关它的更多信息,我们建议阅读我们对 Apache Cayenne 的介绍。
像往常一样,让我们添加cayenne-server Maven 依赖项:
<dependency> <groupId>org.apache.cayenne</groupId> <artifactId>cayenne-server</artifactId> <version>4.0.2</version> </dependency>
我们将特别关注 MySQL 连接设置。在这种情况下,我们将配置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="username" password="password"/> </data-source> </node> </domain>
在以 CayenneDataObject 的形式自动生成datamap.map.xml和Person类之后,我们可以执行一些查询。
例如,我们将像以前一样继续全选:
ServerRuntime cayenneRuntime = ServerRuntime.builder() .addConfig("cayenne-project.xml") .build(); ObjectContext context = cayenneRuntime.newContext(); List<Person> persons = ObjectSelect.query(Person.class).select(context); // do something with persons list...
5. 使用 Spring Data 连接#
Spring Data是一种基于 Spring 的数据访问编程模型。从技术上讲,Spring Data 是一个伞式项目,其中包含许多特定于给定数据库的子项目。
让我们看看如何使用其中两个项目连接到 MySQL 数据库。
5.1 Spring Data / JPA#
Spring Data JPA 是一个健壮的框架,有助于减少样板代码,并提供一种机制来通过几个预定义的存储库接口之一实现基本的 CRUD 操作。除此之外,它还有许多其他有用的功能。
请务必查看我们对 Spring Data JPA 的介绍以了解更多信息。
spring-data-jpa工件可以在Maven Central上找到:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>2.2.4.RELEASE</version> </dependency>
我们将继续使用Person类。下一步是使用注解配置 JPA:
@Configuration @EnableJpaRepositories("packages.to.scan") 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( "username" ); dataSource.setPassword( "password" ); 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("packages.containing.entity.classes"); return lemfb; } }
为了让 Spring Data 实现 CRUD 操作,我们必须创建一个扩展CrudRepository接口的接口:
@Repository public interface PersonRepository extends CrudRepository<Person, Long> { }
最后,让我们看一个使用 Spring Data 的全选示例:
personRepository.findAll().forEach(person -> { // do something with the extracted person });复制
5.2. Spring Data / JDBC#
Spring Data JDBC 是 Spring Data 系列的有限实现,其主要目标是允许对关系数据库进行简单访问。
出于这个原因,它不提供缓存、脏跟踪、延迟加载和许多其他 JPA 特性等特性。
这次我们需要的 Maven 依赖是spring-data-jdbc:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jdbc</artifactId> <version>1.1.4.RELEASE</version> </dependency>
与我们在上一节中为 Spring Data JPA 使用的配置相比,该配置更轻:
@Configuration @EnableJdbcRepositories("packages.to.scan") public class JdbcConfiguration extends AbstractJdbcConfiguration { // NamedParameterJdbcOperations is used internally to submit SQL statements to the database @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("username"); dataSource.setPassword("password"); return dataSource; } }
对于 Spring Data JDBC,我们必须定义一个新的Person类或修改现有的类以添加一些 Spring 特定的注释。
这是因为 Spring Data JDBC 将直接处理实体映射而不是 Hibernate:
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,我们还可以使用CrudRepository接口。因此,声明将与我们在上面的 Spring Data JPA 示例中编写的声明相同。同样,这同样适用于全选示例。
六,结论#
在本教程中,我们看到了从 Java 连接到 MySQL 数据库的几种不同方法。我们从基本的 JDBC 连接开始。然后我们查看了常用的 ORM,如 Hibernate、Mybatis 和 Apache Cayenne。最后,我们看了一下 Spring Data JPA 和 Spring Data JDBC。
使用 JDBC 或 Hibernate API 意味着更多样板代码。使用健壮的框架,如 Spring Data 或 Mybatis,需要更多的配置,但具有显着优势,因为它们提供了默认实现和特性,如缓存和延迟加载。