手写mybatis框架
我们首先要了解JDBC和mybtis的执行流程
public static void main ( String[ ] args) {
try {
Class. forName ( "com.mysql.jdbc.Driver" ) ;
Connection connection = DriverManager. getConnection ( "jdbc:mysql://localhost:3306/test" , "root" , "root" ) ;
Statement statement = connection. createStatement ( ) ;
statement. execute ( "select * from user;" ) ;
ResultSet resultSet = statement. getResultSet ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
public class TestMain {
private SqlSession session;
@Before
public void before ( ) throws Exception{
InputStream is = Resources. getResourceAsStream ( "myBatis-config.xml" ) ;
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder ( ) ;
SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder. build ( new InputStreamReader ( is) ) ;
session = sessionFactory. openSession ( ) ;
}
@After
public void after ( ) {
try {
session. close ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
@Test
public void test ( ) {
DeptDao dao = session. getMapper ( DeptDao. class ) ;
List list = dao. findAll ( ) ;
System. out. println ( list. get ( 0 ) ) ;
System. out. println ( list. get ( 1 ) ) ;
}
}
手写mybtis框架
加载配置文件,这里我们只加载mapper中的sql语句;我们根据DAO中的方法和XML的SQL标签的ID一一对应;
提供一个根据方法名去获取DAO方法对应的SQL和该SQL执行后返回的数据类型;
public class Configuration {
private Connection connection;
private String path;
private String daoName;
private Map sqlMap = new HashMap ( ) ;
private Map typeMap = new HashMap ( ) ;
public Map getSqlMap ( ) {
return sqlMap;
}
public Map getTypeMap ( ) {
return typeMap;
}
public synchronized Connection getConnection ( ) {
return connection;
}
public Configuration ( String path) {
this . path = path;
try {
Class. forName ( "com.mysql.jdbc.Driver" ) ;
connection = DriverManager. getConnection ( "jdbc:mysql://localhost:3306/test" , "root" , "root" ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
initConfiguration ( ) ;
}
public void close ( ) {
try {
if ( connection != null) {
connection. close ( ) ;
}
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
public void initConfiguration ( ) {
try {
URL url = Configuration. class . getClassLoader ( ) . getResource ( "" ) ;
File fileFolder = new File ( url. getPath ( ) + path) ;
String[ ] fileStrs = fileFolder. list ( ) ;
for ( int i= 0 ; fileStrs != null && fileStrs. length > i; i++ ) {
String fullDaoName = fileStrs[ i] ;
daoName = fullDaoName. substring ( 0 , fullDaoName. indexOf ( "." ) ) ;
InputStream in = Resources. getResourceAsStream ( path + "/" + fullDaoName) ;
SAXReader saxReader = new SAXReader ( ) ;
Document document = saxReader. read ( new InputStreamReader ( in) ) ;
setSqlMapAndTypeMethod ( document. getRootElement ( ) , ( String) null) ;
}
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
public void setSqlMapAndTypeMethod ( Element rootElement, String methodName) {
List< Attribute> attributeList = rootElement. attributes ( ) ;
for ( int i= 0 ; attributeList != null && attributeList. size ( ) > 0 && attributeList. size ( ) > i; i++ ) {
Attribute attribute = attributeList. get ( i) ;
String name = attribute. getName ( ) ;
String value = attribute. getValue ( ) ;
if ( "id" . equals ( name) ) {
methodName = daoName + "." + value;
sqlMap. put ( methodName, rootElement. getStringValue ( ) ) ;
} else if ( "resultType" . equals ( name) ) {
typeMap. put ( methodName, value) ;
}
}
List< Element> elementList = rootElement. elements ( ) ;
for ( int i= 0 ; elementList != null && elementList. size ( ) > 0 && elementList. size ( ) > i; i++ ) {
Element element = elementList. get ( i) ;
setSqlMapAndTypeMethod ( element, methodName) ;
}
}
public static void main ( String[ ] args) {
Configuration configuration = new Configuration ( "mapper" ) ;
configuration. initConfiguration ( ) ;
}
}
该类的作用是执行代理监听类的实现类,例如
onclick是代理监听类,func相当于ProxyFactory,而实现类就是StatementHandler;
public class ProxyFactory implements InvocationHandler {
private Configuration configuration;
private Class classFile ;
public ProxyFactory ( Configuration configuration, Class classFile ) {
this . configuration = configuration;
this . classFile = classFile;
}
public Object invoke ( Object proxy, Method method, Object[ ] args) throws Throwable {
String classFullName = classFile. getName ( ) ;
int size = classFullName. lastIndexOf ( "." ) ;
String methodName = classFullName. substring ( size + 1 ) + "." + method. getName ( ) ;
StatementHandler statementHandler = new StatementHandler ( configuration, methodName) ;
return statementHandler. execute ( ) ;
}
}
该类相当于代理监听类的实现类,它主要是获取代理类中需要执行的方法,根据方法名在configuration中获取对应方法需要执行的sql语句
public class StatementHandler {
private Configuration configuration;
private Statement statement;
private String method;
public StatementHandler ( Configuration configuration, String method) {
this . method = method;
this . configuration = configuration;
}
public Object execute ( ) throws Exception{
Map sqlMap = configuration. getSqlMap ( ) ;
Connection connection = configuration. getConnection ( ) ;
statement = connection. createStatement ( ) ;
statement. execute ( sqlMap. get ( method) . toString ( ) ) ;
ResultSet resultSet = statement. getResultSet ( ) ;
List list = new ArrayList ( ) ;
while ( resultSet. next ( ) ) {
Class classFile = Class. forName ( ( String) configuration. getTypeMap ( ) . get ( method) ) ;
Field fields[ ] = classFile. getDeclaredFields ( ) ;
Object classObj = classFile. newInstance ( ) ;
for ( int i= 0 ; i< fields. length; i++ ) {
Field field = fields[ i] ;
String name = field. getName ( ) ;
Class typeClass = field. getType ( ) ;
field. setAccessible ( true ) ;
String resultValue = resultSet. getString ( name) ;
if ( Integer. class == typeClass) {
field. set ( classObj, Integer. valueOf ( resultValue) ) ;
} else if ( String. class == typeClass) {
field. set ( classObj, String. valueOf ( resultValue) ) ;
}
}
list. add ( classObj) ;
}
close ( ) ;
return list;
}
public void close ( ) {
try {
if ( statement != null) {
statement. close ( ) ;
}
} catch ( Exception e) {
e. printStackTrace ( ) ;
}
}
}
该类的最要作用是获取代理监听类,getMapper返回的是代理类
public class SqlSessionFactory {
private Configuration configuration;
public SqlSessionFactory ( Configuration configuration) {
this . configuration = configuration;
}
public Object getMapper ( Class classFile ) {
ProxyFactory proxyFactory = new ProxyFactory ( configuration, classFile) ;
Class classArray [ ] = { classFile} ;
return Proxy. newProxyInstance ( classFile. getClassLoader ( ) , classArray, proxyFactory) ;
}
}
测试类
public class TestMain {
private SqlSessionFactory sqlSessionFactory;
private Configuration configuration;
@Before
public void before ( ) {
configuration = new Configuration ( "mapper" ) ;
sqlSessionFactory = new SqlSessionFactory ( configuration) ;
}
@After
public void after ( ) {
configuration. close ( ) ;
}
@Test
public void test ( ) {
DeptDao deptDao = ( DeptDao) sqlSessionFactory. getMapper ( DeptDao. class ) ;
List list = deptDao. findAll ( ) ;
System. out. println ( list. toString ( ) ) ;
}
}