如何自己实现MyBatis框架
通过本章节的学习,对mybatis的一级缓存,mapper接口没有实现类底层是如何处理的 xml的处理 有所了解
1.自定义实体类
public class Admin implements Serializable{
private String id;
private String aname;
private String password;
private String phone;
public Admin(){
}
public Admin(String id, String aname, String password, String phone) {
super();
this.id = id;
this.aname = aname;
this.password = password;
this.phone = phone;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAname() {
return aname;
}
2.自定义mapper接口
public interface AdminMapper {
public List<Admin> queryAll();
}
3.jdbc工具类
JDBC工具类大家都很熟悉,我没有太优化
public class JDBCUtil {
private static Connection con = null;
private static PreparedStatement ps = null;
private static ResultSet rs = null;
static {
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/stu?useUnicode=true&characterEncoding=utf-8";
String name = "root";
String pwd = "";
con = DriverManager.getConnection(url,name,pwd);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getCon(){
return con;
}
}
4.自定义AdminMapper.xml配置文件
本次只是演示无参的select,有参的 需要的可以再写出来
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.mapper.AdminMapper">
<select id="queryAll">
select id,aname,apwd,phone from tb_admin
</select>
<select id="queryById">
select id,aname,apwd,phone from tb_admin where id = #{id}
</select>
</mapper>
5.xml解析工具类
public class XMLParser {
public static Map<String,String> getSqlMap(){
Map<String,String> map = new HashMap<String, String>();
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("E:/AdminMapper.xml");
NodeList list = doc.getElementsByTagName("select");
for(int i = 0 ;i<list.getLength();i++){
Element e = (Element) list.item(i);
String id = e.getAttribute("id");
String sql = e.getTextContent().trim();
map.put(id, sql);
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
public static void main(String[] args) {
getSqlMap();
}
}
6.代理类
public class MapperProxy implements InvocationHandler{
//类似于sqlsession 缓存
private static Map<String,Object> cachedmap = new HashMap<String, Object>();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//定义要返回的结果
List<Admin> alist = (List<Admin>) cachedmap.get(method.getName());
if(alist != null && alist.size()>0){
System.out.println("第二次进来 从缓存获取");
return alist;
}else{
List<Admin> list = new ArrayList<>();
//System.out.println(method.getName());
String methodName = method.getName();
//1.解析xml
Map<String,String> map = XMLParser.getSqlMap();
String sql = map.get(methodName);
System.out.println("第一次进来 :");
System.out.println(sql);
//2.执行sql
Connection con = JDBCUtil.getCon();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()){
String id = rs.getString("id");
String aname = rs.getString("aname");
String apwd = rs.getString("apwd");
String phone = rs.getString("phone");
Admin admin = new Admin(id, aname, apwd, phone);
list.add(admin);
}
cachedmap.put(methodName, list);
rs.close();
ps.close();
con.close();
return list;
}
}
//我们肯定要得到代理的对象<T>泛型
//inter 就是对应的要处理的接口
public static <T> T getMapper(Class<T> inter){
ClassLoader classloader = inter.getClassLoader();//拿到接口的 类加载器
Class<T>[] inters = new Class[]{inter};//只是转成数组的格式
MapperProxy proxy = new MapperProxy();
//classloader加载器 inters需要的接口 proxy要处理的方法
return (T) Proxy.newProxyInstance(classloader, inters, proxy);
}
}
7.测试类
public class Test {
public static void main(String[] args) {
//返回的就是 处理接口的代理类
AdminMapper adminMapper = MapperProxy.getMapper(AdminMapper.class);
List<Admin> list1 = adminMapper.queryAll();//回调invoke方法
System.out.println(list1.size());
//相同的查询不会再执行sql了,从缓存了获取
List<Admin> list2 = adminMapper.queryAll();//回调invoke方法
System.out.println(list2.size());
}
}