自定义持久层框架MyORMFramework(三)—框架实现
框架端
定义数据源配置和映射语句实体
Configuration
@Data
public class Configuration {
private DataSource dataSource;
/**
* key: statementId value:封装好的mappedStatement对象
*/
Map mappedStatementMap = new HashMap<>();
}
MappedStatement
@Data
public final class MappedStatement {
private String id;
/**
* sql语句
*/
private String sql;
/**
* 参数值类型
*/
private Class> parameterType;
/**
* 返回值类型
*/
private Class> resultType;
}
定义配置文件访问的工具类
public class Resources {
/**
* 根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中
*
* @param path
* @return
*/
public static InputStream getResourceAsSteam(String path) throws IOException {
InputStream in = Resources.class.getClassLoader().getResourceAsStream(path);
if (in == null) {
throw new IOException("找不到资源" + path);
}
return in;
}
}
定义SqlSessionFactoryBuilder
public class SqlSessionFactoryBuilder {
private Configuration configuration;
public SqlSessionFactoryBuilder() {
this.configuration = new Configuration();
}
public SqlSessionFactory build(InputStream inputStream) throws
DocumentException, PropertyVetoException, ClassNotFoundException {
//1.dom4j解析配置⽂件,封装Configuration
XMLConfigerBuilder xmlConfigerBuilder = new
XMLConfigerBuilder(configuration);
Configuration configuration =
xmlConfigerBuilder.parseConfiguration(inputStream);
//2.创建SqlSessionFactory对象(工厂类),生产sqlSession:会话对象
SqlSessionFactory sqlSessionFactory = new
DefaultSqlSessionFactory(configuration);
return sqlSessionFactory;
}
}
数据源配置和映射语句解析XMLConfigBuilder、XMLMapperBuilder
XMLConfigBuilder
public class XMLConfigerBuilder {
private Configuration configuration;
public XMLConfigerBuilder() {
this.configuration = new Configuration();
}
/**
* 该方法就是使用dom4j对配置文件进行解析,封装Configuration
*/
public Configuration parseConfig(InputStream inputStream) throws DocumentException, PropertyVetoException, IOException, ClassNotFoundException {
Document document = new SAXReader().read(inputStream);
//
Element rootElement = document.getRootElement();
List list = rootElement.selectNodes("//property");
Properties properties = new Properties();
for (Element element : list) {
String name = element.attributeValue("name");
String value = element.attributeValue("value");
properties.setProperty(name, value);
}
//连接池
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
comboPooledDataSource.setUser(properties.getProperty("username"));
comboPooledDataSource.setPassword(properties.getProperty("password"));
configuration.setDataSource(comboPooledDataSource);
//mapper.xml解析: 拿到路径--字节输入流---dom4j进行解析
List mapperList = rootElement.selectNodes("//mapper");
for (Element element : mapperList) {
String mapperPath = element.attributeValue("resource");
InputStream resourceAsSteam = Resources.getResourceAsSteam(mapperPath);
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);
xmlMapperBuilder.parse(resourceAsSteam);
}
return configuration;
}
}
XMLMapperBuilder
public class XMLMapperBuilder {
private Configuration configuration;
public XMLMapperBuilder(Configuration configuration) {
this.configuration = configuration;
}
public void parse(InputStream inputStream) throws DocumentException,
ClassNotFoundException {
Document document = new SAXReader().read(inputStream);
Element rootElement = document.getRootElement();
String namespace = rootElement.attributeValue("namespace");
List select = rootElement.selectNodes("select");
for (Element element : select) {
//id的值
String id = element.attributeValue("id");
String parameterType = element.attributeValue("parameterType");
String resultType = element.attributeValue("resultType");
//输⼊参数class
Class> parameterTypeClass = getClassType(parameterType);
//返回结果class
Class> resultTypeClass = getClassType(resultType);
//statementId
String key = namespace + "." + id;
//sql语句
String textTrim = element.getTextTrim();
//封装 mappedStatement
MappedStatement mappedStatement = new MappedStatement();
mappedStatement.setId(id);
mappedStatement.setParameterType(parameterTypeClass);
mappedStatement.setResultType(resultTypeClass);
mappedStatement.setSql(textTrim);
//填充 configuration
configuration.getMappedStatementMap().put(key, mappedStatement);
}
}
private Class> getClassType (String parameterType) throws
ClassNotFoundException {
Class> aClass = Class.forName(parameterType);
return aClass;
}
}
SqlSessionFactory 接口及DefaultSqlSessionFactory 实现类
SqlSessionFactory
public interface SqlSessionFactory {
SqlSession openSession();
}
DefaultSqlSessionFactory
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
return new DefaultSqlSession(configuration);
}
}
SqlSession 接口及 DefaultSqlSession 实现类
SqlSession
public interface SqlSession {
/**
* 查询所有
*
* @param statementId
* @param params
* @param
* @return
* @throws Exception
*/
List selectList(String statementId, Object... params) throws Exception;
/**
* 根据条件查询单个
*
* @param statementId
* @param params
* @param
* @return
* @throws Exception
*/
T selectOne(String statementId, Object... params) throws Exception;
}
DefaultSqlSession
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
public DefaultSqlSession(Configuration configuration) {
this.configuration = configuration;
}
@Override
public List selectList(String statementid, Object... params) throws Exception {
//将要去完成对simpleExecutor里的query方法的调用
SimpleExecutor simpleExecutor = new SimpleExecutor();
MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementid);
List
SQL执行器接口和实现类Executor、SimpleExecutor
Executor
public interface Executor {
/**
* 执行查询SQL
* @param configuration
* @param mappedStatement
* @param params
* @param
* @return
* @throws Exception
*/
List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception;
}
SimpleExecutor
/**
* SQL执行器实现
*
* @author zjq
* @date 2022/3/15
*/
public class SimpleExecutor implements Executor {
@Override
public List query(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
// 1. 注册驱动,获取连接
Connection connection = configuration.getDataSource().getConnection();
// 2. 获取sql语句 : select * from user where id = #{id} and username = #{username}
//转换sql语句: select * from user where id = ? and username = ? ,转换的过程中,还需要对#{}里面的值进行解析存储
String sql = mappedStatement.getSql();
BoundSql boundSql = getBoundSql(sql);
// 3.获取预处理对象:preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
// 4. 设置参数
//获取到了参数的全路径
String paramterType = mappedStatement.getParamterType();
Class> paramtertypeClass = getClassType(paramterType);
List parameterMappingList = boundSql.getParameterMappingList();
for (int i = 0; i < parameterMappingList.size(); i++) {
ParameterMapping parameterMapping = parameterMappingList.get(i);
String content = parameterMapping.getContent();
//反射
Field declaredField = paramtertypeClass.getDeclaredField(content);
//暴力访问
declaredField.setAccessible(true);
Object o = declaredField.get(params[0]);
preparedStatement.setObject(i + 1, o);
}
// 5. 执行sql
ResultSet resultSet = preparedStatement.executeQuery();
//String resultType = mappedStatement.getResultType();
//Class> resultTypeClass = getClassType(resultType);
Class> resultTypeClass = mappedStatement.getResultType();
ArrayList objects = new ArrayList<>();
// 6. 封装返回结果集
while (resultSet.next()) {
Object o = resultTypeClass.newInstance();
//元数据
ResultSetMetaData metaData = resultSet.getMetaData();
for (int i = 1; i <= metaData.getColumnCount(); i++) {
// 字段名
String columnName = metaData.getColumnName(i);
// 字段的值
Object value = resultSet.getObject(columnName);
//使用反射或者内省,根据数据库表和实体的对应关系,完成封装
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass);
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(o, value);
}
objects.add(o);
}
return (List) objects;
}
private Class> getClassType(String paramterType) throws ClassNotFoundException {
if (paramterType != null) {
Class> aClass = Class.forName(paramterType);
return aClass;
}
return null;
}
/**
* 完成对#{}的解析工作:1.将#{}使用?进行代替,2.解析出#{}里面的值进行存储
*
* @param sql
* @return
*/
private BoundSql getBoundSql(String sql) {
//标记处理类:配置标记解析器来完成对占位符的解析处理工作,主要是配合通⽤标记解析器GenericTokenParser类完成对配置⽂件等的解析⼯作,其中TokenHandler主要完成处理
ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
//GenericTokenParser :通⽤的标记解析器,完成了代码⽚段中的占位符的解析,然后再根据给定的标记处理器(TokenHandler)来进⾏表达式的处理
//三个参数:分别为openToken (开始标记)、closeToken (结束标记)、handler (标记处理器)
GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
//解析出来的sql
String parseSql = genericTokenParser.parse(sql);
//#{}里面解析出来的参数名称
List parameterMappings = parameterMappingTokenHandler.getParameterMappings();
BoundSql boundSql = new BoundSql(parseSql, parameterMappings);
return boundSql;
}
}
使用端
创建 sqlMapConfig.xml
创建对应的mapper.xml
UserDao
public interface IUserDao {
//查询所有用户
public List findAll() throws Exception;
//根据条件进行用户查询
public User findByCondition(User user) throws Exception;
}
User实体
@Data
public class User {
private Long id;
private String username;
private String password;
}
框架查询验证
@Test
public void test() throws Exception {
InputStream resourceAsSteam = Resources.getResourceAsSteam("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsSteam);
SqlSession sqlSession = sqlSessionFactory.openSession();
//调用
User user = new User();
user.setId(1);
user.setUsername("张三");
User user2 = sqlSession.selectOne("user.selectOne", user);
System.out.println(user2);
List users = sqlSession.selectList("user.selectList");
for (User user1 : users) {
System.out.println(user1);
}
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~