关于标题
JDBC问题总结:
- 数据库连接创建、释放资源频繁造成系统浪费,从而影响性能。
- sql语句在代码中存在硬编码,不易维护,实际中sql代码可能会经常随着需求做调整,这时就需要改动代码。
- 使用preparedStatement向占位符传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少修改sql还要改代码,不易维护。
- 对结果集解析存在硬编码(查询列名),如果能封装pojo解析会比较方便。
解决JDBC问题思路:
- 数据库频繁创建连接释放资源------>连接池
- sql语句及参数硬编码 ------->配置文件
- 手动解析封装返回结果集 ------->反射、内省
封装JDBC自定义持久层框架
使用端(项目) Ipersistence_test
1.提供核心配置文件sqlMapConfig.xml:存放数据源信息 并引入mapper.xml (?使用框架的时候只用传递一个总配置文件路径就行了)
2.提供Mapper.xml:sql语句的配置信息
框架端(jar) Ipersistence
- 读取配置文件 根据配置文件路径加载配置文件成字节流存储到内存中
- 创建Resource类并提供方法 InputStream getResourceAsSream(string Path)
- 创建两个javaBean:(容器对象) 存放的就是配置文件解析出的内容
- Configuration:核心配置类 存放sqlMapConfig.xml解析出的内容
- MappedStatement:映射配置类 存放mapper.xml解析出的内容
- 解析配置文件(dom4j)
- 创建类sqlSessionFactoryBuilderr 方法build(inputStream in)
- 使用dom4j解析配置文件 将解析出的内容放到configuration容器当中去
- 创建sqlSessionFactory对象 用于生产sqlSession(会话对象) ??crud封装在会话对象中 为什么不直接new出对象呢 此处采用工厂模式 降低程序耦合
- 创建sqlSessionFactory接口及实现类DefaultSqlSessionFactory
- 创建方法openSession() 生产sqlSession
- 创建sqlSession接口及实现类DefaultSqlSession
- 定义数据库的crud操作 selectList() selectOne() update() delete()
- 创建Executor接口及实现类simpleExecutor
- query(Configuration,MappedStatement,Object... params) 执行jdbc代码
Mybatis简介
1.1基本内容
- MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
- Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
1.2Mybatis架构
1、 mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
1.3执行流程
1、使用XML配置文件或Java代码方式生产SqlSessionFactory
2、使用Resources类的getResourceAsStream()方法读取XML配置文件
3、使用SqlSessionFactoryBuilder类的build()方法创建sqlSessionFactory
4、得到sqlSessionFactory类后使用该类的openSession()获取SqlSession
5、得到SqlSession后需要实现映射器的功能,映射器有一个接口和该接口对应的XML映射文件或使用注解组成
6、使用SqlSession的getMapper()方法得到具体的接口类对象
1.4工程搭建入门
1.5Mapper动态代理开发
传统dao层开发是dao层新建接口UserDao ,实现类 UserDaoImpl
动态代理开发是只写接口,实现类由mybatis生成
四个原则:Mapper接口开发需要遵循以下规范
1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
具体实现
- 接口与mapper.xml对应
import com.ali.bean.User;
public interface MapperUser {
//原则一:mapper.xml中的namespace要与mapper接口类路径相同
//原则二:接口方法名与xml中id相同
//原则三:接口的输入参数一致
//原则四:接口方法返回类型一致
public User findUserById(Integer id);
}
<mapper namespace="com.ali.mapper.MapperUser">
<select id="findUserById" resultType="com.ali.bean.User"
parameterType="Integer">
select * from t_user where id=#{v}
</select>
</mapper>
- 测试类 要使用sqlSession.getMapper(MapperUser.class);方法
public void fun1() throws IOException {
String resource="sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlSession生成实现类
MapperUser userMapper = sqlSession.getMapper(MapperUser.class);
User user = userMapper.findUserById(2);
System.out.println(user);
}
1.6mybatis缓存
mybatis默认开启了一级缓存
-
在同一个
SqlSession
中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据; -
不同的
SqlSession
之间的缓存是相互隔离的; -
用一个
SqlSession
, 可以通过配置使得在查询前清空缓存; -
任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。
1.7mybatis插件
1.8mybatis架构原理
1.9mybatis总体流程