自定义实现Mybatis框架


前言

本文分为两部分: 第一部分用mybatis写一个入门程序 第二部分把入门程序中的Mybatis去掉用自定义框架代替

提示:以下是本篇文章正文内容

一、Mybatis框架入门程序

1.1、导入表和数据

DROP TABLE IF EXISTS USER;

CREATE TABLE USER (
  id INT(11) NOT NULL AUTO_INCREMENT,
  username VARCHAR(32) NOT NULL COMMENT '用户名称',
  birthday DATETIME DEFAULT NULL COMMENT '生日',
  sex CHAR(1) DEFAULT NULL COMMENT '性`user`别',
  address VARCHAR(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY  (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;



INSERT  INTO USER(id,username,birthday,sex,address) VALUES (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'老陈','2018-02-27 17:47:08','男','北京'),(43,'老梁','2018-02-27 17:47:08','男','北京');





DROP TABLE IF EXISTS account;

CREATE TABLE account (
  accountId INT(11) NOT NULL AUTO_INCREMENT,
  UID INT(11) DEFAULT NULL COMMENT '用户编号',
  MONEY DOUBLE DEFAULT NULL COMMENT '金额',
  PRIMARY KEY  (accountId),
  KEY FK_Reference_8 (UID),
  CONSTRAINT FK_Reference_8 FOREIGN KEY (UID) REFERENCES USER (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;



INSERT  INTO account(accountId,UID,MONEY) VALUES (1,41,1000),(2,42,1000),(3,43,2000);

1.2、准备数据库环境、创建项目、添加依赖

在这里插入图片描述

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mymybatis</groupId>
	<artifactId>mybatis_my</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.46</version>
		</dependency>
		<!-- mybatis依赖 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.4.5</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
	</dependencies>
</project>

1.3、SqlMapConfig.xml配置

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 数据库连接信息 -->
	<!-- 	environments 配置所有数据库连接
				default:默认连接信息
			environment:配置一个数据库连接信息
				id:唯一标记
					transactionManager:事务管理器
						type:事务管理器类型
							jdbc:使用mybatis自带的事务管理器
								Connection.setAutoCommit(false)
                               	Connection.commit()
                               	Connection.rollback()
				dataSource:数据源(连接池)
					type:数据源类型
						pooled:使用mybatis自带的数据源
					
			
	 -->
	<environments default="mysql">
		<environment id="mysql">
			<transactionManager type="jdbc"></transactionManager>
			<dataSource type="pooled">
				<property name="url" value="jdbc:mysql://192.168.211.130:3306/mybatis_demo"/>
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
	</environments>
	<!-- 相关Dao接口映射(文件或类) -->
	<mappers>
		<mapper resource="com/mymybatis/dao/UserDao.xml"/>
	</mappers>
</configuration>         

1.4实体类

package com.mymybatis.pojo;

import java.util.Date;

public class User {
	private Integer id;
	private String username;
	private Date birthday;
	private String sex;
	private String address;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address="
				+ address + "]";
	}
	
	
	
}


1.5、编写UserDao接口和UserDao接口映射文件

在这里插入图片描述

package com.mymybatis.dao;

import java.util.List;

import com.mymybatis.pojo.User;

public interface UserDao {
	List<User> findAll();
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mymybatis.dao.UserDao">
	<select id="findAll"   resultType="com.mymybatis.pojo.User">
		select * from user;
	</select>
</mapper>

1.6、测试

package com.mymybatis.test;

import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.mymybatis.dao.UserDao;
import com.mymybatis.pojo.User;

public class Demo {
	@Test
	public void test1() throws Exception{
		//1、加载SqlMapconfig.xml
		InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
		//2、创建SQLSessionFactory工厂
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		SqlSessionFactory factory = builder.build(in);
		//3、创建SQLSession
		SqlSession sqlSession = factory.openSession();
		//4、生成Dao接口代理对象
		UserDao userDao = sqlSession.getMapper(UserDao.class);
		List<User> userList = userDao.findAll();
		for (User user : userList) {
			System.out.println(user);
		}
		sqlSession.close();
		in.close();
		
	}
}

二、自定义实现Mybatis框架

2.1、把刚才的入门程序复制一份出来

在这里插入图片描述

2.2、自定义框架 环境准备

使用的技术点

  1. JDK动态代理
  2. dom4j+xpath解析xml
  3. jdbc
  4. jdbc元数据(Metadata)(封装数据库结果集)
  5. 反射

2.3、把mybatis的依赖去掉,添加新的依赖

在这里插入图片描述

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mymybatis</groupId>
	<artifactId>mybatis_my</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<!--mysql驱动  -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.46</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<!--dom4j  -->
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>
		<!-- xpath -->
		<dependency>
			<groupId>jaxen</groupId>
			<artifactId>jaxen</artifactId>
			<version>1.1.6</version>
		</dependency>
		<!-- druid数据源 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.6</version>
		</dependency>
	</dependencies>
</project>

2.4、修改测试类

package com.mymybatis.test;

import java.util.List;

import org.junit.Test;

import com.mymybatis.dao.UserDao;

import com.mymybatis.pojo.User;

public class Demo {
	@Test
	public void test1() throws Exception{
	
		//1、创建SQLSessionFactory工厂
		SqlSessionFactory factory = new SqlSessionFactory();
		//2、创建SQLSession
		SqlSession sqlSession = factory.openSession();
		//3、生成Dao接口代理对象
		UserDao userDao = sqlSession.getMapper(UserDao.class);
		System.out.println("代理对象"+userDao.getClass());
		
		List<User> userList = userDao.findAll();
		for (User user : userList) {
			System.out.println(user);
		}
		
		
	}
}


注意这里的报错我们先不管

2.5自定义框架分析

分析测试代码,我们接下来要实现以下步骤

  1. 定义SqlSessionFactory类,提供openSession方法
  2. 定义SqlSession接口,定义DefaultSqlSession实现类,定义getMapper方法
  3. 在SqlSessionFactory的openSession方法,返回SqlSession接口的实现对像(DefaultSqlSession)

2.6自定义框架(二)定义核心Api

package com.mymybatis.mybatis.factory;

public class SqlSessionFactory {
	/**
	 * 创建SqlSession实现对象
	 */
	public void openSession() {
		
	}
}

2.7、定义SqlSession接口,定义DefaultSqlSession实现类,定义getMapper方法

package com.mymybatis.mybatis.session;

public interface SqlSession {
	/**
	 * 定义getMapper用于生成Dao接口代理对象
	 * 参数:传入需要生成的dao接口类型
	 * 返回值:最后生成代理对象
	 */
	public <T> T getMapper(Class<T> daoClass);
}

定义SqlSession接口的实现

package com.mymybatis.mybatis.session.impl;

import com.mymybatis.mybatis.session.SqlSession;
/**
 * SqlSession接口的默认实现
 * @author 16427
 *
 */
public class DefaultSqlSession implements SqlSession{

	@Override
	public <T> T getMapper(Class<T> daoClass) {
		
		return null;
	}

}

2.8在SqlSessionFactory的openSession方法,返回SqlSession接口的实现对象

package com.mymybatis.mybatis.factory;

import com.mymybatis.mybatis.session.SqlSession;
import com.mymybatis.mybatis.session.impl.DefaultSqlSession;

public class SqlSessionFactory {
	/**
	 * 创建SqlSession实现对象
	 */
	public SqlSession openSession() {
		return new DefaultSqlSession();
	}
}

2.9定义好以上的Api之后,测试代码不会报错了,但是运行的时候报错

在这里插入图片描述
原因:SqlSession接口实现类(DefaultSqlSession)的getMapper方法没有返回代理对象

2.10自定义框架完善DefaultSqlSession

让SqlSession的getMapper生成JDK代理对象

package com.mymybatis.mybatis.session.impl;

import java.lang.reflect.Proxy;

import com.mymybatis.mybatis.proxy.MapperProxy;
import com.mymybatis.mybatis.session.SqlSession;
/**
 * SqlSession接口的默认实现
 * @author 16427
 *
 */
public class DefaultSqlSession implements SqlSession{
	/**
	 * 使用JDK动态代理生成接口代理对象(接口代理)
	 * 参数一:类加载器,通常提供当前类的类加载器即可
	 * 参数二:传入接口列表
	 * 参数三:InvocationHandler接口实现类,可以提供匿名内部类实现
	 */
	@Override
	public <T> T getMapper(Class<T> daoClass) {
		
		return (T)Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(),
				new Class[] {daoClass},
				new MapperProxy());
	}

}

提取了InvocationHandler接口的实现,MapperProxy类

package com.mymybatis.mybatis.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * InvocationHandler接口的实现类
 * @author 16427
 *
 */
public class MapperProxy implements InvocationHandler{

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("========="+method.getName());
		return null;
	}

}

执行测试类
在这里插入图片描述

2.11自定义框架完善MapperProxy A定义Configuration、Mapper类

2.11.1设计Configuration用于完成所有配置的加载工作

public class Configuration {
    
    //定义变量,用于存放数据库连接参数
    private String url;
    private String driver;
    private String username;
    private String password;
    
    //定义用于存储整个项目所有方法信息
    /**
     * key:  namespace+.+id    com.itheima.dao.UserDao.findAll
     * value: 整个方法的信息
     */
    private Map<String,Mapper> mappers  = new HashMap<>();
    
    
  
}

同时,设计一个Mapper,用于封装每个方法信息

package com.mymybatis.mybatis.config;
/**
 * 该类用于
 * @author 16427
 *
 */
public class Mapper {
	private String id;
	private String resultType;
	private String sql;
	private String namespace;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getResultType() {
		return resultType;
	}
	public void setResultType(String resultType) {
		this.resultType = resultType;
	}
	public String getSql() {
		return sql;
	}
	public void setSql(String sql) {
		this.sql = sql;
	}
	public String getNamespace() {
		return namespace;
	}
	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}
	

}

继续补充Configuration的逻辑,完成SqlMapConfig.xml及映射文件加载工作

package com.mymybatis.mybatis.config;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 该类用于封装项目所有XML配置文件
 * @author 16427
 *
 */
public class Configuration {
	//定义变量,用于存储数据库连接参数
	private String url;
	private String driver;
	private String username;
	private String password;
	//定义用于存储整个项目所有方法信息
	private Map<String,Mapper> mappers=new HashMap<>();
	//定义configuration静态对象
	private static Configuration configuration=null;
	//私有构造方法使用单列模式
	private Configuration() {
		loadSqlMapConfig();
	}
	


	public static Configuration getConfiguration() {
		if(configuration==null) {
			return new Configuration();
		}else {
			return configuration;
		}
	}
	/**
	 * 读取SqlMapConfig.xml(单例模式只读取1次)
	 */
	private void loadSqlMapConfig() {
		//使用Dom4j+xpath读取xml配置
		//1.创建SaxReader
		SAXReader saxReader = new SAXReader();
		//2.加载XML返回Document对象
		InputStream in = Configuration.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
		try {
			Document documnet= saxReader.read(in);
			//3.获取根标签
			Element rootElement = documnet.getRootElement();
			/*4.继续读取字标签
			读取property标签(使用xpath更方便获取标签)
			/  一级一级获取
			 //  直接获取指定标签
			*/
			List<Element> propElements=rootElement.selectNodes("//property");
			for (Element propElement : propElements) {
				String name=propElement.attributeValue("name");
				String value = propElement.attributeValue("value");
				if("url".equals(name)) {
					this.url=value;
				}
				if("driver".equals(name)) {
					this.driver=value;
				}
				if("username".equals(name)) {
					this.username=value;
				}
				if("password".equals(name)) {
					this.password=value;
				}
			}
			//继续读取子标签
			List<Element> mapperElements=rootElement.selectNodes("//mapper");
			for (Element mapperElement : mapperElements) {
				String mapperResource = mapperElement.attributeValue("resource");
				//加载dao接口配置文件
				loadMapper(mapperResource);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void loadMapper(String mapperResource) {
		//使用Dom4j+xpath读取xml配置
		//创建SAXReader
		SAXReader saxReader = new SAXReader();
		//加载xml返回du
		InputStream in = Configuration.class.getClassLoader().getResourceAsStream(mapperResource);
		try {
			Document document = saxReader.read(in);
			//获取根标签
			Element rootElement = document.getRootElement();
			String namespace = rootElement.attributeValue("namespace");
			List<Element> selectElement = rootElement.selectNodes("select");//先不管写操作
			for (Element element : selectElement) {
				Mapper mapper = new Mapper();
				String id=element.attributeValue("id");
				String resultType = element.attributeValue("resultType");
				String sql = element.getTextTrim();
				mapper.setId(id);
				mapper.setResultType(resultType);
				mapper.setSql(sql);
				mapper.setNamespace(namespace);
				//存入Map集合
                //namespace+id 
				mappers.put(namespace+"."+id, mapper);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

2.12、自定义框架完善MapperProxy定义Executor类

2.12.1、在Configuration类,提供获取方法映射信息,连接池对象的方法

package com.mymybatis.mybatis.config;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * 该类用于封装项目所有XML配置文件
 * @author 16427
 *
 */
public class Configuration {
	//定义变量,用于存储数据库连接参数
	private String url;
	private String driver;
	private String username;
	private String password;
	//定义连接池对象
	private DataSource dataSource;
	//定义用于存储整个项目所有方法信息
	private Map<String,Mapper> mappers=new HashMap<>();
	//定义configuration静态对象
	private static Configuration configuration=null;
	//私有构造方法使用单列模式
	private Configuration() {
		loadSqlMapConfig();
	}
	


	public static Configuration getConfiguration() {
		if(configuration==null) {
			return new Configuration();
		}else {
			return configuration;
		}
	}
	/**
	 * 读取SqlMapConfig.xml(单例模式只读取1次)
	 */
	private void loadSqlMapConfig() {
		//使用Dom4j+xpath读取xml配置
		//1.创建SaxReader
		SAXReader saxReader = new SAXReader();
		//2.加载XML返回Document对象
		InputStream in = Configuration.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
		try {
			Document documnet= saxReader.read(in);
			//3.获取根标签
			Element rootElement = documnet.getRootElement();
			/*4.继续读取字标签
			读取property标签(使用xpath更方便获取标签)
			/  一级一级获取
			 //  直接获取指定标签
			*/
			List<Element> propElements=rootElement.selectNodes("//property");
			for (Element propElement : propElements) {
				String name=propElement.attributeValue("name");
				String value = propElement.attributeValue("value");
				if("url".equals(name)) {
					this.url=value;
				}
				if("driver".equals(name)) {
					this.driver=value;
				}
				if("username".equals(name)) {
					this.username=value;
				}
				if("password".equals(name)) {
					this.password=value;
				}
			}
			//继续读取子标签
			List<Element> mapperElements=rootElement.selectNodes("//mapper");
			for (Element mapperElement : mapperElements) {
				String mapperResource = mapperElement.attributeValue("resource");
				//加载dao接口配置文件
				loadMapper(mapperResource);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void loadMapper(String mapperResource) {
		//使用Dom4j+xpath读取xml配置
		//创建SAXReader
		SAXReader saxReader = new SAXReader();
		//加载xml返回du
		InputStream in = Configuration.class.getClassLoader().getResourceAsStream(mapperResource);
		try {
			Document document = saxReader.read(in);
			//获取根标签
			Element rootElement = document.getRootElement();
			String namespace = rootElement.attributeValue("namespace");
			List<Element> selectElement = rootElement.selectNodes("select");//先不管写操作
			for (Element element : selectElement) {
				Mapper mapper = new Mapper();
				String id=element.attributeValue("id");
				String resultType = element.attributeValue("resultType");
				String sql = element.getTextTrim();
				mapper.setId(id);
				mapper.setResultType(resultType);
				mapper.setSql(sql);
				mapper.setNamespace(namespace);
				//存入Map集合
                //namespace+id 
				mappers.put(namespace+"."+id, mapper);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	//不用向外提供连接信息只需要向外提供连接池对象即可
	public DataSource getDataSource() {
		if(dataSource==null) {
			DruidDataSource dataSource = new DruidDataSource();
			dataSource.setUsername(username);
			dataSource.setUrl(url);
			dataSource.setPassword(password);
			dataSource.setDriverClassName(driver);
			this.dataSource=dataSource;
		}
		return dataSource;
	}
}

2.12.2、设计Executor类,提供selectList方法,完成最后的数据库查询与结果封装

package com.mymybatis.mybatis.util;

import java.util.List;

import javax.sql.DataSource;

import com.mymybatis.mybatis.config.Mapper;
/**
 * 该类用于
 * 1)使用JDBC执行sql语句
 * 2)把SQL语句执行结果级封装成对象返回
 * @author 16427
 *
 */
public class Executor {
	/**
	 * 查询多个记录
	 * @param mapper  通过XML配置匹配到方法映射信息(包括执行的SQL语句)
	 * @param dataSource 执行sql语句需要的对象
	 * @return
	 */
	public static List selectList(Mapper mapper,DataSource dataSource) {
		return null;
	}
}

2.12.3、在MapperProxy编写完成核心逻辑

package com.mymybatis.mybatis.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

import javax.sql.DataSource;

import com.mymybatis.mybatis.config.Configuration;
import com.mymybatis.mybatis.config.Mapper;
import com.mymybatis.mybatis.util.Executor;

/**
 * InvocationHandler接口的实现类
 *
 */
public class MapperProxy implements InvocationHandler{

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//1.读取xml配置文件
		Configuration configuration = Configuration.getConfiguration();
		//2.获取封装好XML信息的JAVA对象
		Map<String, Mapper> mappers = configuration.getMappers();
		DataSource dataSource = configuration.getDataSource();
		//3.从配置信息获取需要执行的sql语句
		//3.1获取当前执行的那个接口的那个方法
		//方法名称
		String methodName = method.getName();
		//方法所在接口类型
		String interName = method.getDeclaringClass().getName();
		Mapper mapper = mappers.get(interName+"."+methodName);
		if(mapper==null) {
			throw new RuntimeException("该方法没有在XML进行映射");
		}
		//4.执行SQL语句,获取结果集
		//5.把结果集封装成java对象
		return Executor.selectList(mapper, dataSource);
	}

}


package com.mymybatis.mybatis.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import com.mymybatis.mybatis.config.Mapper;
/**
 * 该类用于
 * 1)使用JDBC执行sql语句
 * 2)把SQL语句执行结果级封装成对象返回
 * @author 16427
 *
 */
public class Executor {
	/**
	 * 查询多个记录
	 * @param mapper  通过XML配置匹配到方法映射信息(包括执行的SQL语句)
	 * @param dataSource 执行sql语句需要的对象
	 * @return
	 */
	public static List selectList(Mapper mapper,DataSource dataSource) {
		//获取需要执行的sql
		String sql = mapper.getSql();
		//获取需要封装每条记录的对象
		String resultType = mapper.getResultType();
		//设计list用于存储所有查询的结果
		List list=new ArrayList<>();
		try {
			//获取连接
			Connection connection = dataSource.getConnection();
			//准备sql语句
			PreparedStatement stmt = connection.prepareStatement(sql);
			//执行sql
			ResultSet rs = stmt.executeQuery();
			//获取字节码对象
			Class clazz = Class.forName(resultType);
			//获取jdbc元数据
			ResultSetMetaData metaData = rs.getMetaData();
			//通过元数据获取字段数量
			Integer columnCount = metaData.getColumnCount();
			//把结果集封装到结果集合
			while (rs.next()) {
				//创建需要封装的每条记录的对象
				Object obj = clazz.newInstance();
				//把每条记录的字段值传入对象
				/**
				 * 获取每个对象的属性名称,获取每条记录的每个字段值(对应关联:属性名称和字段名称保持一致)
				 */
				for(int i=1;i<=columnCount;i++) {
					//下标都是从1开始
					//用元数据获取每个字段名称
					String columnName = metaData.getColumnName(i);
					//每个字段值
					Object columnValue = rs.getObject(i);
					//使用反射给obj对象的username属性赋值
					Field field = clazz.getDeclaredField(columnName);
					field.setAccessible(true);
					/**
					 * 参数一赋值的对象
					 * 参数二需要给的值
					 * 
					 */
					field.set(obj, columnValue);
					
				}
				//2.3把封装好的每个对象存入list集合
				list.add(obj);
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
		
		return list;
	}
}

注意:如果在网络不稳定的情况下会报错
原因是在SqlMapConfig.xml和UserDao.xml这两个配置文件中有个约束(当我们dom4j读取配置文件的时候就会扫描到这个网址并且尝试连接网址中的文件,如果网络不稳定的情况下就可能报错)

在这里插入图片描述
解决方法把约束删了就可以(如果用mybatis不报错的原因是我们在依赖的时候已经有约束文件)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值