Java连接MySQL教程

一、概述#

我们可以通过多种方式从 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.xmlPerson之后,我们可以执行一些查询。

例如,我们将像以前一样继续全选:

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,需要更多的配置,但具有显着优势,因为它们提供了默认实现和特性,如缓存和延迟加载。