Java基础 - JDBC操作数据库(MySql)

这篇具有很好参考价值的文章主要介绍了Java基础 - JDBC操作数据库(MySql)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JDBC是Java语言操作数据库的一套接口,也就是规范,具体的实现需要各个数据库厂商去实现。比如我们在使用JDBC去连接mySql数据库的时候,我们必须要依赖一个叫做mysql-connector-java的jar包,这里面封装的就是mySql对于JDBC的实现。

Java中使用JDBC

首先引入mysql-connector-java依赖,比如maven项目的pom.xml文件中添加:

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

然后添加代码(一个简单的例子):

package org.example;

import java.sql.*;

public class JDBCTest {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {

        //Driver类加载,执行其静态代码块,完成驱动注册
        Class.forName("com.mysql.cj.jdbc.Driver");

        //准备用户名、密码、数据库地址
        String name = "root";
        String password = "root";
        String url = "jdbc:mysql://localhost:3306/book";

        //创建数据库连接
        Connection connection = DriverManager.getConnection(url, name, password);

        //创建一个PreparedStatement,字面意思"准备好的语句",用来执行具体的sql字符串
        String sql = "select * from book";
        PreparedStatement statement = connection.prepareStatement(sql);

        //执行sql,返回结果集
        ResultSet resultSet = statement.executeQuery();

        //处理结果集,逐行打印某一列数据
        //ResultSet的光标每次只能指向一条记录,初始定位在在第一行之前,需要调用其next()方法移动光标才能访问记录
        while (resultSet.next()) {
            System.out.println(resultSet.getString("book_name"));
        }

        //释放资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

Spring boot对JDBC的封装

Spring框架对JDBC的支持,暴露在用户层面,最常见的是一个叫做JdbcTemplate的类,封装了各种对数据库的操作。

JdbcTemplate的使用:
1、确保pom.xml中有以下两个依赖(这里由于添加了spring-boot-starter-parent这种标签,可以不写版本号)

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

点开这个spring-boot-starter-jdbc,可以看到主要是添加了HikariCP这个数据源,以及spring-jdbc的代码库。

2、数据源属性的配置,application.yml配置文件中添加如下配置:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/book
    username: root
    password: root

3、在bean中引入JdbcTemplate依赖,业务代码中使用JdbcTemplate执行相关操作,示例如下:

package org.example.service.impl;

import org.example.domain.Book;
import org.example.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 查询全部图书
     * @return
     */
    @Override
    public List<Book> getAllBooks() {
        List<Book> books = jdbcTemplate.query("select * from book", new RowMapper<Book>() {
            @Override
            public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
                Book book = new Book();
                book.setBookId(rs.getInt("book_id"));
                book.setBookName(rs.getString("book_name"));
                book.setBookDesc(rs.getString("book_desc"));
                book.setPublishTime(rs.getDate("publish_time"));
                return book;
            }
        });
        return books;
    }

    /**
     * 更新某个图书
     * @param book
     * @return
     */
    @Override
    public Boolean updateBookMessage(Book book) {
        String sql = "update book set book_desc = ? where book_id = ?";
        Object[] params = new Object[]{book.getBookDesc(), book.getBookId()};
        jdbcTemplate.update(sql, params);
        return true;
    }
}

到这里简单的JdbcTemplate的使用就完成了。

JdbcTemplate的实例化过程

既然JdbcTemplate能用@Autowired自动注入,但我们又没有手动配置这个bean,那么它是如何自动注册成为bean,然后实例化的呢?

配置类解析阶段

1、spring boot在启动过程中,在bean的实例化之前,会对配置类进行解析和注册bean definition。
首先在解析带有@SpringBootApplication的启动类时,会处理里面的@Import(AutoConfigurationImportSelector.class)这个注解(由于是DeferredImportSelector,暂存起来等启动类解析完后再处理);
处理过程中会读取META-INF目录下的spring.factories文件,其中包含了很多启用自动配置(EnableAutoConfiguration)的目标类,这里面就有和JdbcTemplate相关的JdbcTemplateAutoConfiguration类,于是我们找到了线索。
mysql-connector-java,java,数据库,mysql
2、接下来我们找到JdbcTemplateAutoConfiguration类的源码:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(JdbcProperties.class)
@Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class,
		NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {

}

这个类没有做什么实际操作,只是约束了一些自动配置的依赖关系,然后使用@Import注解引入了JdbcTemplateConfiguration这个类。
解析当前类时就会解析JdbcTemplateConfiguration类。

3、接下来看看JdbcTemplateConfiguration类:

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {

	@Bean
	@Primary
	JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
		JdbcProperties.Template template = properties.getTemplate();
		jdbcTemplate.setFetchSize(template.getFetchSize());
		jdbcTemplate.setMaxRows(template.getMaxRows());
		if (template.getQueryTimeout() != null) {
			jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
		}
		return jdbcTemplate;
	}

}

条件注解@ConditionalOnMissingBean(JdbcOperations.class):在没有JdbcOperations类型的bean时才加载当前类。
@Bean方法,返回值类型为JdbcTemplate,而JdbcTemplate恰好就实现了JdbcOperations接口,所以这里@ConditionalOnMissingBean注解的作用,就是当用户自己配置了JdbcOperations接口实现类的bean,并且已经注册时,spring就不会再自动注册jdbcTemplate了。

bean definition注册阶段

配置类解析完,会进行集中处理,注册bean definition。当处理到JdbcTemplateConfiguration这个配置类时,会解析@Bean方法(spring将其视为生成bean对象的工厂方法),检测到@Bean注解没有name属性,则使用方法名"jdbcTemplate"注册一个bean definition。后续在推断jdbcTemplate的类型时,会使用其工厂方法的返回类型JdbcTemplate作为目标类型。

bean实例化阶段

4、现在jdbcTemplate这个bean已经注册上了,并且目标类型为JdbcTemplate。接下来在使用@Autowired注解注入jdbcTemplate实例时,就会使用到bean factory的getBeanNamesForType方法,根据类型找到jdbcTemplate这个bean,然后使用工厂方法,也就是带@Bean注解的jdbcTemplate(DataSource dataSource, JdbcProperties properties)方法进行实例化。

5、这时候只要保证 DataSource 和 JdbcProperties 这两个bean实例化完成,就能完成jdbcTemplate的实例化,我们就能用了。
实际上这个时候DataSource这个参数已经实例化完成了。

DataSource参数

1)DataSource一个数据源接口,那么应该有一个实现类注册了这个bean;或者类似 jdbcTemplate 那样有个配置类通过@Bean方法生成这个bean。
经过debug发现,datasource这个bean,是由org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari类的dataSource方法生成的:

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(HikariDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)
	static class Hikari {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.hikari")
		HikariDataSource dataSource(DataSourceProperties properties) {
			HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
			if (StringUtils.hasText(properties.getName())) {
				dataSource.setPoolName(properties.getName());
			}
			return dataSource;
		}

	}

由于spring-boot-starter-jdbc默认引入了Hikari的jar包,所以spring能够加载到这个配置类,并根据@Bean方法注册了一个名为"dataSource"的bean definition。

2)实例化dataSource时,要先确保DataSourceProperties参数的实例化。
先看看DataSourceProperties的代码:

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {

	private ClassLoader classLoader;

这个类不像常见的配置类那样使用@Configuration注解,而是使用了@ConfigurationProperties注解。
@ConfigurationProperties是用来绑定外部配置属性的注解,我们在applicaition.yml文件中配置的数据源属性,如下图:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/book
    username: root
    password: root

这里前缀正是对应了prefix = "spring.datasource"这个属性,包括后面的driver-class-name、url等属性,都是和DataSourceProperties类的成员变量一一对应的,后续在DataSourceProperties实例初始化的时候会进行解析和绑定。

DataSourceProperties这个bean是如何注册上的呢?
在DataSource的顶层自动配置类DataSourceAutoConfiguration中,使用了一个注解@EnableConfigurationProperties(DataSourceProperties.class),表示启用了DataSourceProperties这个类作为一个配置类,来支持外部配置的属性绑定。
在处理DataSourceAutoConfiguration并注册bean definition的过程中,调用了loadBeanDefinitionsFromRegistrars方法。这里使用了EnableConfigurationPropertiesRegistrar,顾名思义,它解析了@EnableConfigurationProperties的属性,然后注册了对应的bean definition。

DataSourceProperties这个bean又是如何绑定上我们定义的数据源配置的呢?
在DataSourceProperties实例化之后,在初始化过程中调用了initializeBean方法,允许一些BeanPostProcessor执行其postProcessBeforeInitialization方法,做特定的初始化工作;其中就有一个ConfigurationPropertiesBindingPostProcessor,通过bind方法对DataSourceProperties这个bean和配置文件中的属性进行了绑定。

还有一个问题,为什么在我们需要的jdbcTemplate实例化之前,DataSource就已经实例化了呢?
实际上在解析配置类的过程中,还有两个相关的bean被注册上了。

1)dataSourceScriptDatabaseInitializer,
有一个配置类叫做DataSourceInitializationConfiguration,它有一个@Bean方法,用来生成一个SqlDataSourceScriptDatabaseInitializer对象,这是一个数据库初始化器,用来获取数据库初始化相关的配置(比如sql脚本位置、用户名、密码等)。源码如下:

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean({ SqlDataSourceScriptDatabaseInitializer.class, SqlR2dbcScriptDatabaseInitializer.class })
@ConditionalOnSingleCandidate(DataSource.class)
@ConditionalOnClass(DatabasePopulator.class)
class DataSourceInitializationConfiguration {

	@Bean
	SqlDataSourceScriptDatabaseInitializer dataSourceScriptDatabaseInitializer(DataSource dataSource,
			SqlInitializationProperties properties) {
		return new SqlDataSourceScriptDatabaseInitializer(
				determineDataSource(dataSource, properties.getUsername(), properties.getPassword()), properties);
	}

	private static DataSource determineDataSource(DataSource dataSource, String username, String password) {
		if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
			return DataSourceBuilder.derivedFrom(dataSource).username(username).password(password)
					.type(SimpleDriverDataSource.class).build();
		}
		return dataSource;
	}

}

显然dataSourceScriptDatabaseInitializer 和我们的 jdbcTemplate 一样,也依赖 dataSource 这个 bean。

2)DependsOnDatabaseInitializationPostProcessor
它是org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer的静态内部类,实现了BeanFactoryPostProcessor接口,部分源码如下:

public class DatabaseInitializationDependencyConfigurer implements ImportBeanDefinitionRegistrar {

	private final Environment environment;

	DatabaseInitializationDependencyConfigurer(Environment environment) {
		this.environment = environment;
	}

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		String name = DependsOnDatabaseInitializationPostProcessor.class.getName();
		if (!registry.containsBeanDefinition(name)) {
			BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
					DependsOnDatabaseInitializationPostProcessor.class,
					this::createDependsOnDatabaseInitializationPostProcessor);
			registry.registerBeanDefinition(name, builder.getBeanDefinition());
		}
	}

	private DependsOnDatabaseInitializationPostProcessor createDependsOnDatabaseInitializationPostProcessor() {
		return new DependsOnDatabaseInitializationPostProcessor(this.environment);
	}

	/**
	 * {@link BeanFactoryPostProcessor} used to configure database initialization
	 * dependency relationships.
	 */
	static class DependsOnDatabaseInitializationPostProcessor implements BeanFactoryPostProcessor, Ordered {

		private final Environment environment;

		DependsOnDatabaseInitializationPostProcessor(Environment environment) {
			this.environment = environment;
		}

其实DatabaseInitializationDependencyConfigurer这个类在JdbcTemplateAutoConfiguration配置类中已经使用@Import注解引入了。
由于它实现了ImportBeanDefinitionRegistrar接口,重写了registerBeanDefinitions方法,所以在解析的时候会实例化一个对象作为注册器registrar,归属到配置类JdbcTemplateAutoConfiguration中。
在处理配置类JdbcTemplateAutoConfiguration的时候,最终也会调用loadBeanDefinitionsFromRegistrars方法,然后走到DatabaseInitializationDependencyConfigurer重写的registerBeanDefinitions方法,注册了一个DependsOnDatabaseInitializationPostProcessor。

3)配置类的解析和处理,包括注册bean definition的过程,其实是spring容器启动过程中,调用BeanDefinitionRegistryPostProcessor的过程;在此之后,还有一个调用BeanFactoryPostProcessor(前者的父接口)的过程,其中就会实例化DependsOnDatabaseInitializationPostProcessor并调用其postProcessBeanFactory方法。
DependsOnDatabaseInitializationPostProcessor会使用相关的探测器detector去探测到dataSourceScriptDatabaseInitializer这个bean,
然后再使用相关探测器探测到依赖数据库初始化的bean(其中一个探测器的探测方法是寻找实现 JdbcOperations 或者 NamedParameterJdbcOperations 接口的bean),最终找到了我们的 jdbcTemplate,
然后将dataSourceScriptDatabaseInitializer设置成jdbcTemplate的依赖。所以在jdbcTemplate实例化前,已经先实例化了dataSourceScriptDatabaseInitializer以及他们依赖的DataSource。

JdbcProperties参数

JdbcProperties类源码:

@ConfigurationProperties(prefix = "spring.jdbc")
public class JdbcProperties {

	private final Template template = new Template();

	public Template getTemplate() {
		return this.template;
	}

JdbcProperties 和 刚才分析的 DataSourceProperties非常相似,都使用@ConfigurationProperties注解,bean注册和实例化的方式也和DataSourceProperties一样,这里不再分析。
该bean绑定的是以 spring.jdbc 为前缀的,提供给jdbcTemplate使用的配置,比如spring.jdbc.template.max-rows。文章来源地址https://www.toymoban.com/news/detail-824636.html

到了这里,关于Java基础 - JDBC操作数据库(MySql)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL数据库之JDBC编程(从认识到操作)

    目录 前言 一.JDBC的认识 1.1JDBC的来源 1.2JDBC的概念 二.JDBC的导包  三.JDBC的四步操作 三.JDBC常用的类和方法  3.1常用类 3.2常见方法 🎁个人主页:tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主 🎥 本文由 tq02 原创,首发于 CSDN🙉 🎄 本章讲解内容: JDBC的详细讲解 🎥学习

    2024年02月15日
    浏览(46)
  • 【JDBC】Java连接MySQL数据库

    数据库编程指的是通过编程语言与数据库进行交互和操作的过程,包括使用编程语言创建、连接、查询、更新和删除数据库中的数据,以及管理数据库结构和其他相关工作等。 另外,不同的数据库,对应不同的编程语言提供了不同的数据库驱动包,如:MySQL提供了Java的驱动包

    2024年02月15日
    浏览(142)
  • Java的JDBC编程—连接Mysql数据库

    目录 一、 Java的数据库编程:JDBC 二、JDBC工作原理 三、 JDBC使用 四、JDBC使用步骤总结  五. JDBC常用接口和类 5.1 JDBC API 5.2 数据库连接Connection 5.3 Statement对象 5.4 ResultSet对象      JDBC,即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,它是 Java中的数据

    2024年02月05日
    浏览(78)
  • 【JavaEE基础学习打卡04】JDBC之MySQL数据库安装

    📜 本系列教程适用于JavaWeb初学者、爱好者,小白白。我们的天赋并不高,可贵在努力,坚持不放弃。坚信量最终引发质变,厚积薄发。 🚀 文中白话居多,尽量以小白视角呈现,帮助大家快速入门。 🎅 我是 蜗牛老师 ,之前网名是 Ongoing蜗牛 ,人如其名,干啥都慢,所以

    2024年02月12日
    浏览(41)
  • Java连接mysql数据库方法及代码(jdbc)

    编译器使用IDEA 我的相关博客: java代码程序中连接mysql数据库的方法及代码 mysql数据库并发上锁问题,java代码 1.首先从mysql官网下载mysql-connector-java.jar包到本地。 这里注意要和你本地的mysql数据库版本相匹配! 下载相应的压缩包,在本地解压即可进行下一步操作。 2.打开自己

    2024年02月08日
    浏览(67)
  • Java-JDBC建立数据库连接(MySQL)

    注意:连接数据需要先在JAVA中导入mysql的jar包。 1.1—下载JAR包 1、打开浏览器搜索MySQL,进入官网 2、点击DOWNLOADS    3、点击 MySQL Community (GPL) Downloads  4、点击Connector/J 5、点击Archieve 6、选择版本,和OS,然后点击下载即可。          版本号 下载地址 8.0.32 https://download

    2024年02月03日
    浏览(77)
  • java代码实现,利用JDBC接口-连接Mysql数据库

    1、JDBC本质上是一个接口,也就是java语言操作数据库的一套API(应用程序编程接口), 接口就规则,也就是sun公司创建了一个jdbc接口,各个sql(数据库管理系统)去实现接口提供jar包。其优点JDBC不是指单一操作某一个数据库。各个厂商使用相同的接口。不同的sql厂家实现

    2024年02月09日
    浏览(71)
  • java连接mysql8.0数据库—jdbc连接

    mysql官网 点击platform Independent ,然后出现jar包选项 点download 点左下角no thanks,直接下载 原始方法,直接在项目下建一个lib包 然后将刚刚下好的zip解压,复制jar包到该目录下,右键jar包,选择add as Library 出现一堆包,表示成功导入jar包 注意:Driver类创建时,要导入com.mysql.cj.

    2024年02月13日
    浏览(65)
  • 【Java】IntelliJ IDEA使用JDBC连接MySQL数据库并写入数据

    在 IntelliJ IDEA 中连接 MySQL 数据库并将数据存储在数据表中,使用 Java 和 JDBC(Java Database Connectivity)实现。 下载并安装 IntelliJ IDEA 下载并安装 MySQL 数据库 下载 MySQL Connector/J 驱动程序(JDBC 驱动程序) 使用 Navicat 创建一个 MySQL 数据库 打开 IntelliJ IDEA。 选择 \\\"File\\\"→ “New” →

    2024年02月05日
    浏览(85)
  • java中连接数据库com.mysql.jdbc.Driver和com.mysql.cj.jdbc.Driver的区别?

    com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 是MySQL数据库连接驱动的不同版本。 com.mysql.jdbc.Driver :这是旧版的MySQL JDBC驱动(版本5.x)。它已经过时,不再推荐使用。如果您使用较旧的MySQL版本(如MySQL 5.7及以下),可以考虑使用此驱动。但请注意,该驱动在MySQL 8.0及更高版本上可

    2024年02月14日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包