目录
[MyBatis 框架:](#MyBatis 框架:)
[编写持久层(dao层)接口 并写sql语句:](#编写持久层(dao层)接口 并写sql语句:)
[JDBC MyBatis 优缺点:](#JDBC MyBatis 优缺点:)
JDBC:
JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API
1).创建一个数据库 web,并在该数据库中创建user表
sql
create table user(
id int unsigned primary key auto_increment comment 'ID,主键',
username varchar(20) comment '用户名',
password varchar(32) comment '密码',
name varchar(10) comment '姓名',
age tinyint unsigned comment '年龄'
) comment '用户表';
insert into user(id, username, password, name, age) values (1, 'daqiao', '123456', '大乔', 22),
(2, 'xiaoqiao', '123456', '小乔', 18),
(3, 'diaochan', '123456', '貂蝉', 24),
(4, 'lvbu', '123456', '吕布', 28),
(5, 'zhaoyun', '12345678', '赵云', 27);
JDBC基本语法 :
java
public static void main(String[] args) {
// 目标:掌握JDBC操作数据库的基本程序。
// 1、配置MySQL数据库的驱动依赖。
// 2、使用JDBC代码操作数据库。
try {
// 3、加载驱动对象。
Class.forName("com.mysql.jdbc.Driver");
// 4、通过驱动管理器获取与数据库的链接对象。
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dlei01", "root", "dlei");
// 5、通过链接对象获取数据库操作对象Statement。
Statement stm = conn.createStatement();
// 6、通过stm对象发送sql语句到数据库操作
String sql = "update tb_user set username = '灭绝师太' where id = 15";
// 7、正式发送,返回修改的数量。
int count = stm.executeUpdate(sql);
// 8、处理结果。
System.out.println("成功修改了几条数据:" + count);
// 9、关闭资源。
stm.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
1.加载类驱动对象 回自动把对象 封装到 DiverManager 类中运用 动态代理 在调用静态方法 getConnection时 把可以 获取 数据库的url 用户名 和密码 并且 用类驱动对象 链接数据库
- 通过链接对象 conn 获取数据库操作对象 Statement 通过 Statement的 方法 executeUpdate 正式发送sql语句 返回 修改的数量
java
public static void main(String[] args) {
// 目标:理解预编译的方案(重点)
try {
// 1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取链接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/dlei01", "root", "dlei");
// 3、准备sql语句
String sql = "select * from tb_user where username = ? and password= ?";
// 4、获取执行sql对象PreparedStatement
PreparedStatement pstm = conn.prepareStatement(sql);
// 5、给?赋值
pstm.setString(1, "dlei0009");
pstm.setString(2, "666888");
// 6、通知执行sql查询,得到结果集对象。
ResultSet rs = pstm.executeQuery();
// 7、处理结果集
List<User> users = new ArrayList<>(); // 多态!
while (rs.next()) {
// 每次读取一行数据,就封装成一个User对象。
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setAge(rs.getInt("age"));
user.setGender(rs.getString("gender"));
//user.setPassword(rs.getString("password"));
// 8、将User对象添加到集合中
users.add(user);
}
users.forEach(u -> System.out.println(u));
} catch (Exception e) {
e.printStackTrace();
}
}
并未将参数值在SQL语句中写死,而是使用 ? 进行占位,然后再指定每一个占位符对应的值是多少,而最终在执行SQL语句的时候,程序会将SQL语句(SELECT * FROM user WHERE username = ? AND password = ?),以及参数值("daqiao", "123456")都发送给数据库,然后在执行的时候,会使用参数值,将?占位符替换掉。
使用预编译的方法 防止 用户名 和密码 写死
预编译的作用:
防止sql注入:
如果不使用预编译 密码 为 ' or '1' = '1 时 查询 会 恒为真 会直接进入系统 产生安全问题
-
JDBC程序执行DML语句:int rowsUpdated = pstmt.executeUpdate(); //返回值是影响的记录数
-
JDBC程序执行DQL语句:ResultSet resultSet = pstmt.executeQuery(); //返回值是查询结果集
MyBatis 框架:
-
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
-
MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
-
持久层:指的是就是数据访问层(dao),是用来操作数据库的。
- 框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展。
环境配置:
在 application.properties
中配置数据库的连接信息。和配置Mybatis日志输出
java
#数据库访问的url地址
spring.datasource.url=jdbc:mysql://localhost:3306/web
#数据库驱动类类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#访问数据库-用户名
spring.datasource.username=root
#访问数据库-密码
spring.datasource.password=root@1234
#mybatis的配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
编写持久层(dao层)接口 并写sql语句:
在dao层创建 UserMapper接口:
java
@Mapper
public interface UserMapper {
@Select("select * from t_student ")
List<User> findAll();
@Delete("delete from t_student where id=#{id}")
int deleteById(Integer id);
@Select("select * from t_student where id=#{id} and salary=#{salary}")
User findById(@Param("id") int idx, int salary);
@Insert("insert into t_student values(#{id},#{username},#{age},#{gender},#{salary})")
int addUser(User user);
@Update("update t_student set username=#{username},age=#{age},gender=#{gender},salary=#{salary} where id=#{id}")
int updateUser(User user);
List<User> findByAge(Integer age);
void updateUser2(User user);
}
- @Mapper注解:表示是mybatis中的Mapper接口
程序运行时,框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理
- @Select注解:代表的就是select查询,用于书写select查询语句
原理解析:
先用动态代理的方法 创建 接口的实现类对象 例如deleteById 方法 对象调用某以方法时 可以在 InovocationHandler 接口的实现类对象重写的抽象方法invoke 的参数 args 中 获得 参数 Integer id
再用反射创建类对象 找出注解 Delete 并创建注解对象 拿到 value 的值 delete from t_student where id=#{id} 从而 拼接获得了完整的 sql语句 再 用 MyBatis 框架链接数据库进行查询
单元测试:
java
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testFindAll(){
List<User> userList = userMapper.findAll();
for (User user : userList) {
System.out.println(user);
}
}
}
注意:
Autowired 时 spring会自动 创建 UserMapper 接口的实现类对象 并 自动放入 IOC容器中
在autowired时 自动注入 bean 对象 和 之前自己写实现类对象并加 @Component / @Respository
不同
JDBC MyBatis 优缺点:
JDBC程序的缺点:
-
url、username、password 等相关参数全部硬编码在java代码中。
-
查询结果的解析、封装比较繁琐。
-
每一次操作数据库之前,先获取连接,操作完毕之后,关闭连接。 频繁的获取连接、释放连接造成资源浪费。
Mybatis的解决:
-
数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件 application.properties中
-
查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注
-
在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。
数据库链接池:
和 线程池 类似
在前面我们所讲解的mybatis中,使用了数据库连接池技术,避免频繁的创建连接、销毁连接而带来的资源浪费。
1). 没有数据库连接池的情况
客户端执行SQL语句:要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行后又需要关闭连接对象从而释放资源,每次执行SQL时都需要创建连接、销毁链接,这种频繁的重复创建销毁的过程是比较耗费计算机的性能。
2). 有数据库连接池的情况
数据库连接池是个容器,负责分配、管理数据库连接(Connection)
- 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象
允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
- 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象
数据库连接池的好处:
提高性能:
减少连接建立时间:每次数据库操作都需要建立和关闭连接,而连接池预先创建了一定数量的连接,减少了连接建立的时间。提高并发处理能力:连接池可以管理多个连接,使得应用程序能够同时处理更多的请求。
资源管理:
有效管理数据库连接:连接池可以限制同时打开的最大连接数,防止因连接过多导致数据库崩溃。
自动回收空闲连接:连接池可以定期检查连接的状态,并回收空闲连接,确保资源的有效利用。
简化代码 :
减少代码复杂性:使用连接池后,不需要在每个数据库操作中手动管理连接的创建和关闭,简化了代码。
集中管理配置:数据库连接的相关配置可以在连接池中统一管理,便于维护和修改。
增强安全性:
支持连接验证:连接池可以定期验证连接的有效性,确保连接始终可用。
防止SQL注入:虽然连接池本身不直接防止SQL注入,但结合其他安全措施(如预编译语句)可以提高安全性。
支持多种数据库:
兼容性好:大多数连接池库都支持多种数据库,可以根据需要灵活切换数据库类型。
监控和调试:
提供监控工具:连接池通常提供监控功能,可以帮助开发者监控连接的使用情况,及时发现和解决问题。
日志记录:
连接池可以记录连接的使用日志,便于调试和性能分析。
降低服务器负载:
减少数据库服务器压力:通过复用连接,减少了对数据库服务器的频繁请求,降低了服务器的负载。
引用Druid 链接池的方法
①. 在pom.xml
文件中引入依赖
java
<dependency>
<!-- Druid连接池依赖 -->
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.19</version>
</dependency>
②. 在application.properties
中引入数据库连接配置
java
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/web
spring.datasource.druid.username=root
spring.datasource.druid.password=1234
运用Mybaits增删改查:
删除:
java
/**
* 根据id删除
*/
@Delete("delete from user where id = 5")
public void deleteById();
java
/**
* 根据id删除
*/
@Delete("delete from user where id = #{id}")
public void deleteById(Integer id);
注意:
MyBatis会在执行SQL时使用PreparedStatement,从而实现预编译 两种删除方式都使用了预编译
在单元测试类中,增加如下测试方法.
DML语句执行完毕,是有返回值的,我们可以为Mapper接口方法定义返回值来接收,如下
java
/**
* 根据id删除
*/
@Delete("delete from user where id = #{id}")
public Integer deleteById(Integer id);
Integer类型的返回值,表示DML语句执行完毕影响的记录数。
面试题:
- Mybatis的提供的符号,有两个,一个是
#{...}
,另一个是${...}
,区别如下:
项目开发中 使用 ${} 可能会产生 sql 注入的问题
新增:
- Mapper接口:
java
/**
* 添加用户
*/
@Insert("insert into user(username,password,name,age) values(#{username},#{password},#{name},#{age})")
public void insert(User user);
注意id 为 自增属性 所以可以不用传参
修改:
- Mapper接口方法:
java
/**
* 根据id更新用户信息
*/
@Update("update user set username = #{username},password = #{password},name = #{name},age = #{age} where id = #{id}")
public void update(User user);
在测试类中添加测试方法,代码如下:
java
@Test
public void testUpdate(){
User user = new User();
user.setId(6);
user.setUsername("admin666");
user.setPassword("123456");
user.setName("管理员");
user.setAge(30);
userMapper.update(user);
}
查询:
java
/**
* 根据用户名和密码查询用户信息
*/
@Select("select * from user where username = #{username} and password = #{password}")
public User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
注意: 如果使用 spring 官方 骨架 则不用@Param修饰也可以 只需要保证 参数名 和 #{ } 中的 名字相同即可
XML映射配置:
Mybatis的开发有两种方式:
-
注解
-
XML
使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。
在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:
-
XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
-
XML映射文件的namespace属性为Mapper接口全限定名一致
-
XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
创建XML需要 写 影协文件
XML
<?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="com.itheima.mapper.EmpMapper">
<!--查询操作-->
<select id="findAll" resultType="com.itheima.pojo.User">
select * from user
</select>
</mapper>
注意:resulyType 查询返回值类型:
XML
<mapper namespace="com.itheima.dao.UserMapper">
<select id="findByAge" resultType="com.itheima.pojo.User">
select * from t_student where age < #{age}
</select>
<update id="updateUser2">
update t_student set username=#{username},age=#{age},gender=#{gender},salary=#{salary} where id=#{id}
</update>
</mapper>