Mybatis使用詳解和入門案例
前言 MyBatis和Hibernate一樣,是一個優秀的持久層框架。已經說過很多次了,原生的jdbc操作存在大量的重複性程式碼(如註冊驅動,建立連線,建立statement,結果集檢測等)。框架的作用就是把這些繁瑣的程式碼封裝,這樣可以讓程式設計師專注於sql語句本身。
MyBatis通過XML或者註解的方式將要執行的sql語句配置起來,並通過java物件和sql語句對映成最終執行的sql語句。最終由MyBatis框架執行sql,並將結果對映成java物件並返回。
正文 一,MyBatis的執行流程
mybatis配置檔案,包括Mybatis全域性配置檔案和Mybatis對映檔案,其中全域性配置檔案配置了資料來源、事務等資訊;對映檔案配置了SQL執行相關的 資訊。 mybatis通過讀取配置檔案資訊(全域性配置檔案和對映檔案),構造出SqlSessionFactory,即會話工廠。 通過SqlSessionFactory,可以建立SqlSession即會話。Mybatis是通過SqlSession來操作資料庫的。 SqlSession本身不能直接操作資料庫,它是通過底層的Executor執行器介面來操作資料庫的。Executor介面有兩個實現類,一個是普通執行器,一個是快取執行器(預設)。 Executor執行器要處理的SQL資訊是封裝到一個底層物件MappedStatement中。該物件包括:SQL語句、輸入引數對映資訊、輸出結果集對映資訊。其中輸入引數和輸出結果的對映型別包括java的簡單型別、HashMap集合物件、POJO物件型別。 二,MyBatis經典入門案例(原始DAO實現使用者表的增刪改查)
1,環境準備
Jdk環境:jdk1.7.0_72 Ide環境:eclipse indigo 資料庫環境:MySQL 5.1 Mybatis:3.2.7 mysql建庫:
CREATE TABLE `user4` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(20) , `password` varchar(20) , `age` int(11) , PRIMARY KEY (`id`) ) 1 2 3 4 5 6 7 專案目錄如下:
下面一一講解這些檔案。
2,全域性配置檔案:SqlMapConfig.xml
主要是2個標籤:
environments-用於獲取連線池連線,將來與spring整合時,這個就不要啦,由spring來配置資料庫連線。
mappers-用於引用對映檔案。
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/user"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="User.xml"/> </mappers> </configuration> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 3,建立主體類:User.class
package com.jimmy.domain;
public class User { private Integer id; private String username; private String password; private Integer age; //get,set方法省略 } 1 2 3 4 5 6 7 8 9 4,建立對映檔案:User.xml
對映檔案就是框架的核心啦,下面這個檔案就配置了java物件與資料庫表之間的對映。
我們看到,其中4個標籤:select,insert ,delete ,update 分別對應著“查,增,刪,改”操作。每個標籤中還有一些屬性,下面來解釋下:
id:給標籤體內的sql操作起個名字,方便呼叫。 parameterType:傳入引數的型別。傳入java型別,轉化為sql型別,新增到sql語句上。 resultType:返回結果型別。sql結果集轉化為java型別並返回。 <?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屬性,不然會報錯,可看做包名--> <mapper namespace="user"> <select id="findUserById" parameterType="int" resultType="com.jimmy.domain.User"> select * from user4 where id = #{id} </select> <select id="findUserAll" resultType="com.jimmy.domain.User"> select * from user4 </select> <insert id="insertUser" parameterType="com.jimmy.domain.User"> insert into user4(username,password,age) values(#{username},#{password},#{age}) </insert> <delete id="deleteUserById" parameterType="int"> delete from user4 where id=#{id} </delete> <update id="updateUserPassword" parameterType="com.jimmy.domain.User"> update user4 set password=#{password} where id=#{id} </update> </mapper> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 5,建立dao介面和實現類
package com.jimmy.dao;
import java.util.List;
import com.jimmy.domain.User;
// 介面 public interface UserDao { public User findUserById(int id) throws Exception ; public List<User> findAllUsers() throws Exception; public void insertUser(User user) throws Exception; public void deleteUserById(int id) throws Exception; public void updateUserPassword(User user) throws Exception; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.jimmy.dao.impl;
import java.io.InputStream; import java.util.List;
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.jimmy.dao.UserDao; import com.jimmy.domain.User;
// 實現類 public class UserDaoImpl implements UserDao {
public User findUserById(int id) throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------- User user = session.selectOne("user.findUserById",id); //引數一:namespace.id //-------------- session.close(); return user; }
public List<User> findAllUsers() throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- List<User> users = session.selectList("user.findUserAll"); //---------------------- session.close(); return users; }
public void insertUser(User user) throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- session.insert("user.insertUser", user); session.commit(); //增刪改,一定一定要加上commit操作 //---------------------- session.close(); }
public void deleteUserById(int id) throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- session.delete("user.deleteUserById", id); session.commit(); //增刪改,一定一定要加上commit操作 //---------------------- session.close(); }
public void updateUserPassword(User user) throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- session.update("user.updateUserPassword", user); session.commit(); //增刪改,一定一定要加上commit操作 //---------------------- session.close(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 6,編寫測試類
package com.jimmy.test;
import java.util.List; import org.junit.Test; import com.jimmy.dao.UserDao; import com.jimmy.dao.impl.UserDaoImpl; import com.jimmy.domain.User;
public class Test3 { @Test public void testFindUserById() throws Exception{ UserDao userDao = new UserDaoImpl(); User user = userDao.findUserById(7); System.out.println(user); } @Test public void testFindAllUser() throws Exception{ UserDao userDao = new UserDaoImpl(); List<User> findAllUsers = userDao.findAllUsers(); for (User user2 : findAllUsers) { System.out.println(user2); } } @Test public void testInsertUser() throws Exception{ UserDao userDao = new UserDaoImpl(); User user = new User(); user.setUsername("張三"); user.setPassword("lalal"); user.setAge(12); userDao.insertUser(user); } @Test public void testDeleteUserById() throws Exception{ UserDao userDao = new UserDaoImpl(); userDao.deleteUserById(3); } @Test public void testUpdateUserPassword() throws Exception{ UserDao userDao = new UserDaoImpl(); User user = new User(); user.setId(9); user.setPassword("newpassword"); userDao.updateUserPassword(user); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 至此,一個完整的Mybatis入門案例已經初步完成。
回過頭來看DAO的實現類,原始dao開發存在一些問題:
存在一定量的模板程式碼。比如:通過SqlSessionFactory建立SqlSession;呼叫SqlSession的方法操作資料庫;關閉Sqlsession。 存在一些硬編碼。呼叫SqlSession的方法操作資料庫時,需要指定statement的id,這裡存在了硬編碼。 三,Mapper代理開發模式
Mapper代理的開發方式,程式設計師只需要編寫mapper介面(相當於dao介面)即可,而不同再寫dao實現類啦。Mybatis會自動的為mapper介面生成動態代理實現類。不過要實現mapper代理的開發方式,需要遵循一些開發規範。
mapper介面的全限定名要和mapper對映檔案的namespace的值相同。 mapper介面的方法名稱要和mapper對映檔案中的statement的id相同。 mapper介面的方法引數只能有一個,且型別要和mapper對映檔案中statement的parameterType的值保持一致。 mapper介面的返回值型別要和mapper對映檔案中statement的resultType值或resultMap中的type值保持一致。 上面4句話的意思是:介面的包名,類名,引數,返回值分別對應著對映檔案的namespace,id,parameterType,resultType。
下面來改造上面的例子。
1,環境準備,同上。 2,全域性配置檔案,同上。記得引用新的對映檔案。 3,建立主題類,同上。 4,建立對映檔案:UserMapper.xml。檔名一般加上“Mapper”。
下面這個檔案跟原始dao程式設計只有一點不同,就是namespace值。
<?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屬性,不然會報錯,且mapper開發時設定為Mapper介面的全限定名--> <mapper namespace="com.jimmy.dao.UserMapper"> <select id="findUserById" parameterType="int" resultType="com.jimmy.domain.User"> select * from user4 where id = #{id} </select> <select id="findUserAll" resultType="com.jimmy.domain.User"> select * from user4 </select> <insert id="insertUser" parameterType="com.jimmy.domain.User"> insert into user4(username,password,age) values(#{username},#{password},#{age}) </insert> <delete id="deleteUserById" parameterType="int"> delete from user4 where id=#{id} </delete> <update id="updateUserPassword" parameterType="com.jimmy.domain.User"> update user4 set password=#{password} where id=#{id} </update> </mapper> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 5,建立Mapper介面,這裡就沒有實現類啦。
注意,函式一定要注意4點規範。
package com.jimmy.dao;
import java.util.List;
import com.jimmy.domain.User;
public interface UserMapper { public User findUserById(int id); public List<User> findUserAll(); public void insertUser(User user); public void deleteUserById(int id); public void updateUserPassword(User user); } 1 2 3 4 5 6 7 8 9 10 11 12 13 6,編寫測試類
package com.jimmy.test;
import java.io.InputStream; import java.util.List;
import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test;
import com.jimmy.dao.UserMapper; import com.jimmy.domain.User;
public class Test1 { @Test public void findUserByID() throws Exception{ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------- UserMapper userMapper = session.getMapper(UserMapper.class); User user = userMapper.findUserById(2); System.out.println(user); //-------------- session.close(); } @Test public void findAll() throws Exception{ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- UserMapper mapper = session.getMapper(UserMapper.class); List<User> user = mapper.findUserAll(); for (User user2 : user) { System.out.println(user2); } //---------------------- session.close(); } @Test public void insertTest() throws Exception{ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- User user = new User(); user.setUsername("lalala"); user.setPassword("asdf"); user.setAge(12);
UserMapper mapper = session.getMapper(UserMapper.class); mapper.insertUser(user); session.commit(); //---------------------- session.close(); } @Test public void deleteUserById() throws Exception{ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- UserMapper mapper = session.getMapper(UserMapper.class); mapper.deleteUserById(2); session.commit(); //---------------------- session.close(); } @Test public void updateUserPassword() throws Exception{ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); //--------------------- User user = new User(); user.setId(4); user.setPassword("newPassword3");
UserMapper mapper = session.getMapper(UserMapper.class); mapper.updateUserPassword(user); session.commit(); //---------------------- session.close(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 我們看到,現在已經不需要再寫dao介面的實現類啦,而是框架通過對映檔案為我們生成代理類。而那些重複性的程式碼已經轉移到測試程式碼中了,我們在整合spring和Mybatis時,這些重複性程式碼都會在配置檔案中配置。 --------------------- 作者:name_s_Jimmy 來源:CSDN 原文:https://blog.csdn.net/qq_32166627/article/details/70741729 版權宣告:本文為博主原創文章,轉載請附上博文連結!