zoukankan      html  css  js  c++  java
  • 简单自定义mybatis流程!!

    ----简单自定义mybatis流程----
    一.首先封装daoMapperxml文件和sqlMapconfig配置文件,如何封装:
    (1).封装我们的Mapper.xml文件,提取名称空间namespace,提取方法名id,提取我们的结果类型resultType,再提取我们的sql语句sqlStatement创建实例对象封装.
    (2).封装我们的sqlMapconfig.xml操作数据库的配置文件,提取数据源datasource(c3p0,德鲁伊...),再提取连接数据库四个步骤:driver驱动,地址URL,用户名username和密码password,还有最后一个接口映射文件信息,由于实际开发中会有多个,所以可以使用一个Map集合来定义Map<String,Mapper>datasource,接着创建实例封装.
    二.解析xml文件,这里使用dom4j解析,然后创建我们的数据源对象:
    (1).解析sqlMapconfig.xml文件
    //这边使用无参构造方法来解析xml文件和加载数据源datasource!
    public Configuration(){
    loadXpathSqlMapConfig();
    creatDatasource();


    }

    /**
    * 解析数据库配置文件
    */
    public void loadXpathSqlMapConfig(){
    try {
    //通过类加载器加载配置文件
    InputStream resource = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
    //采用dom4j解析xml配置文件
    SAXReader saxReader = new SAXReader();
    Document read = saxReader.read(resource);
    Element rootElement = read.getRootElement();
    //System.out.println(rootElement);
    List<Element> nodesList = rootElement.selectNodes("//property");//语法要求要加"//"
    for (Element element : nodesList) {
    String name = element.attributeValue("name");
    String value = element.attributeValue("value");
    if ("driver".equals(name)){
    driver=value;
    }
    if ("url".equals(name)){
    url=value;
    }
    if ("username".equals(name)){
    username=value;
    }
    if ("password".equals(name)){
    password=value;
    }
    }
    List<Element> list = rootElement.selectNodes("//mapper");
    for (Element element : list) {
    String xpath = element.attributeValue("resource");
    loadMapperXml(xpath);

    } catch (Exception e) {
    e.printStackTrace();
    }


    }

    /**
    * 创建数据源对象设置连接数据库参数
    *
    */
    public void creatDatasource(){

    try {
    //创建数据源对象
    dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass(driver);
    dataSource.setJdbcUrl(url);
    dataSource.setUser(username);
    dataSource.setPassword(password);

    } catch (Exception e) {
    e.printStackTrace();
    }

    }
    (2).解析interfaceMapperXml文件.封装到我们的Mapper中!
    /**
    * 解析interfaceMapperXml文件
    * @param xpath
    */
    public void loadMapperXml(String xpath) {
    mappers = new HashMap<>();
    try {
    InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(xpath);
    SAXReader saxReader = new SAXReader();
    Document document = saxReader.read(inputStream);
    Element rootElement = document.getRootElement();
    String namespace = rootElement.attributeValue("namespace");
    List<Element> elements = rootElement.elements();
    Mapper mapper = new Mapper();
    for (Element element : elements) {
    String id = element.attributeValue("id");
    String resultType = element.attributeValue("resultType");
    String sqlStatement = element.getText();
    mapper.setId(id);
    mapper.setNamespace(namespace);
    mapper.setResultType(resultType);
    mapper.setSqlStatement(sqlStatement);
    String key=namespace+"."+id;
    mappers.put(key,mapper);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    三.创建核心对象SqlSession对象,旧版Mybatis前常用SqlSession对象中的增删查改方法,现在新版Myatis常用getMapper方法,面向接口的编程方式,需要接口名与mapper的命名空间属性值保持一致,从而将接口与mapper文件对应起来。当namespace绑定某一接口之后,可以不用写该接口的实现类,MyBatis会通过接口的完整限定名查找到对应的mapper配置来执行SQL语句.里边使用了动态代理技术.
    public class SqlSession {


    public <T> T getMapper(Class<T> type){
    T proxy= (T) Proxy.newProxyInstance(
    this.getClass().getClassLoader(),
    new Class[]{type},
    new MapperProxy()

    );

    return proxy;
    }
    }

    public class MapperProxy implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //加载映射文件和配置文件
    Configuration configuration = new Configuration();
    //数据源
    ComboPooledDataSource dataSource = configuration.getDataSource();
    //执行的sql语句
    Map<String, Mapper> mappers = configuration.getMappers();
    String methodName = method.getName();
    String className = method.getDeclaringClass().getName();

    String key=className+"."+methodName;
    System.out.println(key);
    Mapper mapper = mappers.get(key);

    return Executor.findAll(mapper,dataSource.getConnection());
    }
    }
    四.创建我们的SqlSessionFactory会话工厂对象,通过里面的openSession()方法打开(得到)我们的核心Sqlsession会话对象;
    * @Description: 会话工厂对象对象,此对象提供一个openSession()方法
    */
    public class SqlSessionFactory {


    public static SqlSession openSession(){
    return new SqlSession();
    }
    }
    五.创建Executor工具类 执行数据库操作并且封装结果集返回:
    public class Executor {


    public static <T> List<T> findAll(Mapper mapper, Connection connection){

    List<T> resultList =new ArrayList<T>();
    PreparedStatement preparedStatement=null;
    ResultSet resultSet=null;
    try {
    //获取到sql语句
    String sqlStatement = mapper.getSqlStatement();
    //获取返回值类型
    String resultType = mapper.getResultType();
    //转成字节码对象
    Class<?> aClass = Class.forName(resultType);
    preparedStatement = connection.prepareStatement(sqlStatement);
    //执行完返回resultSet 封装结果集
    resultSet = preparedStatement.executeQuery();
    handleResult(resultList,aClass,resultSet);
    } catch (Exception e) {
    e.printStackTrace();
    }finally {
    close(connection,preparedStatement,resultSet);
    }


    return resultList;

    }

    /**
    * 处理结果集方法
    * @param resultList
    * @param aClass
    * @param resultSet
    */
    private static void handleResult(List resultList, Class<?> aClass, ResultSet resultSet) {
    try {
    //首先获取到元数据
    ResultSetMetaData metaData = resultSet.getMetaData();
    //获取元数据字段数量
    int columnCount = metaData.getColumnCount();

    //获取字段名称,因为多个,所以使用数组保存
    String[] columnNames= new String[columnCount];
    for (int i = 1; i <= columnNames.length; i++) {
    columnNames[i-1]= metaData.getColumnName(i);
    }
    //循环取数据
    while (resultSet.next()){
    //通过反射技术给成员变量赋值
    Object o = aClass.newInstance();//这个对象表示是User对象
    //便利字段名称数组
    for (int i = 0; i < columnNames.length; i++) {
    //resultSet.getObject():获取此的当前行中指定列的值
    Object object = resultSet.getObject(columnNames[i]);

    Field field = aClass.getDeclaredField(columnNames[i]);
    field.setAccessible(true);
    field.set(o,object);
    }
    resultList.add(o) ;
    }

    } catch (Exception e) {
    e.printStackTrace();
    }

    }

    /**
    * 释放资源
    * @param connection
    * @param preparedStatement
    * @param resultSet
    */
    private static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
    try {
    if (connection!=null) connection.close();
    if (preparedStatement!=null) preparedStatement.close();
    if (resultSet!=null) resultSet.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    }

    六.测试:
    public class MybatisTest {

    public static void main(String[] args) {

    //测试
    SqlSession sqlSession = SqlSessionFactory.openSession();
    UserDao mapper = sqlSession.getMapper(UserDao.class);
    List<User> userList = mapper.findAll();
    for (User user : userList) {
    System.out.println(user);
    }
    }
    }
    输出测试数据如下:

     

  • 相关阅读:
    【前端进阶】VUE高性能组件引用
    「前端进阶」高性能渲染十万条数据(虚拟列表) (自己修改版本)
    页面缓存、离线存储技术localforage(案例篇)
    页面缓存、离线存储技术localforage(介绍篇)
    websocket快速搭建(node+websocket)
    一款程序员的杀手级应用:TabNine代码补全工具
    如何把es6的代码转成es5,ECMAScript 2015+代码转换神器——Babel
    如何使用echarts画一个简单k线图
    深入浅出理解 . 深拷贝 . 浅拷贝
    JS高级一看就懂什么是原型链
  • 原文地址:https://www.cnblogs.com/flzidea/p/10857486.html
Copyright © 2011-2022 走看看