1.說說Mybatis的緩存機制:
MyBatis 是一個優秀的持久層框架,它簡化了企業應用開發中數據庫操作的代碼。MyBatis 提供了一級緩存和二級緩存機制來優化對數據庫的訪問。
一級緩存 (SqlSession級別的緩存)
一級緩存是 MyBatis 中默認開啟且無法關閉的緩存機制。它存在于 SqlSession 的生命周期內,當同一個 SqlSession 實例執行相同的查詢語句時,MyBatis 會首先檢查一級緩存中是否已經有結果存在。如果有,則直接返回緩存中的數據,不再發起數據庫查詢;如果沒有,則查詢數據庫并將結果存入緩存中。
一級緩存的生命周期與 SqlSession 綁定,因此在以下情況下,一級緩存會被清空:
- 提交或回滾事務后;
- 執行任何更新、插入或刪除操作后;
- 手動調用 clearCache() 方法;
- 當 SqlSession 關閉時。
二級緩存 (Mapper級別的緩存)
二級緩存可以跨多個 SqlSession 使用,并且可以在不同的 SqlSession 之間共享。它通常應用于多個用戶可能會查詢相同的數據的情況。要啟用二級緩存,需要做如下配置:
-
在核心配置文件(如 mybatis-config.xml)中設置 來全局開啟二級緩存。
-
在具體的 Mapper XML 文件中添加 或者更復雜的 配置來為特定的命名空間開啟緩存。
使用二級緩存需要注意的問題包括但不限于:
- 確保實體類是可序列化的,因為緩存對象可能被序列化到磁盤或者分布式緩存系統中。
- 不能對頻繁更新的數據使用二級緩存,否則會導致臟讀問題。
- 注意并發情況下的緩存一致性問題。
自定義緩存
MyBatis 還允許開發者通過實現自己的緩存接口來自定義緩存策略。你可以通過繼承 Cache 接口創建自定義緩存,并將其集成到 MyBatis 的緩存架構中。
總的來說,合理地利用 MyBatis 的緩存機制可以顯著提高應用程序的性能,但同時也需要考慮到緩存帶來的潛在問題,如數據的一致性和時效性等。
2.JDBC 編程有哪些步驟?
JDBC(Java Database Connectivity)編程是Java應用程序連接和操作數據庫的標準方法。以下是使用JDBC進行編程的基本步驟:
-
加載JDBC驅動:
- 早期的JDBC版本需要顯式地使用 Class.forName() 方法來加載特定數據庫的JDBC驅動程序類。
- 從JDBC 4.0開始,只要JDBC驅動在類路徑中,DriverManager 將自動加載它,因此不再需要顯式調用 Class.forName()。
-
獲取數據庫連接:
- 使用 DriverManager.getConnection() 方法提供數據庫URL、用戶名和密碼來建立與數據庫的連接。
- 或者使用 DataSource 接口提供的方法來獲取連接,這通常用于企業級應用中,因為 DataSource 支持連接池等高級特性。
-
創建Statement對象:
- 使用 Connection.createStatement() 創建一個 Statement 對象用于執行SQL語句。
- 或者使用 Connection.prepareStatement() 來創建一個預編譯的 PreparedStatement 對象,以提高性能并防止SQL注入攻擊。
- 如果需要調用存儲過程,則可以使用 Connection.prepareCall() 創建 CallableStatement 對象。
-
執行SQL語句:
- 對于查詢操作,使用 Statement.executeQuery() 執行SQL SELECT語句,并返回一個 ResultSet 對象。
- 對于更新操作(如INSERT, UPDATE, DELETE),使用 Statement.executeUpdate() 執行這些語句,該方法返回受影響的行數。
-
處理結果集(僅適用于查詢):
- 使用 ResultSet 的各種 getXXX() 方法來遍歷結果集并提取數據。
- 注意要正確處理 ResultSet 中的數據類型轉換。
-
清理資源:
- 關閉 ResultSet, Statement 和 Connection 等資源非常重要。未關閉的資源可能會導致內存泄漏或數據庫連接耗盡。
- 最好是在finally塊中或者使用try-with-resources語句(Java 7及以上)來確保即使發生異常也能正確關閉資源。
示例代碼片段如下:
try (Connection conn = DriverManager.getConnection(dbUrl, user, password);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT id, name FROM users")) {while (rs.next()) {// Process each row of the result set.int id = rs.getInt("id");String name = rs.getString("name");System.out.println("ID: " + id + ", Name: " + name);}
} catch (SQLException e) {e.printStackTrace();
}
這段代碼展示了如何使用 try-with-resources 自動管理資源關閉,并且執行了一個簡單的查詢操作。
3. MyBatis 中見過什么設計模式?
MyBatis 框架中使用了多種設計模式,以提高代碼的可維護性、可擴展性和靈活性。以下是 MyBatis 中常見的一些設計模式:
1. 工廠模式 (Factory Pattern)
MyBatis 使用工廠模式來創建 SqlSessionFactory。SqlSessionFactoryBuilder 根據配置信息(XML 或 Java 配置)構建 SqlSessionFactory 實例。SqlSessionFactory 負責創建 SqlSession 對象,而 SqlSession 是執行數據庫操作的主要入口。
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {// Use the session to execute SQL statements.
}
2. 代理模式 (Proxy Pattern)
MyBatis 利用 JDK 動態代理或 CGLIB 創建 Mapper 接口的代理實例。這些代理對象攔截方法調用,并將它們轉換為對底層 JDBC API 的調用,從而隱藏了數據訪問層的實現細節。
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectAllUsers();
3. 建造者模式 (Builder Pattern)
SqlSessionFactory 的創建過程通過 SqlSessionFactoryBuilder 來完成,它根據不同的配置選項逐步構建出最終的對象。建造者模式使得可以靈活地創建復雜的對象而不必使用大量的構造函數參數。
4. 模板方法模式 (Template Method Pattern)
在 MyBatis 內部,對于 CRUD 操作的流程有一個大致固定的步驟:創建連接 -> 創建語句 -> 執行語句 -> 處理結果 -> 關閉資源。這個流程由框架提供,用戶只需要定義具體的 SQL 和映射規則,這正是模板方法模式的應用。
5. 單例模式 (Singleton Pattern)
SqlSessionFactory 通常在整個應用程序生命周期內只被創建一次,并且可以被多個線程安全地共享和重用。因此,它通常被設計成單例模式。
6. 適配器模式 (Adapter Pattern)
MyBatis 的類型處理器(TypeHandler)用于在 JDBC 類型和 Java 類型之間進行轉換,起到了適配器的作用,使得不同類型的對象能夠兼容工作。
7. 策略模式 (Strategy Pattern)
當涉及到查詢緩存時,MyBatis 允許用戶選擇不同的緩存實現(如一級緩存、二級緩存等),并且可以通過插件機制添加自定義的緩存策略,這體現了策略模式的思想。
這些設計模式共同作用,使得 MyBatis 成為了一個高效、靈活且易于使用的持久層框架。
4.MyBatis 中比如 UserMapper.java 是接口,為什么沒有實現類還能調用?
在 MyBatis 中,UserMapper.java 是一個接口,而不需要提供實現類的原因是因為 MyBatis 使用了 動態代理 的機制。具體來說,MyBatis 利用 Java 的反射和動態代理功能(如 JDK 動態代理或 CGLIB)來為這些接口創建代理實例。當你調用 session.getMapper(UserMapper.class) 時,MyBatis 會根據你提供的 Mapper 接口生成一個代理對象。
這個代理對象能夠攔截你對 Mapper 接口中定義的方法的調用,并將它們轉換成相應的 SQL 操作。例如,如果你有一個方法 List<User> selectAllUsers();,那么 MyBatis 會查找與之對應的 XML 映射文件中的 <select> 標簽或者注解配置,并執行該標簽內定義的 SQL 語句,然后將結果集映射到返回的對象中。
下面是 MyBatis 如何做到這一點的大致流程:
- 配置映射信息:你需要通過 XML 文件(如 UserMapper.xml)或者注解的方式為接口中的每個方法指定相應的 SQL 語句。
- 獲取 Mapper 實例:使用 SqlSession 提供的 getMapper(Class type) 方法傳入你的 Mapper 接口類型,MyBatis 會為你創建一個代理實例。
- 代理方法調用:當你調用代理實例上的方法時,實際是觸發了 MyBatis 內部邏輯去解析并執行對應的 SQL 語句。
- 執行 SQL 和處理結果:MyBatis 使用底層的 JDBC 連接執行 SQL 語句,并將結果集映射到 Java 對象,最后返回給調用者。
由于這一切都是在運行時由 MyBatis 自動完成的,所以開發者無需編寫具體的實現類。這種方式不僅簡化了代碼,還提高了靈活性,因為你可以輕松地更改 SQL 語句而不必修改業務邏輯代碼。此外,它也遵循了面向接口編程的最佳實踐,有助于提高代碼的可測試性和可維護性。