mybatis入門案例分析

mybatis入門案例分析

1、設計模式分析
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目錄就不存在了。所以在讀取配置文件時,只有兩種方法:html

1.使用類加載器:只能讀取類路徑的配置文件。java

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

2.建立工廠

在建立工廠時,mybatis使用了構建者模式,builder就是構建者,把對象的建立細節隱藏,使用戶直接調用方法即可得到對象。sql

3.生產SqlSession對象

生產SqlSession對象時使用了工廠模式,能夠下降類間的依賴關係,便於以後對項目進行修改。數據庫

4.建立代理對象

建立DAO接口實現類的代理對象實現了使用了代理模式,這樣就不須要本身寫DAO實現類。設計模式

2、mybatis執行查詢全部的分析
1.普通的java實現數據庫查詢

1.註冊驅動,獲取connection對象數組

2.建立數據庫的執行sql的預處理對象服務器

3.執行sql語句session

4.封裝查詢結果mybatis

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();)便可進行封裝。因爲實體類的屬性和數據庫表中的列名一致,能夠把表的列名看成是實體類的屬性名稱,而後利用反射技術來根據名稱獲取每一個屬性,並把值賦進去。反射參考連接

3、建立代理對象的分析
//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入門實例

相關文章
相關標籤/搜索