MyBatis學習--簡單的增刪改查


  • jdbc程序

  在學習MyBatis的時候先簡單了解下JDBC編程的方式,我們以一個簡單的查詢為例,使用JDBC編程,如下:

 

 1 Public static void main(String[] args) {
 2             Connection connection = null;
 3             PreparedStatement preparedStatement = null;
 4             ResultSet resultSet = null;
 5             
 6             try {
 7                 //加載數據庫驅動
 8                 Class.forName("com.mysql.jdbc.Driver");
 9                 
10                 //通過驅動管理類獲取數據庫鏈接
11                 connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/shop?characterEncoding=utf-8", "root", "mysql");
12                 //定義sql語句 ?表示占位符
13             String sql = "select * from user where username = ?";
14                 //獲取預處理statement
15                 preparedStatement = connection.prepareStatement(sql);
16                 //設置參數,第一個參數為sql語句中參數的序號(從1開始),第二個參數為設置的參數值
17                 preparedStatement.setString(1, "王五");
18                 //向數據庫發出sql執行查詢,查詢出結果集
19                 resultSet =  preparedStatement.executeQuery();
20                 //遍歷查詢結果集
21                 while(resultSet.next()){
22                     System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));
23                 }
24             } catch (Exception e) {
25                 e.printStackTrace();
26             }finally{
27                 //釋放資源
28                 if(resultSet!=null){
29                     try {
30                         resultSet.close();
31                     } catch (SQLException e) {
32                         // TODO Auto-generated catch block
33                         e.printStackTrace();
34                     }
35                 }
36                 if(preparedStatement!=null){
37                     try {
38                         preparedStatement.close();
39                     } catch (SQLException e) {
40                         // TODO Auto-generated catch block
41                         e.printStackTrace();
42                     }
43                 }
44                 if(connection!=null){
45                     try {
46                         connection.close();
47                     } catch (SQLException e) {
48                         // TODO Auto-generated catch block
49                         e.printStackTrace();
50                     }
51                 }
52 
53             }
54 
55         }

 

  從上面可以看出JDBC編程一般要如下步驟:  

  1、 加載數據庫驅動

  2、 創建並獲取數據庫連接

  3、 創建jdbc statement對象

  4、 設置sql語句

  5、 設置sql語句中的參數(使用preparedStatement)

  6、 通過statement執行sql並獲取結果

  7、 對sql執行結果進行解析處理

  8、 釋放資源(resultSetpreparedstatementconnection)

  可以看出所有的JDBC編程有好多相同的步驟,如:加載驅動、獲取連接等。也有一些不同的地方,如sql語句、參數、查詢結果等。JDBC編程主要有以下問題: 

  1、 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。

 

  2、 Sql語句在代碼中硬編碼,造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。

 

  3、 使用preparedStatement向占有位符號傳參數存在硬編碼,因為sql語句的where條件不一定,可能多也可能少,修改sql還要修改代碼,系統不易維護。

 

  4、 對結果集解析存在硬編碼(查詢列名),sql變化導致解析代碼變化,系統不易維護,如果能將數據庫記錄封裝成pojo對象解析比較方便。

 

 

  MyBatis就是這樣一種框架,把上面的步驟按模板模式進行封裝,將相同的部分實現,將不同的部分在配置文件中配置,同時支持參數和查詢條件的映射、結果集和java對象的映射,從而簡化編程。

  • MyBatis

  MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis,實質上Mybatis對ibatis進行一些改進。 

 

  MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。

 

  Mybatis通過xml或注解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java對象和statement中的sql進行映射生成最終執行的sql語句,最后由mybatis框架執行sql並將結果映射成java對象並返回。

  MyBatis架構圖如下:

  1、 mybatis配置

  SqlMapConfig.xml,此文件作為mybatis的全局配置文件,配置了mybatis的運行環境等信息。

  mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載。

  2、 通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠

  3、 由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行。

  4、 mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。

  5、 Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sqlid即是Mapped statementid

  6、 Mapped Statementsql執行輸入參數進行定義,包括HashMap、基本類型、pojoExecutor通過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。

  7、 Mapped Statementsql執行輸出結果進行定義,包括HashMap、基本類型、pojoExecutor通過Mapped Statement在執行sql后將輸出結果映射至java對象中,輸出結果映射過程相當於jdbc編程中對結果的解析處理過程。

  • MyBatis實例

  應用MyBatis來實現簡單的增刪改查,下面分別實現:

  對象類如下:

 

 1 public class User {
 2     private int id;
 3     private String username;// 用戶姓名
 4     private String sex;// 性別
 5     private Date birthday;// 生日
 6     private String address;// 地址
 7     public int getId() {
 8         return id;
 9     }
10     public void setId(int id) {
11         this.id = id;
12     }
13     public String getUsername() {
14         return username;
15     }
16     public void setUsername(String username) {
17         this.username = username;
18     }
19     public String getSex() {
20         return sex;
21     }
22     public void setSex(String sex) {
23         this.sex = sex;
24     }
25     public Date getBirthday() {
26         return birthday;
27     }
28     public void setBirthday(Date birthday) {
29         this.birthday = birthday;
30     }
31     public String getAddress() {
32         return address;
33     }
34     public void setAddress(String address) {
35         this.address = address;
36     }
37     @Override
38     public String toString() {
39         // TODO Auto-generated method stub
40         return this.id+"-"+this.username+"-"+this.sex+"-"+this.address+"-"+this.birthday.toString();
41     }
42     
43 }
View Code

 

  SqlMapConfig.xml配置如下:

 

 1 <configuration>
 2     <!-- 和spring整合后 environments配置將廢除-->
 3     <environments default="development">
 4         <environment id="development">
 5         <!-- 使用jdbc事務管理-->
 6             <transactionManager type="JDBC" />
 7         <!-- 數據庫連接池-->
 8             <dataSource type="POOLED">
 9                 <property name="driver" value="com.mysql.jdbc.Driver" />
10                 <property name="url" value="jdbc:mysql://localhost:3306/shop?characterEncoding=utf-8" />
11                 <property name="username" value="root" />
12                 <property name="password" value="" />
13             </dataSource>
14         </environment>
15     </environments>
16     <mappers>
17         <mapper resource="sqlmap/User.xml"/>
18     </mappers>
19 </configuration>
View Code

 

  1、用戶id查詢一個用戶信息

  映射文件如下:

 

1 <mapper namespace="user">
2     <select id="findUserById" parameterType="int" resultType="com.luchao.mybatis.first.po.User">
3         select * from user where id = #{id}
4     </select>
5 </mapper>

 

  注意:namespace :命名空間,對sql進行分類化管理,用於隔離sql語句。

  id:和namespace 一起標識statement。

  parameterType:定義輸入到sql中的映射類型,#{id}表示使用preparedstatement設置占位符號並將輸入變量id傳到sql

 

  resultType:定義結果映射類型。

  代碼:

 1 @Before
 2     public void createSqlSessionFactory() throws IOException{
 3         //配置文件
 4         String resource = "SqlMapConfig.xml";
 5         InputStream inputStream = Resources.getResourceAsStream(resource);
 6         //使用SqlSessionFactoryBuilder從xml配置文件中加載sqlSessionFactory
 7         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
 8     }
 9     //根據id查詢用戶
10     @Test
11     public void findUserByIdTest(){
12         //數據庫會話實例
13         SqlSession session = null;
14         try {
15             // 創建數據庫會話實例sqlSession
16             session = sqlSessionFactory.openSession();
17             // 查詢單個記錄,根據用戶id查詢用戶信息
18             User user = session.selectOne("user.findUserById", 10);
19             System.out.println(user);
20         } catch (Exception e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         } finally{
24             if(session!=null){
25                 session.close();
26             }
27         }
28     }

  2、根據用戶名模糊查詢用戶信息

  映射文件:

1 <select id="findUserByName" parameterType="java.lang.String" resultType="com.luchao.mybatis.first.po.User">
2         select * from user where username like '%${value}%'
3 </select>

  #{}表示一個占位符號,通過#{}可以實現preparedStatement向占位符中設置值,自動進行java類型和jdbc類型轉換,#{}可以有效防止sql注入。 #{}可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱。

    ${}表示拼接sql串,通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換, ${}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}括號中只能是value

  代碼:

 

 1 //根據用戶名模糊查詢用戶
 2     @Test
 3     public void findUserByNameTest(){
 4             //數據庫會話實例
 5             SqlSession session = null;
 6             try {
 7                 // 創建數據庫會話實例sqlSession
 8                 session = sqlSessionFactory.openSession();
 9                 // 查詢多個記錄,根據用戶姓名模糊查詢用戶信息
10                 List<User> userList = session.selectList("user.findUserByName", "張");
11                 System.out.println(userList.size());
12             } catch (Exception e) {
13                 // TODO Auto-generated catch block
14                 e.printStackTrace();
15             } finally{
16                 if(session!=null){
17                     session.close();
18                 }
19             }
20 }

 

  selectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常:

1 org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
2 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

    selectList可以查詢一條或多條記錄。

  3、添加用戶

  映射文件:

 

1 <insert id="insertUser" parameterType="com.luchao.mybatis.first.po.User">
2         <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
3             select LAST_INSERT_ID()
4         </selectKey>
5         insert into user(username,birthday,sex,address) value (#{username},#{birthday},#{sex},#{address});
6     </insert>

 

  這里要注意,如果mysql是自增主鍵,映射文件如下:

1 insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
2         <!-- selectKey將主鍵返回,需要再返回 -->
3         <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
4             select LAST_INSERT_ID()
5         </selectKey>
6        insert into user(username,birthday,sex,address)
7         values(#{username},#{birthday},#{sex},#{address});
8 </insert>

  添加selectKey實現將主鍵返回

  keyProperty:返回的主鍵存儲在pojo中的哪個屬性

  orderselectKey的執行順序,是相對與insert語句來說,由於mysql的自增原理執行完insert語句之后才將主鍵生成,所以這里selectKey的執行順序為after

  resultType:返回的主鍵是什么類型

  LAST_INSERT_ID():mysql的函數,返回auto_increment自增列新記錄id值。

  mysql是UUID實現,映射文件如下:

1 <insert  id="insertUser" parameterType="cn.luchao.mybatis.po.User">
2 <selectKey resultType="java.lang.String" order="BEFORE" 
3 keyProperty="id">
4 select uuid()
5 </selectKey>
6 insert into user(id,username,birthday,sex,address) 
7          values(#{id},#{username},#{birthday},#{sex},#{address})
8 </insert>
9 注意這里使用的order是“BEFORE”

 

  Oracle使用序列實現,映射文件如下:

1 <insert  id="insertUser" parameterType="cn.luchao.mybatis.po.User">
2 <selectKey resultType="java.lang.Integer" order="BEFORE" 
3 keyProperty="id">
4 SELECT 自定義序列.NEXTVAL FROM DUAL
5 </selectKey>
6 insert into user(id,username,birthday,sex,address) 
7          values(#{id},#{username},#{birthday},#{sex},#{address})
8 </insert>
9 注意這里使用的order是“BEFORE”

  代碼:

 1 //插入用戶
 2         @Test
 3         public void insertUserTest(){
 4                 //數據庫會話實例
 5                 SqlSession session = null;
 6                 try {
 7                     // 創建數據庫會話實例sqlSession
 8                     session = sqlSessionFactory.openSession();
 9                     //添加用戶信息
10                     User user = new User();
11                     user.setAddress("上海");
12                     user.setBirthday(new Date());
13                     user.setSex("1");
14                     user.setUsername("王小二");
15                     session.insert("insertUser",user);
16                     //提交事務
17                     session.commit();
18                 } catch (Exception e) {
19                     // TODO Auto-generated catch block
20                     e.printStackTrace();
21                 } finally{
22                     if(session!=null){
23                         session.close();
24                     }
25                 }
26         }

  4、刪除用戶

  映射文件:

1 <delete id="deleteUser" parameterType="int">
2         delete from user where id=#{id}
3     </delete>

  代碼:

 1 //刪除用戶
 2                 @Test
 3                 public void deleteUserTest(){
 4                         //數據庫會話實例
 5                         SqlSession session = null;
 6                         try {
 7                             // 創建數據庫會話實例sqlSession
 8                             session = sqlSessionFactory.openSession();
 9                             session.delete("deleteUser",30);
10                             //提交事務
11                             session.commit();
12                         } catch (Exception e) {
13                             // TODO Auto-generated catch block
14                             e.printStackTrace();
15                         } finally{
16                             if(session!=null){
17                                 session.close();
18                             }
19                         }
20                 }

  5、修改用戶:

  映射文件:

1 <update id="updateUser" parameterType="com.luchao.mybatis.first.po.User">
2         update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
3         where id=#{id}
4     </update>

  代碼:

 1 //修改用戶
 2                 @Test
 3                 public void updteaUserTest(){
 4                         //數據庫會話實例
 5                         SqlSession session = null;
 6                         try {
 7                             // 創建數據庫會話實例sqlSession
 8                             session = sqlSessionFactory.openSession();
 9                             //修改用戶信息
10                             User user = new User();
11                             user.setId(28);
12                             user.setAddress("上海");
13                             user.setBirthday(new Date());
14                             user.setSex("0");
15                             user.setUsername("王小二1");
16                             session.update("updateUser", user);
17                             //提交事務
18                             session.commit();
19                         } catch (Exception e) {
20                             // TODO Auto-generated catch block
21                             e.printStackTrace();
22                         } finally{
23                             if(session!=null){
24                                 session.close();
25                             }
26                         }
27                 }
  • MyBatis解決JDBC編程的問題 

  1、 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。

  解決:在SqlMapConfig.xml中配置數據鏈接池,使用連接池管理數據庫鏈接。

  2、 Sql語句寫在代碼中造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。

  解決:將Sql語句配置文件中與java代碼分離。

  3、 向sql語句傳參數麻煩,因為sql語句的where條件不一定,可能多也可能少,占位符需要和參數一一對應。

  解決:Mybatis自動將java對象映射至sql語句,通過statement中的parameterType定義輸入參數的類型。

  4、 對結果集解析麻煩,sql變化導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。

  解決:Mybatis自動將sql執行結果映射至java對象,通過statement中的resultType定義輸出結果的類型。

  • MyBatis與Habernate的比較

  Mybatishibernate不同,它不完全是一個ORM框架,因為MyBatis需要程序員自己編寫Sql語句,不過mybatis可以通過XML或注解方式靈活配置要運行的sql語句,並將java對象和sql語句映射生成最終執行的sql,最后將sql執行的結果再映射生成java對象。

 

    Mybatis學習門檻低,簡單易學,程序員直接編寫原生態sql,可嚴格控制sql執行性能,靈活度高,非常適合對關系數據模型要求不高的軟件開發,例如互聯網軟件、企業運營類軟件等,因為這類軟件需求變化頻繁,一但需求變化要求成果輸出迅速。但是靈活的前提是mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件則需要自定義多套sql映射文件,工作量大。專注是sql本身,需要程序員自己編寫sql語句,sql修改、優化比較方便。mybatis是一個不完全 的ORM框架,可以簡單理解為SQL Mapper,雖然程序員自己寫sqlmybatis 也可以實現映射(輸入映射、輸出映射)。應用場景:適用與需求變化較多的項目,比如:互聯網項目。

 

 

    Hibernate對象/關系映射能力強,數據庫無關性好,對於關系模型要求高的軟件(例如需求固定的定制化軟件)如果用hibernate開發可以節省很多代碼,提高效率。但是Hibernate的學習門檻高,要精通門檻更高,而且怎么設計O/R映射,在性能和對象模型之間如何權衡,以及怎樣用好Hibernate需要具有很強的經驗和能力才行。是一個標准ORM框架(對象關系映射)。入門門檻較高的,不需要程序寫sqlsql語句自動生成了,sql語句進行優化、修改比較困難的。應用場景:適用與需求變化不多的中小型項目,比如:后台管理系統,erpormoa

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM