作為一個java的學習者,我相信JDBC是大家最早接觸也是入門級別的資料庫連接方式,所以我們先來回憶一下JDBC作為一種用於執行SQL語句的Java API是如何工作的。下麵的一段代碼就是最基本的JDBC開發流程。 在上代碼之前要先導入JDBC的jar包,由於我用的資料庫是mysql,所以要先導 入 ...
作為一個java的學習者,我相信JDBC是大家最早接觸也是入門級別的資料庫連接方式,所以我們先來回憶一下JDBC作為一種用於執行SQL語句的Java API是如何工作的。下麵的一段代碼就是最基本的JDBC開發流程。
在上代碼之前要先導入JDBC的jar包,由於我用的資料庫是mysql,所以要先導
入如下的jar包
接下來的就是載入資料庫驅動,獲取資料庫鏈接之類的工作了,當然了這些工作都是通過代碼來完成的。為了和接下的mybatis配置文件對比,我在這裡採用的預處理的方式進行查詢,代碼如下:
public class Testjdbc { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 載入資料庫驅動 Class.forName("com.mysql.jdbc.Driver"); // 通過驅動管理類獲取資料庫鏈接 connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "123456"); // 定義sql語句 ?表示占位符 String sql = "select * from user where username = ?"; // 獲取預處理statement preparedStatement = (PreparedStatement) connection.prepareStatement(sql); // 設置參數,第一個參數為sql語句中參數的序號(從1開始),第二個參數為設置的參數值 preparedStatement.setString(1, "王五"); // 向資料庫發出sql執行查詢,查詢出結果集 resultSet = preparedStatement.executeQuery(); // 遍歷查詢結果集 while (resultSet.next()) { System.out.println(resultSet.getString("id") + " " + resultSet.getString("username")); } } catch (Exception e) { e.printStackTrace(); } finally { // 釋放資源 if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
然後用過JDBC的人也都知道它有這樣那樣的缺點,總結下來有以下幾點:
- 資料庫連接,使用時就創建,不使用時立即釋放,對資料庫進行頻繁連接開啟和關閉,造成資料庫資源浪費,影響資料庫性能。
解決方案:使用資料庫連接池管理資料庫
- 以上的JDBC代碼中明顯將sql語句硬編碼到java代碼中,如果sql語句修改,需要重新編譯java代碼,不利於系統的維護。
解決方法:將sql語句配置到xml配置文件中,這樣即使sql變化,也不需要對java代碼重新編譯
- 向preparedStatement中設置參數時,對占位符位置和設置參數值硬編碼在java代碼中,同樣不利於系統維護
解決方法:同樣可以將占位符和參數配置在xml文件中
- 從resultSet中遍歷結果集數據時,存在硬編碼
解決方法:將查詢的結果集自動映射為java對象
說完了JDBC,大家也都看到了JDBC的種種不便,於是Hibernate、Mybatis等等的對象關係映射框架便應運而生,而名義上雖說都是ORM框架,Hibernate和Mybatis在細枝末節上還是有很大不同的,但是本文是探討Mybatis框架。
首先Mybatis是什麼?
- mybatis是一個持久層的框架,是apache下的頂級項目(已托管在github上面)
- mybatis讓程式將主要精力放在sql上,通過mybatis提供的映射方式,自由靈活生成滿足需求的sql語句
- mybatis可以向preparedStatement中的輸入參數自動進行輸入映射,將查詢結果集靈活映射成java對象(輸出映射)。
Mybatis架構:
接下來用mybatis寫一個入門程式
首先講一下我們的需求,在我的資料庫里有一張用戶的表,表結構如下
我現在要做的是根據用戶的id(主鍵)查詢用戶信息
在開始擼代碼之前,先要搭好環境
eclipse本人採用的是java EE的版本,然後可以去https://github.com/mybatis/mybatis-3/releases該網站下載mybatis的jar包導入到工程裡面去
再然後就是就是上面已經提到了的mysql的驅動包
除了上面架構圖所提到的sqlMapConfig.xml配置文件外,還需要一個包來存映射文件(映射文件是什麼後面會提到),即sqlMap。
最後創建log4j.properties文件方便查看日誌
所以整個項目的架構如下
為方便查閱,這裡直接貼出整個項目代碼
首先是log4j.properties文件
# Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
然後是SqlMapconfig.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"> <configuration> <!-- 和spring整合後 environments配置將廢除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理 --> <transactionManager type="JDBC" /> <!-- 資料庫連接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> </configuration>
這串配置文件無非是配置事務管理和資料庫連接池,每個ORM框架都是必備的所以不深究
緊接著就是我們的重頭戲映射文件了
映射文件命名:
User.xml, 而在mapper代理開發映射文件名稱叫xxxMapper.xml, 比如:UserMapper.xml
而我們在映射文件里要乾的活就是配置sql語句,最直觀的對比就是hibernate直接在映射文件中將java對象映射為關係(即資料庫中的表),而在mybatis中細化了這種映射關係,具體了輸入映射和輸出映射
先把具體映射文件貼上來,然後一一解釋
<?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"> <mapper namespace="test"> <select id="findUserById" parameterType="int" resultType="com.mybatis.pojo.User"> select * from user where id=#{id}; </select> </mapper>
有一下幾點申明:
- namespace命名空間,作用是對sql進行分類化管理,理解為sql隔離
註意:使用mapper代理方法開發,namespace有特殊作用
- 通過select執行資料庫查詢, id標識映射文件中的sql,將sql語句封裝到mappedStatement對象中,所以將id稱之為statement的id
- #{}:表示一個占位符 #{id}: 其中的id表示接收輸入的參數,參數名稱就是id, 如果輸入參數是簡單類型,#{}中的參數名稱可以任意
- parameterType指的是輸入參數類型,在這裡輸入的是id當然是整型,parameterType指的是輸出結果所映射的java類型,由於sql語句查到的是一組數據,所以在這裡需要一個java對象來接收。
User類如下:
之後就是將映射文件載入到全局配置文件SqlMapConfig文件中去
就是在該文件加上一句
<mappers>
<mapper resource="sqlMap/User.xml"/>
</mappers>
到這裡整個配置文件就完成了,接下來的工作就是編寫程式來測試了
按照之前的架構一步一步來,最後寫成的程式如下:
public class MybatisTest { @Test public void findUserByIdTest() throws IOException{ InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession=sqlSessionFactory.openSession(); User user=sqlSession.selectOne("test.findUserById",1); System.out.println(user); } }
在這裡值得註意的地方有兩個,第一個是輸入流(inputStream)來源於mybatis配置文件
第二個地方是是selectOne方法里的兩個參數:
第一個參數:映射文件中statement的id,在這裡則要寫成 namespace+’.’+statement的id
第二個參數:指定和映射文件中所匹配的parameterType類型的參數
結果如下:
寫到這裡,Mybatis從配置文件到測試代碼整個Mybatis入門程式已經寫完了,請期待本人接下來的更新