分析mybtis概念
1.读取配置文件
InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
在读取路径无论是绝对路径还是相对路径都有问题,所以只有两种方式,第一个是使用类加载器读取类配置文件,第二个是ServletContext.getRealPath可以读取到当前项目的绝对路径。
2.创建mysql SessionFactory对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = builder.build(in);
mybatis使用了构建者模式,只需要把数据给他就行,隐藏对象创建的细节
3.使用工厂类生产sqlSession对象
SqlSession sqlSession = build.openSession();
使用了我工厂模式,优势解耦
4.使用sqlSession对象创建Dao代理类
JDBCDao mapper = sqlSession.getMapper(JDBCDao.class);
通过字节码建立代理对象
proxy.newProxyIntence(类加载器,代理对象要实现接口字节码数据 , 如何代理)
类加载器:它使用和被代理对象的同一个类加载器
代理对象要实现接口字节码数据:实现相同的接口
如何实现:他就是增强方法需要我们自己学一个接口实现这个实现类调用代理的对应方法比如selectList
使用了代理模式
5.使用代理对象执行方法
List<User> users = mapper.findAll();
36.释放资源
sqlSession.close();
in.close();
实现思想
首先SqlSessionFactoryBuilder需要读取配置信息需要一个XMLConiguration对我们的主配置文件进行读取,对数据库的连接密码url,驱动这些进行解析并将这些信息写入Configuration这个类而这个类更为关键是他还有个Map<String ,Mapper>String 记录是吃韭菜持久层类名+sql和记录Mapper。而Mapper类是为封装mysql语句和返回类的全限定名的。还有而获取配置路径就是使用Resources方法。
然后根据配置信息就会创建SqlSessionFactory这个类并将Configration引用传递给他,这样就可以通过工厂模式对Session对象就行创建。
而Session对象创建后通过getMapper方法将将持久层的类Class对象传递进去,而在getMapper方法中实现对持久层方法的代理。而代理对象就是MapperProxy类,通过对其进行动态代理实现它invoke方法,在invoke方法中通过获取被代理对象的类和执行方法来取出Configuration中的Map<String ,Mapper> map这样就可以获得Mapper而Mapper中包含sql语句以及返回对象的全限定名,以及获取DataSourceConnection类的连接数据库的Connection对象,而DataSourceConnection这个类是通过获取Configuration对象获取url,密码,用户名,驱动包。最后调用工具类Excuter实现执行方法。
实现步骤
第一步加入在pom.xml依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
首先第一步加如配置文件因为没有导入mybatis的包可以不加如约束
主配置如下
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="jdbc"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/db1"/>
<property name="username" value="root"/>
<property name="password" value="zheng"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/zheng/dao/UserMapper.xml"></mapper>
</mappers>
</configuration>
映射文件如下
<?xml version="1.0" encoding="UTF-8" ?>
<!--
mapper:用于定义一个映射文件的根节点
namespace 用来配置命名空间,主要进行session级别的缓存配置
通常情况,命名空间的值,就是当前操作实体类对象的全名称
-->
<mapper namespace="com.Dao.JDBCDao">
<select id="fillAll" resultType="com.zheng.User">
select * from test1
</select>
</mapper>
class Resources这个类用于加载资源
public class Resources {
/**
* 根据参数获取字节流
* @param file
* @return
*/
public static InputStream getResourceAsStream(String file)
{
return Resources.class.getClassLoader().getResourceAsStream(file);
}
}
class SqlSessionFactoryBuilder 这个了用于接收配置文件然后构建SqlSessionFactory
public class SqlSssionFactoryBuilder {
public static SqlSssionFactory build(InputStream is)
{
Configuration cgf = XMLConiguration.loadConfiguration(is);
return new SqlSessionFactoryImp(cgf);
}
}
interface SqlSessionFactory这个类是sqlSesion对象的工厂类用于创建SqlSession
public interface SqlSssionFactory {
public SqlSession openSession();
}
interface SqlSessionFactoryImp实现SqlSessionFactory
public class SqlSessionFactoryImp implements SqlSssionFactory {
private Configuration cfg;
public SqlSessionFactoryImp(Configuration cfg)
{
this.cfg = cfg;
}
/**
* 创建一个新的操作数据库对象
* @return
*/
public SqlSession openSession() {
return new SqlSessionImp(cfg);
}
}
interface SqlSession 是执行sql语句和sql对象的集合
public interface SqlSession {
<T> T getMapper(Class<T> dointerfaceClass);
void close();
}
class SqlSessionImp
public class SqlSessionImp implements SqlSession {
private Configuration cfg;
private Connection con;
public SqlSessionImp(Configuration cfg ) {
this.cfg = cfg;
try {
this.con = DataSourceConnection.getConnection(cfg);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 用于创建代理对象
* @param dointerfaceClass
* @param <T>
* @return
*/
public <T> T getMapper(Class<T> dointerfaceClass) {
/**
* 代理谁就用谁的类加载器
*/
return (T)Proxy.newProxyInstance(dointerfaceClass.getClassLoader(),
new Class[]{dointerfaceClass},new MapperProxy(cfg.getMap(),con));
}
/**
* 释放资源
*/
public void close() {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Configuration 用于出读ImputStream取配置信息
public class Configuration {
private String dirver;
private String username;
private String url;
private String password;
private Map<String ,Mapper> map= new HashMap<String, Mapper>() {
};
public Map<String, Mapper> getMap() {
return map;
}
public void setMap(Map<String, Mapper> map) {
this.map.putAll(map);
}
public String getDirver() {
return dirver;
}
public void setDirver(String dirver) {
this.dirver = dirver;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
class DataSourceConnection 用于创建Connection的对象
public class DataSourceConnection {
public static Connection getConnection(Configuration cfg) throws ClassNotFoundException, SQLException {
Class.forName(cfg.getDirver());
return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
}
}
用于封装SQL语句和返回的类型的全限定
public class Mapper {
private String queryString;
private String resultTepe;
public String getQueryString() {
return queryString;
}
public void setQueryString(String queryString) {
this.queryString = queryString;
}
public String getResultTepe() {
return resultTepe;
}
public void setResultTepe(String resultTepe) {
this.resultTepe = resultTepe;
}
}
class Excuter是一个工具类用于获取Mapper中的SQL和返回对象,以及使用Connection的sql连接来执行。
由于代码太长粘贴影响阅读而且本文主要是为了理解概念就不贴具体的代码,了解这个类的作用即可
public class Excuter {
public <E> List<E> selectList(Mapper mapper, Connection conn)
{
List<E> list=null;
return list;
}
}
class MapperProxy是为了实现前面的Session传入的返回对象,对其进行代理,使用动态方法实现的类。
public class MapperProxy implements InvocationHandler {
Map<String,Mapper> map;
private Connection conn;
public MapperProxy(Map<String,Mapper> map,Connection con)
{
this.map = map;
this.conn = con;
}
/**
* 用于对方法增强的
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取方法名
String methodName = method.getName();
//获取类名
String className = method.getDeclaringClass().getName();
//获取Map中key
String key = className+"."+methodName;
//获取Map中的Mapper
Mapper mapper = map.get(key);
//是否有mapper
if (mapper == null) {
throw new IllegalAccessException("传入参数有误");
}
//调用工具类
return new Excuter().selectList(mapper, conn);
}
}
class XMLConiguration是一个用于解析配置的类
由于代码太长粘贴影响阅读而且本文主要是为了理解概念就不贴具体的代码,了解这个类的作用即可
public class XMLConiguration {
static Configuration loadConfiguration(InputStream is)
{
return null;
}
}
网友评论