zoukankan      html  css  js  c++  java
  • mybatis入门案例分析

    mybatis入门案例分析

    一、设计模式分析
    public class MybatisTest {
        public static void main(String[] args) throws Exception{
            //1.读取配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
            //3.使用工厂生产SqlSession对象
            SqlSession session = factory.openSession();
            //4.使用SqlSession创建Dao的代理对象
            IUserDao userDao = session.getMapper(IUserDao.class);
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for(User user : users) {
                System.out.println(user);
            }
            //6.释放资源
            session.close();
            in.close();
    
        }
    }
    
    1.读取配置文件

    在读取文件时,通常有两种方法,一种是采用绝对路径,另一种是采用相对路径。如果采用绝对路径,其缺点为不易迁移和部署,在开发时如果我们路径为“D:SqlMapConfig.xml”,部署到服务器时,可能服务器上没有D盘。相对路径的缺点就在于,如果项目为Web工程,部署之后src目录就不存在了。因此在读取配置文件时,只有两种方法:

    1.使用类加载器:只能读取类路径的配置文件。

    2.使用SeverletContext对象的getPath()方法。

    2.创建工厂

    在创建工厂时,mybatis使用了构建者模式,builder就是构建者,把对象的创建细节隐藏,使用户直接调用方法便可获得对象。

    3.生产SqlSession对象

    生产SqlSession对象时使用了工厂模式,可以降低类间的依赖关系,便于之后对项目进行修改。

    4.创建代理对象

    创建DAO接口实现类的代理对象实现了使用了代理模式,这样就不需要自己写DAO实现类。

    二、mybatis执行查询所有的分析
    1.普通的java实现数据库查询

    1.注册驱动,获取connection对象

    2.创建数据库的执行sql的预处理对象

    3.执行sql语句

    4.封装查询结果

    5.释放资源

    public class JDBCTest {
        public static void main(String[] args) {
            JDBCTest test=new JDBCTest();
            test.firstJDBC();
        }
    
        public void firstJDBC(){
            Connection connection=null;
            PrepareStatement prepareStatement=null;
            ResultSet resultSet=null;
    
            try {
                //1.register,注册驱动
                DriverManager.registerDriver(new Driver());
                //2.得到数据连接。url格式:jdbc:mysql://主机IP:端口号/数据库名?user=用户名&password=密码
                //因为MySQL安装时,端口号默认设置的是3306,所以都是3306
                String url="jdbc:mysql://localhost:3306/sport?user=root&password=12345678";
                connection=DriverManager.getConnection(url);
              
                //3.得到数据库的执行sql对象
             		String sql="select * from player"; //SQL查询语句
                prepareStatement=connection.prepareStatement();
                //4.执行语句  
                resultSet=prepareStatement.executeQuery();
                while(resultSet.next()){
                    //取出查询的信息
                    String name=resultSet.getString("player_name");
                    int age=resultSet.getInt("player_age");
                    int score=resultSet.getInt("player_score");
                    System.out.println("name="+name+",age="+age+",score="+score);
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally {
                //5.关闭资源
                if(connection!=null){
                    try {
                        connection.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(prepareStatement!=null){
                    try {
                        prepareStatement.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(resultSet!=null){
                    try {
                        resultSet.close();
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
    
    }
    
    2.mybatis中如何实现查询
    <!-- mybatis的主配置文件 -->
    <configuration>
        <!-- 配置环境 -->
        <environments default="mysql">
            <!-- 配置mysql的环境 -->
            <environment id="mysql">
                <!-- 配置事务的类型 -->
                <transactionManager type="JDBC"></transactionManager>
                <!-- 配置数据源(连接池) -->
                <dataSource type="POOLED">
                    <!-- 配置连接数据库的四个基本信息 -->
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                    <property name="username" value="root"/>
                    <property name="password" value="12345678"/>
                </dataSource>
            </environment>
        </environments>
    
        <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
        <mappers>
            <mapper resource="dao/IUserDao.xml" />
        </mappers>
    </configuration>
    

    1.创建connection对象。通过主被配置文件SqlMapConfig.xml,我们可以获得连接数据库的信息(驱动、路径、用户名和密码)以及映射配置文件的位置。通过连接数据库的信息,我们可以构建connection对象。

    <mapper namespace="dao.IUserDao">
        <!-- 配置查询所有 -->
        <select id="findAll" resultType="domain.User">
            select * from user;
        </select>
    </mapper>
    

    2.创建prepareStatement对象。通过映射配置文件的信息,我们可以获得执行的SQL语句和封装的实体类全限定类名,就可以创建prepareStatement对象。mybatis通过dom4j技术来解析xml文件获取上述信息。

    3.存储解析结果。在获取相关信息中后,mybatis需要将执行的SQL语句和封装结果的实体类全限定类名组合起来定义成一个Mapper对象,每一个Mapper对象对应一个完整String类型的id(namespace+“.”+id)。例如本项目中的SQL语句为“select * from user;”,封装结果的实体类全限定类名为“domain.user”,完整的id为"dao.IUserDao.findAll",这些都是String类型的字段。

    4.利用反射技术封装。创建prePareStatement对象之后,通过resultSet = prepareStatement.executeQuery();语句我们可以获得查询结果集,在对查询结果集进行封装时。我们通过完整的id(即封装结果的全限定类名),利用反射技术(Class.forName("domain.User").getDeclaredConstructor().newInstance();)即可进行封装。由于实体类的属性和数据库表中的列名一致,可以把表的列名当作是实体类的属性名称,然后利用反射技术来根据名称获取每个属性,并把值赋进去。反射参考链接

    三、创建代理对象的分析
    //MybatisTest.class
    IUserDao userDao = session.getMapper(IUserDao.class);
    
    //DefaultSqlSession.class
    public <T> T getMapper(Class<T> type) {
    		return this.configuration.getMapper(type, this);
    }
    
    //Configuration.class
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        return this.mapperRegistry.getMapper(type, sqlSession);
    }
    
    //MapperRegistry.class
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
         MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
         if (mapperProxyFactory == null) {
                throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
         } else {
                try {
                    return mapperProxyFactory.newInstance(sqlSession);
                } catch (Exception var5) {
                    throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
                }
         }
    }
    
    //MapperProxyFactory.class
    public T newInstance(SqlSession sqlSession) {
            MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
            return this.newInstance(mapperProxy);
    }
    
    protected T newInstance(MapperProxy<T> mapperProxy) {
            return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
    }
    
    //Proxy.class
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
                                              InvocationHandler h) {
            Objects.requireNonNull(h);
    
            final Class<?> caller = System.getSecurityManager() == null
                                        ? null
                                        : Reflection.getCallerClass();
    
            /*
             * Look up or generate the designated proxy class and its constructor.
             */
            Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
    
            return newProxyInstance(caller, cons, h);
    }
    

    上述是MybatisTest类中,getMapper()的调用层级。可以看到最终调用的方法是public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h),这个方法有三个参数,分别是:

    1.类加载器loader:使用和被代理对象相同的类加载器

    2.代理对象要实现的接口字节码数组interfaces:和被代理对象实现的是相同的接口

    3.代理方式h:就是增强的方法,实际上就是一个InvocationHandler接口的实现类,在实现类中调用selectList方法(查询所有方法)。

    mybatis入门案例,可以参考我的上一篇博客:mybatis入门实例

  • 相关阅读:
    第4次作业得分-东师软工
    第3次作业得分-东师软工
    C语言-第3次作业得分
    NPM
    Node模块化
    spring源码解析前瞻
    单例DCL模式
    dubbo-admin安装
    linux 安装Zookeeper
    Tomcat在Linux上的安装与配置
  • 原文地址:https://www.cnblogs.com/liyier/p/12264180.html
Copyright © 2011-2022 走看看