本文大致介绍JDBC,数据库连接池,MyBatis框架。以及Java连接数据库的不同方式,包括原生JDBC的连接,JDBC使用Druid连接数据库,MyBatis框架连接数据库,Spring整合MyBatis连接数据库
JDBC
JDBC简介
JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API。
本质:
sun公司官方定义的一套操作所有关系型数据库的规范,即接口。
各个数据库厂商去实现这套接口,提供数据库驱动jar包(实际上就是实现sun公司接口的实现类)。
我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
通过JDBC就可以用一套Java代码操作不同的关系型数据库。
Demo
- pom文件导入mysql驱动
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
- 利用JDBC操作数据库
public class jdbcDemo {
private static final String url = "jdbc:mysql://localhost:3306/student";
private static final String username = "root";
private static final String password = "123456";
public static void main(String[] args) throws Exception {
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接
Connection connection = DriverManager.getConnection(url, username, password);
// 3. 定义sql
String sql = "UPDATE primaryinfo SET age = 21 WHERE name = 'Lysssyo'";
// 4. 获取执行sql的对象
Statement statement = connection.createStatement();
// 5. 执行sql
int count = statement.executeUpdate(sql); // 返回值为受影响的行数
// 6. 处理结果
System.out.println(count);
// 7. 释放资源
statement.close();
connection.close();
}
}
Class.forName("com.mysql.jdbc.Driver");
这段代码做了这些事情:
- 加载驱动类:
Class.forName
方法动态加载指定的驱动类。在这里,加载的是com.mysql.jdbc.Driver
类,这是 MySQL 的 JDBC 驱动类。- 静态初始化块:在加载驱动类时,
com.mysql.jdbc.Driver
类的静态初始化块会被执行。这个静态初始化块会注册驱动程序实例到DriverManager
。源码:
public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }
- 注册驱动:驱动程序的注册是通过
DriverManager
类的registerDriver
方法完成的。注册的驱动程序会被添加到DriverManager
管理的驱动程序列表中。
JDBC的API
-
DriverManager:驱动管理类
-
注册驱动
上面的demo中的
Class.forName("com.mysql.jdbc.Driver");
可以看出,这段代码的底层是是通过DriverManager
类的registerDriver
方法完成驱动的注册。 -
获取数据库连接
DriverManager
的getConnection
方法:static Connection getConnection(string url,string user,string password)
其中,参数url的语法为
jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2
示例:jdbc:mysql://127.0.0.1:3306/db1?useSSL=falsejdbc:mysql
是一个可以看作一个协议,指用jdbc连接mysql数据库参数键值对配置 useSSL=false 参数,可以禁用安全连接方式,解决警告提示
-
-
Connection:数据库连接接口
-
获取执行sql的对象
例如:
Statement statement = connection.createStatement();
-
管理事务
-
-
Statement:执行sql的接口
-
执行sql
例如:
int count = statement.executeUpdate(sql); // 返回值为受影响的行数
-
数据库连接池
数据库连接池简介
数据库连接池是个容器,负责分配、管理数据库连接(Connection)。它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。此外,数据库连接池还会释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。
好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
避免数据库连接遗漏是指在应用程序执行完数据库操作后,及时释放数据库连接,以确保连接池中的连接能够得到有效的重复利用,并防止数据库连接资源泄漏
数据库连接池实现
标准接口:DataSource
-
官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口。
-
功能:获取连接
Connection getConnection()
常见的数据库连接池:
- DBCP
- C3P0
- Druid
Druid连接池是阿里巴巴开源的数据库连接池项目,功能强大,性能优秀,是Java语言最好的数据库连接池之一
利用数据库连接池,Connection对象不再通过DriverManager获取而是通过第三方实现的DataSource接口的getConnection方法获取
使用Druid数据库连接池
- 导入坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
- 定义配置文件
#ruid.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间(毫秒)
# 程序向连接池中请求连接时,超过maxWait的值后,认为本次请求失败,即连接池没有可用连接,设置-1时表示无限等待
maxWait=3000
-
加载配置文件
-
获取数据库连接池对象
-
获取连接
// 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src/druid.properties"));
//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//获取数据库连接 Connection
Connection connection = dataSource.getConnection();
完整代码:
public class jdbcDemo {
public static void main(String[] args) throws Exception {
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接
// 2.1 加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src/druid.properties"));
// 2.2 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 2.3 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
// 3. 定义sql
String sql = "UPDATE primaryinfo SET age = 20 WHERE name = 'Lysssyo'";
// 4. 获取执行sql的对象
Statement statement = connection.createStatement();
// 5. 执行sql
int count = statement.executeUpdate(sql); // 返回值为受影响的行数
// 6. 处理结果
System.out.println(count);
// 7. 释放资源
statement.close();
connection.close();
}
}
MyBatis
MyBatis简介
-
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
-
MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
-
官网:https://mybatis.org/mybatis-3/zh/index.html
- 持久层:指的是就是数据访问层(dao),是用来操作数据库的。
- 框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展。
从上面JDBC的demo可以看出,通过原生JDBC连接数据库存在硬编码,操作繁琐的问题,MyBatis可以简化JDBC的开发
图中XML配置使用的是PooledConnectionDataSource,它是MyBatis中的一种连接池实现。PooledConnectionDataSource是一个基于Apache Commons Pool的简单连接池,用于管理数据库连接。这个连接池在MyBatis中默认提供,可以通过配置文件来配置连接池的参数,如最大活动连接数、最大空闲连接数等。
Demo——查询User表中的数据
- 导入坐标
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
- 创建核心配置文件
<!--mybatis-config.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
- 编写sql映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<select id="selectAll" resultType="com.lysssyo.pojo.User">
select * from user;
</select>
</mapper>
- 编码
public class MyBatisDemo {
public static void main(String[] args) throws IOException {
// 1. 加载MyBatis核心配置文件,获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
// 通常情况下,当资源文件(比如配置文件、属性文件等)位于项目的 resources 目录下时,可以直接使用相对路径来加载
// 因为在编译后,这些资源文件会被打包到类路径下,可以通过类加载器直接访问到。
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.获取sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3. 执行sql语句
List<User> users = sqlSession.selectList("test.selectAll");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
程序可以正常运行,但是连接信息是硬编码在mybatis-config.xml中的,可以再写一个properties解耦:
#jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_test?useSSL=false
jdbc.username=root
jdbc.password=123456
修改mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--这里指明要加载jdbc.properties-->
<properties resource="jdbc.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--连接信息-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--省略-->
</mappers>
</configuration>
Mapper代理
步骤:
- 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
编译后的代码都在类路径(classes)下,resources的配置文件也是在类路径下:
如果想要resources中的SQL映射文件与mapper在同一目录下,只需要在resources中建与接口同样层次的包就可以了:
- 设置SQL映射文件的namespace属性为Mapper接口全限定名
<mapper namespace="com.lysssyo.mapper.UserMapper">
<select id="selectAll" resultType="com.lysssyo.pojo.User">
select * from user;
</select>
</mapper>
- 在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
public interface UserMapper {
List<User> selectAll();
}
-
编码:
-
通过 SqlSession 的 getMapper方法获取 Mapper接囗的代理对象
-
调用对应方法完成sql的执行
-
public class MyBatisDemo {
public static void main(String[] args) throws IOException {
// 1. 加载MyBatis核心配置文件,获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.获取sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3. 执行sql语句
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
}
如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式优化SQL映射文件的加载
前面已经做到了Mapper接口名和SQL映射文件名相同且在同一目录下,所以可以用包扫描的方式化SQL映射文件的加载,即mybatis-config.xml可以这样写:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<!--省略environment-->
</environments>
<mappers>
<!--加载sql映射文件-->
<!--<mapper resource="com/lysssyo/mapper/UserMapper.xml"/>-->
<!--Mapper代理的方式-->
<package name="com.lysssyo.mapper"/>
</mappers>
</configuration>
与Spring框架整合
Druid连接池与Spring框架整合
IOC/DI配置管理Druid
环境准备:
- pom.xml添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- 配置spring的配置文件,resources下添加spring的配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
- 编码启动类
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
利用配置实现Druid管理:
- 导入Druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
- 在applicationContext.xml配置文件中添加
DruidDataSource
的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--管理DruidDataSource对象-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
</beans>
- 从IOC容器中获取对应的bean对象
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);
}
}
结果:
IOC/DI注解开发管理第Druid
环境准备:
- pom.xml添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
- 添加一个配置类
SpringConfig
@Configuration
public class SpringConfig {
}
- 创建启动类
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
}
}
利用注解实现Druid管理:
- 导入Druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
- 在配置类中添加一个方法,并在方法上加@Bean
@Configuration
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
- 从IOC容器中获取对应的bean对象
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource);
}
}
优化:
如果把所有的第三方bean都配置到Spring的配置类SpringConfig
中,虽然可以,但是不利于代码阅读和分类管理,所有我们就想能不能按照类别将这些bean配置到不同的配置类中?
对于数据源的bean,我们新建一个JdbcConfig
配置类,并把数据源配置到该类下。
public class JdbcConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
}
然后,在SpringConfig中引入这个配置类
@Configuration
@Import({JdbcConfig.class})
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
}
此外,Driver,url这些是以硬编码的方式写在配置类中,不够优雅也不利于维护,应该另写一个properties给它
#jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_test?useSSL=false
jdbc.username=root
jdbc.password=123456
然后在SpringConfig引用它:
@Configuration
@Import({JdbcConfig.class})
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
}
改写JdbcConfig
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("jdbc.url")
private String url;
@Value("jdbc.username")
private String userName;
@Value("jdbc.password")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
MyBatis框架与Spring框架整合
IOC/DI注解开发管理MyBatis
- 导入Spring,MySql,MyBatis的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
- 导入Spring操作数据库的坐标,MyBatis与Spring整合的坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
- 编写MyBatis核心配置类
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setTypeAliasesPackage("com.lysssyo.pojo");
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer=new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.lysssyo.mapper");
return mapperScannerConfigurer;
}
}
与MyBatis的配置文件类比:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--连接信息-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--Mapper代理的方式-->
<package name="com.lysssyo.mapper"/>
</mappers>
</configuration>
配置文件中的datasource标签是设置数据源,用注解开发管理MydataBatis时,是通过形参把IOC容器中的DruidBean对象引入的,从而设置datasource
而mapperScannerConfigurer这个Bean对象,对应配置文件中的mappers标签
- SpringConfig引入这个配置类
@Configuration
@Import({JdbcConfig.class, MybatisConfig.class})
@PropertySource({"classpath:jdbc.properties"})
@ComponentScan("com.lysssyo")
public class SpringConfig {
}
- 测试
public class SpringDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = ctx.getBean(UserService.class);
List<User> users = userService.getAllUsers();
for (User user : users) {
System.out.println(user);
}
}
}