1. 程式人生 > 其它 >2.第一個mybatis

2.第一個mybatis

1.導包:此處建立的只是簡單的maven專案,沒有建立springboot專案
    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!--重點:匯入mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--引入採控平臺:postgresql的包-->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.19</version>
        </dependency>
    </dependencies>

2.編寫mybatis的工具類
    public class MybatisTools {
        //1:通過xml檔案建立SqlSessionFactory
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //2:獲取SqlSession
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    解說:
       1.每個基於 MyBatis 的應用都是以一個 SqlSessionFactory 的例項為核心的。
       2.SqlSessionFactory 的例項可以通過 SqlSessionFactoryBuilder 獲得。
       3.而 SqlSessionFactoryBuilder 則可以從 XML 配置檔案或一個預先配置的 Configuration 例項來構建出 SqlSessionFactory 例項。
       4.從SqlSessionFactory獲得 SqlSession 的例項。SqlSession 提供了在資料庫執行 SQL 命令所需的所有方法
       
3.編寫一個介面:
    public interface UserDao {
        List<User> getUserList();
    }
4.編寫一個UserMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    //重點1:namespace是對映的介面類名
    <mapper namespace="cn.com.wmd.dao.UserDao">
        //重點2:id是介面中的方法名稱 resultType:返回值的型別,如果是集合,則是泛型的型別
        <select id="getUserList" resultType="cn.com.wmd.pojo.User">
            select * from public.user
        </select>
    </mapper>
5.實體類程式碼:
    public class User {
        private int id;
        private String name;
        private String pwd;
        ...
    }

6.mybatis的配置檔案內容:mybatis-config.xml
    <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">
        <!--mybatis的資料庫配置-->
        <configuration>
            <!--可以同時配置多個數據源,一個數據源等於一個environment-->
            <environments default="development">
                <environment id="development">
                    <!--事務-->
                    <transactionManager type="JDBC"/>
                    <dataSource type="POOLED">
                        <property name="driver" value="org.postgresql.Driver"/>
                        <property name="url" value="jdbc:postgresql://133.64.181.208:18921/wmd_test"/>
                        <property name="username" value="root"/>
                        <property name="password" value="Ustcinfo@2020"/>
                    </dataSource>
                </environment>
            </environments>
            //重點2:將新增的mapper載入到mybatis的配置檔案中
            <mappers>
                <mapper resource= "cn/com/wmd/mapper/UserMapper.xml"/>
            </mappers>
        </configuration>

7.測試類程式碼:
        @org.junit.Test
        public void test() {
            //重點1:根據自定義的工具類獲取SqlSession 物件
            SqlSession sqlSession = MybatisTools.getSqlSession();
            //重點2:呼叫sqlSession.getMapper方法,獲取UserDao物件,UserDao和UserMapper.xml繫結,UserMapper中有對應執行的sql
            UserDao userDao = (UserDao)sqlSession.getMapper(UserDao.class);
            //重點3:執行sql
            List<User> userList = userDao.getUserList();
            Iterator var4 = userList.iterator();
        
            while(var4.hasNext()) {
                User user = (User)var4.next();
                System.out.println(user);
            }
            //重點4:關閉流
            sqlSession.close();
        }
結論:可以正常輸出
主要的邏輯圖: 碰到的問題:
問題描述:出現了mapper.xml找不到的問題
    Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. 
    Cause: java.io.IOException: Could not find resource cn/com/wmd/dao/UserMapper.xml

問題排查:出了路徑寫錯的情況,還有一種情況:
    maven打包時,預設不會將src/main/java中的配置檔案(.properties或.xml檔案打包到target目錄下)
    而jdk執行的是編譯後的class檔案,即target目錄下的class檔案,如果target下沒有對應的mapper.xml檔案,就會報上述錯誤

解決辦法:在pom檔案中規定打包時將對應的配置檔案也打包
    <build>
        <resources>
            <resource>
                <!--將resource下的配置檔案打包-->
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <!--將src/main/java下的配置檔案打包-->
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <!--重點:此處必須時false-->
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
問題描述圖: 更改了pom檔案後:
1.SqlSessionFactoryBuilder
這個類可以被例項化、使用和丟棄,一旦建立了 SqlSessionFactory,就不再需要它了。
因此 SqlSessionFactoryBuilder 例項的最佳作用域是方法作用域(也就是區域性方法變數)。
 你可以重用 SqlSessionFactoryBuilder 來建立多個 SqlSessionFactory 例項,但最好還是不要一直保留著它,以保證所有的 XML 解析資源可以被釋放給更重要的事情。


2.SqlSessionFactory
SqlSessionFactory 一旦被建立就應該在應用的執行期間一直存在,沒有任何理由丟棄它或重新建立另一個例項。
 使用 SqlSessionFactory 的最佳實踐是在應用執行期間不要重複建立多次,多次重建 SqlSessionFactory 被視為一種程式碼“壞習慣”。
 因此 SqlSessionFactory 的最佳作用域是應用作用域。 有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式。


3.SqlSession
每個執行緒都應該有它自己的 SqlSession 例項。SqlSession 的例項不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。 
絕對不能將 SqlSession 例項的引用放在一個類的靜態域,甚至一個類的例項變數也不行。 
也絕不能將 SqlSession 例項的引用放在任何型別的託管作用域中,比如 Servlet 框架中的 HttpSession。 
如果你現在正在使用一種 Web 框架,考慮將 SqlSession 放在一個和 HTTP 請求相似的作用域中。 
換句話說,每次收到 HTTP 請求,就可以開啟一個 SqlSession,返回一個響應後,就關閉它。 這個關閉操作很重要,為了確保每次都能執行關閉操作,你應該把這個關閉操作放到 finally 塊中。
 下面的示例就是一個確保 SqlSession 關閉的標準模式:
try (SqlSession session = sqlSessionFactory.openSession()) {
  // 你的應用邏輯程式碼
}
在所有程式碼中都遵循這種使用模式,可以保證所有資料庫資源都能被正確地關閉。