模拟Mybatis的实现方法
所需要用到的其他工具或技术:
项目管理工具:Maven
测试运行工具:Junit
数据库 :Derby
XML操作工具:Dom4j
继续不废话
MavenDependencies:
junit junit 4.9 test org.apache.derby derby 10.10.2.0 org.apache.derby derbyclient 10.10.2.0 dom4j dom4j 1.6.1
SQL建表及数据插入(如果在第一节中作过,可以跳过此步):
CREATETABLEUSER_TEST_TB( IDINTPRIMARYKEY, USERNAMEVARCHAR(20)NOTNULL, PASSWORDVARCHAR(20)NOTNULL, NICKNAMEVARCHAR(20)NOTNULL ); INSERTINTOUSER_TEST_TBVALUES(1,'1st','111','Jack'); INSERTINTOUSER_TEST_TBVALUES(2,'2nd','222','Rose'); INSERTINTOUSER_TEST_TBVALUES(3,'3rd','333','Will');
Mybatis配置文件src/main/resource源目录下
test-mybatis-configuration.xml
User.java对象类(src/main/java/com/bjpowernode/practice目录下)
packagecom.bjpowernode.practice;
/**
*
*UserModel
*
*/
publicclassUser
{
privateStringid;
privateStringusername;
privateStringpassword;
privateStringnickname;
publicStringgetId()
{
returnid;
}
publicvoidsetId(Stringid)
{
this.id=id;
}
publicStringgetUsername()
{
returnusername;
}
publicvoidsetUsername(Stringusername)
{
this.username=username;
}
publicStringgetPassword()
{
returnpassword;
}
publicvoidsetPassword(Stringpassword)
{
this.password=password;
}
publicStringgetNickname()
{
returnnickname;
}
publicvoidsetNickname(Stringnickname)
{
this.nickname=nickname;
}
}
Select.java注解类(src/main/java/com/bjpowernode/practice/annotation目录下)
packagecom.bjpowernode.practice.annotation;
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;
/**标注此注解只能用在方法上*/
@Target(ElementType.METHOD)
/**标注此注解生命周期是在Runtime运行时*/
@Retention(RetentionPolicy.RUNTIME)
public@interfaceSelect
{
Stringvalue();
}
UserMapper.java基于Annotation的配置类(src/main/java/com/bjpowernode/practice/annotation目录下)
packagecom.bjpowernode.practice.annotation;
importcom.bjpowernode.practice.User;
importjava.util.List;
publicinterfaceUserMapper
{
@Select("select*fromUSER_TEST_TB")
publicListgetUser();
}
Mapper.java对象类(src/main/java/com/bjpowernode/practice/simulation目录下)
packagecom.bjpowernode.practice.simulation;
/**
*
*存储查询结果对象
*
*/
publicclassMapper
{
/**
*返回类型
*/
privateStringresultType;
/**
*查询SQL
*/
privateStringquerySql;
publicStringgetResultType()
{
returnresultType;
}
publicvoidsetResultType(StringresultType)
{
this.resultType=resultType;
}
publicStringgetQuerySql()
{
returnquerySql;
}
publicvoidsetQuerySql(StringquerySql)
{
this.querySql=querySql;
}
}
SQLSelectProxy.javaAOP动态代理类(src/main/java/com/bjpowernode/practice/simulation目录下)
packagecom.bjpowernode.practice.simulation;
importcom.bjpowernode.practice.annotation.Select;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.util.List;
publicclassSQLSelectProxyimplementsInvocationHandler
{
@Override
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable
{
/**
*获得Mapper方法上的Select注解,以此来取得注解中的SQL语句
*/
Selectselect=method.getAnnotation(Select.class);
if(!method.isAnnotationPresent(Select.class))
{
thrownewRuntimeException("缺少@Select注解!");
}
PreparedStatementpstmt=null;
ResultSetrs=null;
Objectobj=null;
try
{
pstmt=SqlSessionImpl.connection.prepareStatement(select.value());
rs=pstmt.executeQuery();
/**
*获得Method的返回对象类型,此处应当作判断处理,当List的时候,当只返回一个对象的时候.
*为了简单实现功能并与第一节中测试文件不发生冲突起见,此处当作List处理
*/
StringreturnType=method.getGenericReturnType().toString();//java.util.List
if(returnType.startsWith(List.class.getName()))
{
//去掉我们不需要的字符串,得到List中的类型
returnType=returnType.replace(List.class.getName(),"").replace("<","").replace(">","");
}
else
{
//返回其他对象应当作其他处理,此处为了简单起见,暂不处理
}
obj=SqlSessionImpl.executeQuery(rs,returnType);
}
finally
{
if(rs!=null&&!rs.isClosed())
{
rs.close();
}
if(pstmt!=null&&!pstmt.isClosed())
{
pstmt.close();
}
}
returnobj;
}
}
SqlSession.javaMybatis模拟接口(src/main/java/com/bjpowernode/practice/simulation目录下)
packagecom.bjpowernode.practice.simulation;
importjava.util.List;
/**
*
*模拟SqlSession
*
*/
publicinterfaceSqlSession
{
publicTgetMapper(Classclazz);
publicListselectList(Stringquery)throwsException;
}
SqlSessionFactory.javaMybatis模拟类(src/main/java/com/bjpowernode/practice/simulation目录下)
packagecom.bjpowernode.practice.simulation;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importorg.dom4j.Document;
importorg.dom4j.DocumentException;
importorg.dom4j.Element;
importorg.dom4j.io.SAXReader;
/**
*
*模拟SqlSessionFactory
*
*/
publicclassSqlSessionFactory
{
privateInputStreamconfiguration;
publicSqlSessionopenSession()throwsIOException
{
SqlSessionImplsession=newSqlSessionImpl();
loadConfigurations(session);
returnsession;
}
/**
*
*通过Dom4j读取配置文件信息
*
*@paramsession
*@throwsIOException
*/
privatevoidloadConfigurations(finalSqlSessionImplsession)throwsIOException
{
try
{
Documentdocument=newSAXReader().read(configuration);
Elementroot=document.getRootElement();
Listmappers=root.element("mappers").elements("mapper");
for(Elementmapper:mappers)
{
if(mapper.attribute("resource")!=null)
{
session.setXmlSQLs(loadXMLConfiguration(mapper.attribute("resource").getText()));
}
if(mapper.attribute("class")!=null)
{
}
}
}
catch(Exceptione)
{
System.out.println("读取配置文件错误!");
}
finally
{
configuration.close();
}
}
/**
*
*通过dom4j读取Mapper.xml中的信息
*
*@paramresource
*@return
*@throwsDocumentException
*@throwsIOException
*/
privateMaploadXMLConfiguration(Stringresource)throwsDocumentException,IOException
{
Mapmap=newHashMap();
InputStreamis=null;
try
{
is=this.getClass().getClassLoader().getResourceAsStream(resource);
Documentdocument=newSAXReader().read(is);
Elementroot=document.getRootElement();
if(root.getName().equalsIgnoreCase("mapper"))
{
Stringnamespace=root.attribute("namespace").getText();
for(Elementselect:(List)root.elements("select"))
{
MappermapperModel=newMapper();
mapperModel.setResultType(select.attribute("resultType").getText());
mapperModel.setQuerySql(select.getText().trim());
map.put(namespace+"."+select.attribute("id").getText(),mapperModel);
}
}
}
finally
{
is.close();
}
returnmap;
}
publicInputStreamgetConfiguration()
{
returnconfiguration;
}
publicvoidsetConfiguration(InputStreamconfiguration)
{
this.configuration=configuration;
}
}
SqlSessionFactoryBuilder.javaMybatis模拟类(src/main/java/com/bjpowernode/practice/simulation目录下)
packagecom.bjpowernode.practice.simulation;
importjava.io.InputStream;
/**
*
*模拟SqlSessionFactoryBuilder
*
*/
publicclassSqlSessionFactoryBuilder
{
publicSqlSessionFactorybuild(InputStreamis)
{
SqlSessionFactorysessionFactory=newSqlSessionFactory();
sessionFactory.setConfiguration(is);
returnsessionFactory;
}
}
SqlSessionImpl.javaMybatis模拟类(src/main/java/com/bjpowernode/practice/simulation目录下)
packagecom.bjpowernode.practice.simulation;
importjava.lang.reflect.Method;
importjava.lang.reflect.Proxy;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Map;
/**
*
*模拟SqlSessionImpl
*
*/
publicclassSqlSessionImplimplementsSqlSession
{
/**DBconnection*/
publicstaticConnectionconnection;
privateMapxmlSQLs;
privateListannotationClasses;
publicSqlSessionImpl()
{
/**
*driverString和connString应该是从配置文件读取,这里简化了
*/
finalStringdriverString="org.apache.derby.jdbc.ClientDriver";
finalStringconnString="jdbc:derby://localhost:1527/bjpowernode;create=true";
try
{
Class.forName(driverString);
/**获得DB连接*/
connection=DriverManager.getConnection(connString);
}
catch(Exceptione)
{
System.out.println("获取DBConnection出错!");
}
}
/**
*基于Annotation的数据库操作
*
*/
@Override
publicTgetMapper(Classclazz)
{
TclazzImpl=
(T)Proxy.newProxyInstance(this.getClass().getClassLoader(),newClass[]{clazz},newSQLSelectProxy());
returnclazzImpl;
}
/**
*
*基于XML的查询操作
*/
@Override
publicListselectList(Stringquery)throwsException
{
PreparedStatementpstmt=null;
ResultSetrs=null;
try
{
/**简单的PreparedStatemeJDBC实现*/
pstmt=connection.prepareStatement(xmlSQLs.get(query).getQuerySql());
rs=pstmt.executeQuery();
/**执行查询操作*/
returnexecuteQuery(rs,xmlSQLs.get(query).getResultType());
}
finally
{
if(!rs.isClosed())
{
rs.close();
}
if(!pstmt.isClosed())
{
pstmt.close();
}
}
}
/**
*
*执行查询操作,并将查询到的结果与配置中的ResultType根据变量名一一对应,通过反射调用Set方法注入各个变量的值
*
*@paramrs
*@paramtype
*@return
*@throwsException
*/
publicstaticListexecuteQuery(ResultSetrs,Stringtype)throwsException
{
intcount=rs.getMetaData().getColumnCount();
ListcolumnNames=newArrayList();
for(inti=1;i<=count;i++)
{
columnNames.add(rs.getMetaData().getColumnName(i));
}
finalListlist=newArrayList
UserMapper.xml基于XML的Mapper配置文件(src/main/java/com/bjpowernode/practice/xml目录下)
select* fromUSER_TEST_TB
TestMyBatis.java测试类(src/test/java/com/bjpowernode/practice目录下)
packagecom.bjpowernode.practice;
importcom.bjpowernode.practice.annotation.UserMapper;
importcom.bjpowernode.practice.simulation.SqlSession;
importcom.bjpowernode.practice.simulation.SqlSessionFactory;
importcom.bjpowernode.practice.simulation.SqlSessionFactoryBuilder;
importcom.bjpowernode.practice.simulation.SqlSessionImpl;
importjava.io.InputStream;
importjava.sql.SQLException;
importjava.text.MessageFormat;
importjava.util.List;
importorg.junit.After;
importorg.junit.Before;
importorg.junit.Test;
publicclassTestMyBatis
{
/**配置置文件*/
privateStringsource;
privateInputStreaminputStream;
privateSqlSessionFactorysqlSessionFactory;
@Before
publicvoidsetUp()
{
source="test-mybatis-configuration.xml";
}
/**
*
*基于XML格式配置的测试方法
*
*/
@Test
publicvoidtestXMLConfingure()
{
try
{
/**
*获得Session
*/
inputStream=TestMyBatis.class.getClassLoader().getResourceAsStream(source);
sqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);
SqlSessionsession=sqlSessionFactory.openSession();
/**
*执行Query操作
*/
Listusers=(List)session.selectList("com.bjpowernode.practice.UserMapper.getUser");
System.out.println("QuerybyXMLconfiguration...");
/**
*打印结果
*/
this.printUsers(users);
}
catch(Exceptione)
{
e.printStackTrace();
}
}
/**
*
*基于Annotation配置的测试方法
*
*/
@Test
publicvoidtestAnnotationConfingure()
{
try
{
inputStream=TestMyBatis.class.getClassLoader().getResourceAsStream(source);
sqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);
SqlSessionsession=sqlSessionFactory.openSession();
UserMapperuserMapper=session.getMapper(UserMapper.class);
System.out.println("\r\nQuerybyannotationconfiguration...");
this.printUsers(userMapper.getUser());
}
catch(Exceptione)
{
e.printStackTrace();
}
}
@After
publicvoidclearUp()throwsSQLException
{
if(SqlSessionImpl.connection!=null&&!SqlSessionImpl.connection.isClosed())
{
SqlSessionImpl.connection.close();
}
}
privatevoidprintUsers(finalListusers)
{
intcount=0;
for(Useruser:users)
{
System.out.println(MessageFormat.format("==User[{0}]=================",++count));
System.out.println("UserId:"+user.getId());
System.out.println("UserUserName:"+user.getUsername());
System.out.println("UserPassword:"+user.getPassword());
System.out.println("Usernickname:"+user.getNickname());
}
}
}
以上就是基于XML以及Annotation的方式对Mybatis实现了一个简单的模拟。旨在理解Mybatis的工作原理。
笔者一直觉得当学习一个工具类技术的时候,路线应该是
1.实现一个小例子
2.找材料理解其中原理
3.学习技术细节,并动手全部实现
4.在全部学完之后动手做一个小项目,尽可能的使用这个在技术中的各个环节。
总结
以上所述是小编给大家介绍的模拟Mybatis的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。