一、框架的概述
1.1 什么是框架
- 框架: 是整个或部分系统的可重用设计。是某种应用的半成品 ,是一组组件。
1.2 要解决的问题
- 解决的最重要的一个问题是**技术整合 ** 的问题。
- 框架一般处在低层应用平台(如J2EE)和高层业务逻辑之间的中间层。
1.3 分层开发的常见框架
1.3.1解决数据的持久化问题的Mybatis框架
- 是一个dao层(持久层)的框架,是apache下的开源框架(Ibatis)。内部封装了jdbc 操作,使开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动,创建connection,创建statement,封装statement,封装结果集等jdbc 繁杂的代码操作。(搭建好框架后我们只需要提供sql和返回值既就可以了。)
1.3.2 解决WEB层问题的MVC框架
1.3.3 解决技术整合问题的框架–spring
Spring框架是由于软件开发 的复杂性而创建的。
- 目的: 解决企业应用开发的复杂性
- 功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能。
- 范围:任何java应用
- Spring是一个轻量级控制反转(loC)和面向切面(AOP) 的容器框架。
1.2 JDBC编程分析
JDBC: 原始
Class.forName(“com.mysql.jdbc.driver”); // 加载驱动
Connection conn = DriverManager.getConnection(url,name,pwd); // 创建连接
PreparedStatement ps = conn.PreparedStatement(); // 获得语句执行者
String sql = "select * from User "; // 编写sql
ResultSet rs = ps.query(sql); // 执行sql
while(rs.next()){
// 处理结果集
id
name
pwd // 元数据 --
}
// 关闭连接
1.2.1 JDBC操作数据库的弊端
- 连接数据库的基本信息都是硬编码到代码中
-
- 将动态的数据抽离成xml配置文件
- 动态的sql语句和返回值也是硬编码到代码中
-
- 将动态的sql和返回值抽离成xml配置文件
- jdbc操作数据库流程繁琐
-
- 抽取工具类
二 、Mybatis框架的使用步骤
- 创建maven项目
- 引入Mybatis框架所需的jar包
- 导入Mybatis框架的核心配置文件(xml)
-
- SqlMapConfig.xml(连接数据库的基本信息 username,password,url ,driver)
三、自定义MyBatis框架
3.1 Mybatis框架解决的问题
- 准备数据库和表 以及表数据
- 配置文件
- 1.数据库信息(核心配置文件SqlMapConfig.xml) 存放java连接数据库的基本信息
-
- Sql语句(sql配置文件:UserMapper.xml) 存放要执行的sql语句(eg:select * from 表名)
3.2 自定义Mybatis图解
3.3自定义Mybatis实现步骤
- 由图可知,需要先配置xml 文件
-
- 1.配置pom.xml
-
-
- 导入mybatis jar包文件以及其他文件jar包
-
<!-- 日志信息 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!-- 解析xml的jar包 -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- xpath的jar包 -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
</dependency>
-
- 2.配置UserMapper.xnl文件
<!--namespace:名称空间
区分模块
唯一:namespace.id
-->
<mapper namespace="com.itheima.dao.UserDao">
<!-- select 查询 -->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user
</select>
</mapper>
-
-
- 得到Mapper实体类
-
private String sql;
private String resultType;
-
-
- get,set,tostring方法自行补上。
-
-
- 3.配置SqlMapConfig.xml文件
<!--配置所有sql的映射文件-->
<mappers>
<!--相对路径-->
<mapper resource="UserMapper.xml"></mapper>
</mappers>
-
- 得到Configuration实体
private String username;
private String password;
private String url;
private String driver;
private Map<String ,Mapper> mappers;
-
- 代码的其他部分自行补上。get,set,tostring方法。
- 创建SqlSessionFactoryBuilder
/**
* 1.解析核心配置文件,得到Configuration实体对象
* 2.创建SqlSessionFactory对象,并将cf传递给SqlSessionFactory
*/
public class SqlSessionFactoryBuilder {
public SqlSessionFactory builder(InputStream is) throws Exception {
//1.解析核心配置文件,得到Configuration实体对象
Configuration cfg = XMLConfigBuilder.buildConfiguration(is);
//2. 创建SqlSessionFactory对象,并将cfg传递给SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactory(cfg);
return sqlSessionFactory;
}
}
- 创建SqlSessionFactory
public class SqlSessionFactory {
private Configuration cfg;
public SqlSessionFactory(Configuration cfg){
this.cfg=cfg;
}
//创建SqlSession对象的实现类
public SqlSession openSession(){
return new DefaultSqlSession(cfg);
}
}
- 创建SqlSession接口
- SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
- 通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
public interface SqlSession {
<T> List <T> findAll(String mapperId) throws Exception;
}
- 创建DefaultSqlSession
public class DefaultSqlSession implements SqlSession {
private Configuration cfg;
public DefaultSqlSession(Configuration cfg){
this.cfg=cfg;
}
/**
* 查询所有数据
* 加载 驱动,执行sql,返回结果集
* @param mapperId
* @param <T>
* @return
*/
public <T> List<T> findAll(String mapperId) throws Exception {
Map<String, Mapper> mappers = cfg.getMappers();
//Mapper
Mapper mapper = mappers.get(mapperId);
//获取要执行的sql语句
String sql = mapper.getSql();
//获取响应的返回值的全限定名
String resultType = mapper.getResultType();
Executor executor = new Executor(cfg);
List<T> list = executor.executeQuery(sql, resultType);
return list;
}
}
- 测试:
public class TestMybatis {
@Test
public void testFindAll() throws Exception {
//1.创建SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//解析配置文件
InputStream is = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//2.SqlSessionFactory
SqlSessionFactory builder = sqlSessionFactoryBuilder.builder(is);
//3.通过SqlSessionFactory得到 SqlSession对象
SqlSession sqlSession = builder.openSession();
//4.调用sqlSession的方法,获取结果集
List<User> list = sqlSession.findAll("com.itheima.dao.UserDao.findAll");
for (User user : list) {
System.out.println(user);
}
}
}
四 、使用注解的方式实现Mybatis
在注解上提供sql和返回值的全限定名
4.1 SelectAll注解
/**
* 代替sql映射文件
* sql:
* resultType:
*/
@Target(ElementType.METHOD)//设置注解的使用位置 方法上
@Retention(RetentionPolicy.RUNTIME)//设置注解存活的时期
public @interface SelectAll {
String sql();
String resultType();
}
4.2 **重新编写DefaultSqlSession **
public class DefaultSqlSession implements SqlSession {
private Configuration cfg;
public DefaultSqlSession(Configuration cfg){
this.cfg=cfg;
}
/**
* 查询所有数据
* 加载 驱动,执行sql,返回结果集
* @param mapperId
* @param <T>
* @return
*/
public <T> List<T> findAll(String mapperId) throws Exception {
Map<String, Mapper> mappers = cfg.getMappers();
//Mapper
Mapper mapper = mappers.get(mapperId);
//获取要执行的sql语句
String sql = mapper.getSql();
//获取响应的返回值的全限定名
String resultType = mapper.getResultType();
Executor executor = new Executor(cfg);
List<T> list = executor.executeQuery(sql, resultType);
return list;
}
@Override
/**
* 注解的方式
*/
public <T> List<T> findAll(String sql, String resultType) throws Exception {
Executor executor = new Executor(cfg);
List<T> list = executor.executeQuery(sql, resultType);
return list;
}
/**
* 使用动态代理生成接口的实现类对象
* @param clazz
* @param <E>
* @return
*/
public <E> E getMapper(Class clazz) {
E proxy =(E) Proxy.newProxyInstance(
clazz.getClassLoader(),//类加载器
new Class[]{clazz}, //代理类需要实现的接口
new InvocationHandler() {//处理业务逻辑
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name=method.getName();//获取执行的方法
if ("findAll".equals(name)){
//查询所有信息,
//获取代理类所实现的接口的权限定名称(命名空间)
String nameSpace = proxy.getClass().getGenericInterfaces()[0].getTypeName();
//获取id的值,(当前执行的方法名称)
String mapperId = nameSpace+"."+name;
List list = findAll(mapperId);
return list;
}
return null;
}
}
);
return proxy ;
}
}
4.3 测试类
public class TestMybatis {
@Test
public void testFindAll() throws Exception {
//1.创建SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//解析配置文件
InputStream is = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//2.SqlSessionFactory
SqlSessionFactory builder = sqlSessionFactoryBuilder.builder(is);
//3.通过SqlSessionFactory得到 SqlSession对象
SqlSession sqlSession = builder.openSession();
//4.调用sqlSession的方法,获取结果集
// List<User> list = sqlSession.findAll("com.itheima.dao.UserDao.findAll");
// UserDaoImpl dao = new UserDaoImpl();
//使用动态代理的方式生成UserDao的实现类
UserDao dao = sqlSession.getMapper(UserDao.class);
List<User> list = dao.findAll();
for (User user : list) {
System.out.println(user);
}
}
}