① 创建工程,导入驱动jar包(mysql-connector-java-5.1.48.jar)
② 注册驱动。Class.forName(“com.mysql.jdbc.Driver”);
③ 获取连接。Connection conn = DriverManager.getConnection(url, username, password);
④ 定义SQL语句。String sql = “update…”;
⑤ 获取执行SQL对象。Statement stmt = conn.createStatement();
⑥ 执行SQL。stmt.executeUpdate(sql);
⑦ 处理返回结果。
⑧ 释放资源。
数据库连接池是个容器,负责分配、管理数据库连接(Connection)它允许应用程序 重复使用一个现有的数据库连接,而不是再重新建立一个 ;
DataSource、DBCP、C3PO、Drulid
Connection getConnection()
(1)数据库连接创建、释放频繁会造成系统资源浪费,从而影响系统性能。
(2)SQL语句在代码中硬编码,造成代码不易维护。在实际应用的开发中,SQL变化的可能性较大。在传统JDBC编程中,SQL变动需要改变Java代码,违反了开闭原则。
(3)用PreparedStatement向占位符传参数存在硬编码,因为SQL语句的where条件不一定,可能多也可能少,修改SQL需要修改代码,造成系统不易维护。
(4)JDBC对结果集解析存在硬编码(查询列名),SQL变化导致解析代码变化,造成系统不易维护。
mybatis 是一个优秀的基于 java 的持久层框架,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
mybatis 通过 xml或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
优点:
缺点:
实例
<mapper namespace="com.southwind.repository.AccountRepository">
<insert id="save" parameterType="com.southwind.entity.Account">
insert into t_account(username,password,age) values(#{username},#{password},#{age})
insert>
<update id="update" parameterType="com.southwind.entity.Account">
update t_account set username = #{username},password=#{password},age=#{age}
update>
<delete id="deleteById" parameterType="long">
delete from t_account where id = #{id}
delete>
<select id="findAll" resultType="com.southwind.entity.Account">
select * from t_account
select>
<select id="findById" parameterType="long" resultType="com.southwind.entity.Account">
select * from t_account where id = #{id}
select>
mapper>
由于${}是直接替换参数,不会给参数添加单引号,因此会导致SQL语句错误,如果非要使用${},就需要手动对参数添加单引号,但这样又会带来SQL注入的问题(传入参数:"' or 1 = '1")
能使用#{}就使用#{}!如果非要使用${},那么一定要进行参数校验。
数据量大了的时候,一次性将所有数据查出来不现实,所以我们一般都是分页查询的,减轻服务端的压力,提升了速度和效率
Limit实现分页:mysql分页优化,灵活性高
RowBounds分页(不建议使用):RowBounds中有2个字段offset和limit。这种方式获取所有的ResuitSet,从ResultSet中的offset位置开始获取limit个记录(不会查询所有结果),不指定参数的话默认查询所有行。(无论如何DB压力都大,因为结果暂存在db中了)
利用数组Sublist分页
@Override
public List<Student> queryStudentsByArray(int currPage, int pageSize) {
List<Student> students = studentMapper.queryStudentsByArray();
// 从第几条数据开始
int firstIndex = (currPage - 1) * pageSize;
// 到第几条数据结束
int lastIndex = currPage * pageSize;
return students.subList(firstIndex, lastIndex);
}
## 1.拦截器机制
Mvbatis中的拦截器机制是指,在执行数据库操作时,可以通过自定义拦截器对SQL语句进行拦截和处理。Mvbatis提供了-个Interceptor接口,只要实现该接口并配置到mybatis-config.xml文件中即可使用
## 2.分页插件实现原理
在Mybatis中使用分页插件的原理如下:
(1)首先,在mybatis-config.xml文件中配置分页插件,
(2)当执行查询操作时,拦截器会对SQL语句进行拦截,并根据传入的参数自动将SQL语句进行改写,添加limit和offset关键字。
(3)最后将改写后的SQL语句交给Mybatis执行。
## 物理分页和逻辑分页
物理分页就是数据库本身提供了分页方式,如MySQL的limit,好处是效率高,不好的地方就是不同数据库有不同的搞法。
逻辑分页利用游标分页,好处是所有数据库都统一,坏处就是效率低。使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索。
结论:物理分页总是优于逻辑分页,没有必要将属于数据库端的压力加诸到应用端来,就算速度上存在优势,然而其它性能上的优点足以弥补这个缺点
在开发过程中很多时候我们并不需要总是在加载⽤户信息时就⼀定要加载他的订单信息。而是想用到订单信息时才会加载,延迟加载是基于嵌套查询来实现的。
原理:它的原理是,使⽤ CGLIB 或 Javassist( 默认 ) 创建⽬标对象的代理对象。当调⽤代理对象的延迟加载属性的 getting ⽅法时,进⼊拦截器⽅法。⽐如调⽤ a.getB().getName() ⽅法,进⼊拦截器的invoke(…) ⽅法,发现 a.getB() 需要延迟加载时,那么就会单独发送事先保存好的查询关联 B对象的 SQL ,把 B 查询上来,然后调⽤ a.setB(b) ⽅法,于是 a 对象 b 属性就有值了,接着完成 a.getB().getName() ⽅法的调⽤。这就是延迟加载的基本原理
优点:先从单表查询,需要时再从关联表去关联查询,⼤⼤提⾼数据库性能,因为查询单表要⽐关联查询多张表
缺点:因为只有当需要⽤到数据时,才会进⾏数据库查询,这样在⼤批量数据查询时会很慢。
所以:在多表中:⼀对多,多对多——通常情况下采⽤延迟加载,⼀对⼀(多对⼀)——通常情况下采⽤⽴即加载
①、一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
②、二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
Hibernate的优缺点:
Mybatis的优缺点:
SimpleExecutor(简单执行器):这是默认的执行器类型。它每次执行都会创建一个Statement对象,并立即执行SQL语句。这种执行器不支持事务,每次都会关闭Statement对象,适用于简单的查询场景。
ReuseExecutor(重用执行器):这种执行器重用预处理的Statement对象。它会缓存Statement对象,当需要执行相同的SQL语句时,会直接使用缓存的Statement对象,而不是每次都创建新的对象。这种执行器也不支持事务。
BatchExecutor(批处理执行器):这种执行器用于批量操作,可以一次执行多个SQL语句。它会将相同类型的SQL语句分组,并使用JDBC的批处理功能执行。这种执行器可以提高性能,尤其适用于需要执行大量相同类型SQL语句的场景,如批量插入或更新操作。