1.实例化sqlSessionFactory ,加载数据库配置文件以及mapper.xml 文件到configuration对象中
2.获取sqlSession对象
3.通过动态代理获取接口
4.遵循jdbc规范,通过底层的四大对象的合作完成数据查询和数据转化
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6</version>
</dependency>
1.完成SqlSessionFactory的创建
1.1.生成sqlSession对象
加载数据库配置文件
1.2.实例化configuration对象
加载mapper文件
public class SqlSessionFactory {
private final Configuration conf=new Configuration();
private static final String DB_CONFIG_FILE="db.properties";
private static final String MAPPER_CONFIG_LOCATION="mappers";
/**
* 通过构造方法加载
* 1.数据库配置文件
* 2.加载配置文件
*/
public SqlSessionFactory() {
//1.加载数据库配置文件
loadDbInfo();
//2.加载mapper文件
loadMappersInfo();
}
/**
* 加载数据库配置文件
*/
private void loadDbInfo() {
InputStream dbIs = SqlSessionFactory.class.getClassLoader().getResourceAsStream(DB_CONFIG_FILE);
Properties p = new Properties();
try {
p.load(dbIs);
} catch (IOException e) {
e.printStackTrace();
}
conf.setJdbcDriver(String.valueOf(p.get("db.driver")));
conf.setJdbcUrl(String.valueOf(p.get("jdbc.url")));
conf.setJdbcUsername(String.valueOf(p.get("jdbc.username")));
conf.setJdbcPassword(String.valueOf(p.get("jdbc.password")));
}
/**
* 加载所有的mapper.xml文件
*/
private void loadMappersInfo() {
URL resources = SqlSessionFactory.class.getClassLoader().getResource(MAPPER_CONFIG_LOCATION);
File mappers = new File(resources.getFile());
if (mappers.isDirectory()){
File[] listFiles = mappers.listFiles();
for (File file : listFiles) {
//加载文件
loadMapperInfo(file);
}
}
}
/**
* 加载配置文件
*/
private void loadMapperInfo(File file) {
// 创建reader对象
SAXReader reader = new SAXReader();
Document document=null;
try {
document = reader.read(file);
} catch (DocumentException e) {
e.printStackTrace();
}
//获取根节点元素
Element rootElement = document.getRootElement();
//获取命名空间
String namespace = rootElement.attribute("namespace").getData().toString();
//获取select子列表
List<Element> selects = rootElement.elements("select");
for (Element element : selects) {
//实例化mappedStatement
MappedStatement mappedStatement = new MappedStatement();
//读取id
String id = element.attribute("id").getData().toString();
//读取返回类型
String resultType = element.attribute("resultType").getData().toString();
//读取sql
String sql = element.getData().toString();
String sourceId=namespace+"."+id;
//赋值
mappedStatement.setNamespace(namespace);
mappedStatement.setResultType(resultType);
mappedStatement.setSourceId(sourceId);
mappedStatement.setSql(sql);
//注册到conf中
conf.getMappedStatementMap().put(sourceId,mappedStatement);
}
}
/**
* 获取sqlSession
* @return
*/
public SqlSession openSession(){
return new DefaultSqlSession(conf);
}
}
public interface SqlSession {
/**
* 查询单个对象
* @param statement 方法对应的sql 语句
* @param parameter sql 参数
* @param <T>
* @return
*/
<T> T selectOne(String statement,Object parameter);
/**
* 查询全部
* @param statement 方法对应的sql 语句
* @param parameter sql 参数
* @param <E>
* @return
*/
<E> List<E> selectList(String statement,Object parameter);
/**
* 反射获取mapper对象
* @param type
* @param <T>
* @return
*/
<T> T getMapper(Class<T> type);
}
public class DefaultSqlSession implements SqlSession {
private Configuration conf;
private Executor executor;
public DefaultSqlSession(Configuration conf) {
this.conf = conf;
executor=new DefaultExecutor(conf);
}
@Override
public <T> T selectOne(String statement, Object parameter) {
List<Object> objects = selectList(statement, parameter);
if (objects==null || objects.size()==0){
return null;
}
if (objects.size()==1){
return (T) objects.get(0);
}else {
throw new RuntimeException("Too Many Result.....");
}
}
@Override
public <E> List<E> selectList(String statement, Object parameter) {
MappedStatement mappedStatement = conf.getMappedStatementMap().get(statement);
return executor.query(mappedStatement,parameter);
}
@Override
public <T> T getMapper(Class<T> type) {
MapperProxy mapperProxy = new MapperProxy(this);
return (T) Proxy.newProxyInstance(type.getClassLoader(),new Class[]{type},mapperProxy);
}
}
public class MappedStatement {
private String namespace; // 命名空间
private String sourceId;//方法名
private String resultType;//返回类型
private String sql;//sql 语句
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getSourceId() {
return sourceId;
}
public void setSourceId(String sourceId) {
this.sourceId = sourceId;
}
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 class Configuration {
private String jdbcDriver;
private String jdbcUrl;
private String jdbcUsername;
private String jdbcPassword;
//存放sql 类型
private Map<String,MappedStatement> mappedStatementMap=new HashMap<>();
public String getJdbcDriver() {
return jdbcDriver;
}
public void setJdbcDriver(String jdbcDriver) {
this.jdbcDriver = jdbcDriver;
}
public String getJdbcUrl() {
return jdbcUrl;
}
public void setJdbcUrl(String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
public String getJdbcUsername() {
return jdbcUsername;
}
public void setJdbcUsername(String jdbcUsername) {
this.jdbcUsername = jdbcUsername;
}
public String getJdbcPassword() {
return jdbcPassword;
}
public void setJdbcPassword(String jdbcPassword) {
this.jdbcPassword = jdbcPassword;
}
public Map<String, MappedStatement> getMappedStatementMap() {
return mappedStatementMap;
}
public void setMappedStatementMap(Map<String, MappedStatement> mappedStatementMap) {
this.mappedStatementMap = mappedStatementMap;
}
}
动态代理mapper
public class MapperProxy implements InvocationHandler {
private SqlSession sqlSession;
public MapperProxy(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class<?> returnType = method.getReturnType();
if (Collection.class.isAssignableFrom(returnType)){
return sqlSession.selectList(method.getDeclaringClass().getName()+"."+method.getName(),args==null?null:args[0]);
}else {
return sqlSession.selectOne(method.getDeclaringClass().getName()+"."+method.getName(),args==null?null:args[0]);
}
}
}
定时操作数据库的主体类
public interface Executor {
/**
*查询
* @param ms 封装sql语句的mappedStatement
* @param parameter 查询参数
* @param <E>
* @return
*/
<E> List<E> query(MappedStatement ms,Object parameter);
}
public class DefaultExecutor implements Executor {
private final Configuration conf;
public DefaultExecutor(Configuration conf) {
this.conf = conf;
}
/**
*
* @param ms 封装sql语句的mappedStatement
* @param parameter 查询参数
* @param <E>
* @return
*/
@Override
public <E> List<E> query(MappedStatement ms, Object parameter) {
System.out.println("执行sql"+ms.getSql());
ArrayList<E> ret = new ArrayList<>();
try {
//1.加载驱动
Class.forName(conf.getJdbcDriver());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
//2.连接数据库
connection = DriverManager.getConnection(conf.getJdbcUrl(), conf.getJdbcUsername(), conf.getJdbcPassword());
//3.预加载sql
preparedStatement=connection.prepareStatement(ms.getSql());
parameterize(preparedStatement,parameter);
//4.执行sql
resultSet = preparedStatement.executeQuery();
//5.映射结果集
handlerResultSet(resultSet,ret,ms.getResultType());
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
resultSet.close();
preparedStatement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return ret;
}
/**
* 映射结果集
* @param resultSet
* @param ret
* @param resultType
* @param <E>
*/
private <E> void handlerResultSet(ResultSet resultSet, ArrayList<E> ret, String resultType) {
Class<E> eClass=null;
try {
eClass= (Class<E>) Class.forName(resultType);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
while (resultSet.next()){
Object entity = eClass.newInstance();
ReflectionUtil.setPropToBeanFromResultSet(entity,resultSet);
ret.add((E) entity);
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 处理sql
* @param preparedStatement
* @param parameter
*/
private void parameterize(PreparedStatement preparedStatement, Object parameter) throws SQLException {
if (parameter instanceof Integer){
preparedStatement.setInt(1, (Integer) parameter);
}else if (parameter instanceof Long){
preparedStatement.setLong(1, (Long) parameter);
}else if (parameter instanceof String){
preparedStatement.setString(1, (String) parameter);
}
}
}
反射解析查询结果
public class ReflectionUtil {
/**
* 为指定bean 的propName属性赋值为value
* @param bean 目标对象
* @param propName 对象属性名
* @param value 值
*/
public static void setPropToBean(Object bean,String propName,Object value){
Field f;
try {
f= bean.getClass().getDeclaredField(propName); //获取对象指定属性
f.setAccessible(true); //将对象设置为可通过反射进行访问
f.set(bean,value);//为属性赋值
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 从result 中读取一行数据 并填充的实体bean
* @param entity
* @param resultSet
*/
public static void setPropToBeanFromResultSet(Object entity, ResultSet resultSet) throws SQLException {
Field[] declaredFields = entity.getClass().getDeclaredFields();//通过反射获取对象的所有字段
for (int i = 0; i < declaredFields.length; i++) {
if (declaredFields[i].getType().getSimpleName().equals("String")){
setPropToBean(entity,declaredFields[i].getName(),resultSet.getString(declaredFields[i].getName()));
}else if (declaredFields[i].getType().getSimpleName().equals("Integer")){
setPropToBean(entity,declaredFields[i].getName(),resultSet.getInt(declaredFields[i].getName()));
}else if (declaredFields[i].getType().getSimpleName().equals("Long")){
setPropToBean(entity,declaredFields[i].getName(),resultSet.getLong(declaredFields[i].getName()));
}
}
}
}