zoukankan      html  css  js  c++  java
  • 自定义Mybatis框架

    使用:

    idea

    apache-maven-3.3.9

    jdk1.8.0_162

    数据库mybatis1

    数据表:user

    CREATE TABLE `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) DEFAULT NULL,
    `age` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;

    创建maven工程并引入坐标:

    例如:创建mybatis_frame的maven工程,并引入依赖

      

    dom4j  jaxen  解析xml配置文件
     
    <dependencies>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
    </dependencies>

    自定义框架原理:

     项目结构

    1.编写配置文件:

             SqlMapConfig.xml

             UserMapper.xml

       SqlMapConfig.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver" />
                    <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis1" />
                    <property name="username" value="root" />
                    <property name="password" value="root" />
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="com/review/mapper/UserMapper.xml"></mapper>
        </mappers>
    </configuration> 
    UserMapper.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <mapper namespace="com.review.mapper.UserMapper">
        <select id="findAll" resultType="com.review.pojo.User">
            select * from user
        </select>
    </mapper>

    2 编写配置文件对应的实体类:

             Confinguration

    public class Configuration {
        private String driverClass;
        private String url;
        private String username;
        private String password;
        private Map<String, Mapper> mappers = new HashMap<>();
    
        public String getDriverClass() {
            return driverClass;
        }
    
        public void setDriverClass(String driverClass) {
            this.driverClass = driverClass;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public Map<String, Mapper> getMappers() {
            return mappers;
        }
    
        public void setMappers(Map<String, Mapper> mappers) {
            this.mappers = mappers;
        }
    }
             Mapper


    public class Mapper {
        private String sql;//sql语句
    
        public String getSql() {
            return sql;
        }
    
        public void setSql(String sql) {
            this.sql = sql;
        }
    
        public String getResultType() {
            return resultType;
        }
    
        public void setResultType(String resultType) {
            this.resultType = resultType;
        }
    
        private String resultType;//返回值类型
    
    }


    3编写SqlSession接口及实现类SqlSessionImpl,Executor执行器

             SqlSession接口:对数据库进行操作的方法

             SqlSessionImpl类:对接口中的方法进行重写,在构造中创建executor对象,并对configuration赋值

             Executor: 用于实现 SQL 语句的执行,主要是调用 JDBC 来实现 SQL 语句的执行

    SqlSession 接口:
    public interface SqlSession {
        //执行
        public <T> List<T> selectList(String mapperId);
        //关闭资源
        public void close();
    }

    SqlSessionImpl类:
    public class SqlSessionImpl implements SqlSession {
        private Configuration cfg;
        private Executor executor;
    
    
        public SqlSessionImpl(Configuration configuration) {
            this.cfg = configuration;
            this.executor = new Executor(cfg);
        }
    
    
        public <T> List<T> selectList(String mapperId) {
            Mapper mapper = cfg.getMappers().get(mapperId);
            String sql = mapper.getSql();
            String returnType = mapper.getResultType();
            return executor.executorQuery(sql, returnType);
        }
        public void close() {
    
            executor.release();
        }
    }

     Executor类:用于实现 SQL 语句的执行,主要是调用 JDBC 来实现 SQL 语句的执行
    public class Executor {
        private Configuration configuration;
    
        public Executor(Configuration configuration) {
            this.configuration = configuration;
        }
    
        private Connection conn = null;
        private PreparedStatement pst = null;
        private ResultSet rs = null;
    
        public <T> List<T> executorQuery(String sql, String returnType) {
    
            List<T> list = new ArrayList<T>();
            //连接数据库,执行sql语句
            try {
                //注册驱动
                Class.forName(configuration.getDriverClass());
                //获得链接
                conn = DriverManager.getConnection(configuration.getUrl(), configuration.getUsername(), configuration.getPassword());
                //获得执行者对象
                pst = conn.prepareStatement(sql);
                //获得结果集
                rs = pst.executeQuery();
    
                //获得元数据
                ResultSetMetaData metaData = rs.getMetaData();
                //字段数
                int columnCount = metaData.getColumnCount();
                //存放字段
                List<String> columnNames = new ArrayList<String>();
    
                //遍历字段数
                for (int i = 1; i <= columnCount; i++) {
                    //获得对应的字段名
                    String columnName = metaData.getColumnName(i);
                    //放入到list集合
                    columnNames.add(columnName);
    
                }
    
                //获得字节码文件
                Class obj = Class.forName(returnType);
                //解析结果集
                while (rs.next()) {
                    //创建对象 相当于 new User();
                    Object o = obj.newInstance();
    
                    //获得User实体类中的所有方法
                    Method[] methods = obj.getMethods();
                    for (Method method : methods) {
                        //遍历字段
                        for (String columnName : columnNames) {
                            if (method.getName().equalsIgnoreCase("set" + columnName)) {
                                try {
                                    method.invoke(o,rs.getObject(columnName));
                                } catch (InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                    //放到对象集合中
                    list.add((T) o);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }/*finally {
                relese();
            }*/
            return list;
    
        }
    
        public void release() {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
    
            }
            if (pst != null) {
                try {
                    pst.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
    
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
    
            }
    
        }
    }


    4 编写SqlSessionFactory:创建SqlSession对象

             构造方法中传入InputStream对象

             提供返回值SqlSession 的openSession方法

             加载配置文件

    public class SqlSessionFactory {
        private InputStream inputStream;
        //需要传入一个流对象
        public SqlSessionFactory(InputStream inputStream) {
            this.inputStream = inputStream;
        }
    
        //获取SqlSessiom 对象
        public SqlSession openSession() {
            Configuration configuration = new Configuration();
            loadConfiguration(configuration);
            return new SqlSessionImpl(configuration);
        }
    
        //读取配置文件
        private void loadConfiguration(Configuration cfg){
    
            SAXReader saxReader = new SAXReader();
            Document doc = null;
            Element rootElement = null;
            try {
                doc = saxReader.read(inputStream);
                rootElement = doc.getRootElement();
                List<Element> list = rootElement.selectNodes("//property");
                for (Element e : list) {
                    //e.attributeValue(name) :获取指定的属性名的属性值
                    //如果取出的name的属性值是driver,name就可以封装大搜Configuration中的driverClass属性中
                    if(e.attributeValue("name").equalsIgnoreCase("driver")){
                        cfg.setDriverClass(e.attributeValue("value"));
                    }
                    if(e.attributeValue("name").equalsIgnoreCase("url")){
                        cfg.setUrl(e.attributeValue("value"));
                    }
                    if(e.attributeValue("name").equalsIgnoreCase("username")){
                        cfg.setUsername(e.attributeValue("value"));
                    }
                    if(e.attributeValue("name").equalsIgnoreCase("password")){
                        cfg.setPassword(e.attributeValue("value"));
                    }
    
    
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            //加载另一个配置文件
    
            Element mappers = rootElement.element("mappers");
            List<Element> mapperList = mappers.elements();
            for (Element e : mapperList) {
                String mapperPath = e.attributeValue("resource");
                loadMapperConfiguration(mapperPath, cfg);
            }
    
        }
    
        private void loadMapperConfiguration(String mapperPath, Configuration cfg) {
            InputStream inputStream = SqlSessionFactory.class.getClassLoader().getResourceAsStream(mapperPath);
            SAXReader saxReader = new SAXReader();
            try {
                Document doc = saxReader.read(inputStream);
                Element rootElement = doc.getRootElement();
    
                Map<String, Mapper> mapperMap = cfg.getMappers();
    
                String key = null;
                String namespace = rootElement.attributeValue("namespace");
    
                //获取根节点下所有的子节点
                List<Element> elements = rootElement.elements();
                for (Element element : elements) {
                    String id = element.attributeValue("id");
                    //com.itheima.mapper.UserDao.findAll
                    key = namespace +"."+ id;
                    // value:存储Mapper对象,返回值类型和sql语句
                    Mapper mapper = new Mapper();
                    //获取返回值类型
                    String resultType = element.attributeValue("resultType");
                    mapper.setResultType(resultType);
                    //获取sql语句:getTextTrim{获取节点中的文本且去除两侧空白
                    String sql = element.getTextTrim();
                    mapper.setSql(sql);
                    mapperMap.put(key,mapper);
                }
    
    
    
            } catch (DocumentException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    View Code


    5 编写SqlSessionFactoryBuilder

             三个重载的builder方法:无参,String path,InputStream is;

    public class SqlSessionFactoryBuilder {
    
        public SqlSessionFactory builder(InputStream inputStream){
            return  new SqlSessionFactory(inputStream);
        }
    
        public SqlSessionFactory builder(String path){
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(path);
            return  new SqlSessionFactory(inputStream);
        }
    
    
        public SqlSessionFactory builder(){
            String path = "SqlMapConfig.xml";
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(path);
            return  new SqlSessionFactory(inputStream);
        }
    }

    把自定义的mybatis打成jar:install

    测试自定义框架:
    创建maven测试工程:
    引入依赖:
      打成jar文件的自定义框架
      mysql驱动
      junit测试
    <dependencies>
        <dependency>
            <groupId>com.review</groupId>
            <artifactId>mybatis_frame</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>



    引入配置文件:自定义mybatis一样,将resource中的文件复制一份

    创建User实体类:

    public class User {
        private Integer id;
        private String name;
        private int age;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    测试类:
    public class TestMybatis {
        SqlSessionFactory sessionFactory = null;
        @Before
        public void init(){
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
            sessionFactory = new SqlSessionFactoryBuilder().builder(inputStream);
        }
        @Test
        public void FindAll(){
            SqlSession sqlSession = sessionFactory.openSession();
            List<User> userList = sqlSession.selectList("com.review.mapper.UserMapper.findAll");
            for (User user : userList) {
                System.out.println(user.getName());
            }
            sqlSession.close();
    
        }
    }





  • 相关阅读:
    MySql 范式
    MySql 多表关系
    MySql 约束条件
    MySql 枚举和集合 详解
    【RoR win32】新建rails项目找不到script/server的解决办法
    【RoR win32】安装RoR
    【RoR win32】提高rails new时bundle install运行速度
    【bs4】安装beautifulsoup
    【py分析网页】可能有用的-re去除网页上的杂碎
    【pyQuery】抓取startup news首页
  • 原文地址:https://www.cnblogs.com/Cyan-W/p/9818136.html
Copyright © 2011-2022 走看看