簡介
使用Mybatis開發(fā)Dao,通常有兩個方法,即原始Dao開發(fā)方法和Mapper接口開發(fā)方法。下面話不多說,來一起看看詳細(xì)的介紹:
主要概念介紹:
MyBatis中進(jìn)行Dao開發(fā)時候有幾個重要的類,它們是SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession。
SqlSession中封裝了對數(shù)據(jù)庫的操作,如:查詢、插入、更新、刪除等。通過SqlSessionFactory創(chuàng)建SqlSession,而SqlSessionFactory是通過SqlSessionFactoryBuilder進(jìn)行創(chuàng)建。
1、SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于創(chuàng)建SqlSessionFacoty,SqlSessionFacoty一旦創(chuàng)建完成就不需要SqlSessionFactoryBuilder了,因為SqlSession是通過SqlSessionFactory生產(chǎn),所以可以將SqlSessionFactoryBuilder當(dāng)成一個工具類使用,最佳使用范圍是方法范圍即方法體內(nèi)局部變量。
2、SqlSessionFactory
SqlSessionFactory是一個接口,接口中定義了openSession的不同重載方法,SqlSessionFactory的最佳使用范圍是整個應(yīng)用運行期間,一旦創(chuàng)建后可以重復(fù)使用,通常以單例模式管理SqlSessionFactory。
3、SqlSession
SqlSession是一個面向用戶的接口, sqlSession中定義了數(shù)據(jù)庫操作,默認(rèn)使用DefaultSqlSession實現(xiàn)類。
SqlSession中提供了很多操作數(shù)據(jù)庫的方法:如:selectOne(返回單個對象)、selectList(返回單個或多個對象),SqlSession是線程不安全的,在SqlSesion實現(xiàn)類中除了有接口中的方法(操作數(shù)據(jù)庫的方法)還有數(shù)據(jù)域?qū)傩裕琒qlSession最佳應(yīng)用場合在方法體內(nèi),定義成局部變量使用,絕對不能將SqlSession實例的引用放在一個類的靜態(tài)字段或?qū)嵗侄沃小?/p>
打開一個 SqlSession;使用完畢就要關(guān)閉它。通常把這個關(guān)閉操作放到 finally 塊中以確保每次都能執(zhí)行關(guān)閉。
如下:
1
2
3
4
5
6
|
SqlSession session = sqlSessionFactory.openSession(); try { // do work } finally { session.close(); } |
原始Dao開發(fā)方式
原始Dao開發(fā)方法需要程序員編寫Dao接口和Dao實現(xiàn)類。
還是以前文提到的簡單的增刪改查為例,來簡單介紹原始Dao開發(fā)方式。
1、映射文件
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
|
<?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= "user" > <!-- 根據(jù)id獲取用戶信息 --> <select id= "findUserById" parameterType= "int" resultType= "user" > select * from user where id = #{id} </select> <!-- 根據(jù)username模糊查詢用戶信息 --> <select id= "findUserByName" parameterType= "java.lang.String" resultType= "com.luchao.mybatis.first.po.User" > select * from user where username like '%${value}%' </select> <!-- 添加用戶信息 --> <insert id= "insertUser" parameterType= "com.luchao.mybatis.first.po.User" > <selectKey keyProperty= "id" order= "AFTER" resultType= "java.lang.Integer" > select LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) value (#{username},#{birthday},#{sex},#{address}); </insert> <!-- 根據(jù)id刪除用戶信息 --> <delete id= "deleteUser" parameterType= "int" > delete from user where id=#{id} </delete> <!-- 修改用戶信息 --> <update id= "updateUser" parameterType= "com.luchao.mybatis.first.po.User" > update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper> |
2、Dao接口
1
2
3
4
5
6
7
8
|
public interface UserDao { //根據(jù)ID查詢用戶信息 public User findUserById( int id) throws Exception; //添加用戶信息 public void insertUser(User user) throws Exception; //刪除用戶信息 public void deleteUser( int id) throws Exception; } |
3、Dao接口實現(xiàn)類
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
|
public class UserDaoImpl implements UserDao{ // 需要向dao實現(xiàn)類中注入SqlSessionFactory // 這里通過構(gòu)造方法注入 private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { super (); this .sqlSessionFactory = sqlSessionFactory; } @Override public void deleteUser( int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); //執(zhí)行刪除操作 sqlSession.insert( "user.deleteUser" , id); // 提交事務(wù) sqlSession.commit(); // 釋放資源 sqlSession.close(); } @Override public User findUserById( int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); //獲取sqlSession User user = sqlSession.selectOne( "user.findUserById" , id); sqlSession.close(); //關(guān)閉資源 return user; } @Override public void insertUser(User user) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); //執(zhí)行插入操作 sqlSession.insert( "user.insertUser" , user); // 提交事務(wù) sqlSession.commit(); // 釋放資源 sqlSession.close(); } } |
4、測試代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class MyBatis_dao_test { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException{ //創(chuàng)建sqlSessionFactory //MyBatis配置文件 String resource = "SqlMapConfig.xml" ; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創(chuàng)建會話工廠,傳入MyBatis的配置信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ //創(chuàng)建UserDao對象 UserDao userDao = new UserDaoImpl(sqlSessionFactory); //調(diào)用UserDao的方法,根據(jù)ID查找user User user = userDao.findUserById( 10 ); //打印客戶信息 System.out.println(user); } } |
5、原始Dao方法總結(jié):
(1)、dao接口實現(xiàn)類方法中存在大量模板方法,如:通過SqlSessionFactory創(chuàng)建SqlSession,調(diào)用SqlSession的數(shù)據(jù)庫操作方法。
(2)、調(diào)用sqlSession的數(shù)據(jù)庫操作方法需要指定statement的id,這里存在硬編碼。
(3)、調(diào)用sqlsession方法時傳入的變量,由于sqlsession方法使用泛型,即使變量類型傳入錯誤,在編譯階段也不報錯,不利于程序員開發(fā)。
Mapper動態(tài)代理方式
1、實現(xiàn)原理
Mapper接口開發(fā)方法只需要程序員編寫Mapper接口(相當(dāng)于Dao接口),由Mybatis框架根據(jù)接口定義創(chuàng)建接口的動態(tài)代理對象,代理對象的方法體同上邊Dao接口實現(xiàn)類方法。這樣通過動態(tài)代理就實現(xiàn)了將模板方法進(jìn)行封裝,只需要實現(xiàn)具體的實現(xiàn)即可。
Mapper接口開發(fā)需要遵循以下規(guī)范:
(1)、 Mapper.xml文件中的namespace與mapper接口的類路徑相同。
(2)、 Mapper接口方法名和Mapper.xml中定義的每個statement的id相同 。
(3)、 Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個sql 的parameterType的類型相同。
(4)、 Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個sql的resultType的類型相同。
2、Mapper.xml(映射文件)
映射文件與原始Dao開發(fā)的映射文件相似,只需要將namespace定于為mapper接口全路徑。
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
|
<?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= "com.luchao.mybatis.first.mapper.UserMapper" > <!-- 根據(jù)id獲取用戶信息 --> <select id= "findUserById" parameterType= "int" resultType= "user" > select * from user where id = #{id} </select> <!-- 根據(jù)username模糊查詢用戶信息 --> <select id= "findUserByName" parameterType= "java.lang.String" resultType= "com.luchao.mybatis.first.po.User" > select * from user where username like '%${value}%' </select> <!-- 添加用戶信息 --> <insert id= "insertUser" parameterType= "com.luchao.mybatis.first.po.User" > <selectKey keyProperty= "id" order= "AFTER" resultType= "java.lang.Integer" > select LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) value (#{username},#{birthday},#{sex},#{address}); </insert> <!-- 根據(jù)id刪除用戶信息 --> <delete id= "deleteUser" parameterType= "int" > delete from user where id=#{id} </delete> <!-- 修改用戶信息 --> <update id= "updateUser" parameterType= "com.luchao.mybatis.first.po.User" > update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper> |
3、Mapper.java(接口文件)
1
2
3
4
5
6
7
8
9
10
11
12
|
public interface UserMapper { //根據(jù)ID查詢用戶信息 public User findUserById( int id) throws Exception; //添加用戶信息 public void insertUser(User user) throws Exception; //刪除用戶信息 public void deleteUser( int id) throws Exception; //更新用戶信息 public void updateUser(User user) throws Exception; //根據(jù)用戶名模糊查找 public List<User> findUserByName(String user) throws Exception; } |
接口定義有如下特點:
(1)、 Mapper接口方法名和Mapper.xml中定義的statement的id相同。
(2)、 Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的statement的parameterType的類型相同。
(3)、 Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的statement的resultType的類型相同。
4、加載UserMapper.xml文件
在SqlMapConfig.xml文件中加載UserMapper.xml,如下:
1
2
3
|
<mappers> <mapper resource= "mapper/UserMapper.xml" /> </mappers> |
5、測試代碼:
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
|
public class MyBatis_mapper_test { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException{ //創(chuàng)建sqlSessionFactory //MyBatis配置文件 String resource = "SqlMapConfig.xml" ; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //創(chuàng)建會話工廠,傳入MyBatis的配置信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ //獲取sqlSession對象 SqlSession sqlSession = sqlSessionFactory.openSession(); //創(chuàng)建UserMapper對象,MyBatis自動生成mapper代理 UserMapper userMapper = sqlSession.getMapper(UserMapper. class ); //調(diào)用userMapper的方法 User user = userMapper.findUserById( 10 ); //關(guān)閉資源 sqlSession.close(); //打印客戶信息 System.out.println(user); } } |
5、Mapper動態(tài)代理總結(jié):
(1)、動態(tài)代理對象調(diào)用sqlSession.selectOne()
和sqlSession.selectList()
是根據(jù)mapper接口方法的返回值決定,如果返回list則調(diào)用selectList方法,如果返回單個對象則調(diào)用selectOne方法。
(2)、使用mapper代理方法時,輸入?yún)?shù)可以使用pojo包裝對象或map對象,保證dao的通用性。在系統(tǒng)中,dao層的代碼是被業(yè)務(wù)層公用的。即使mapper接口只有一個參數(shù),可以使用包裝類型的pojo滿足不同的業(yè)務(wù)方法的需求。
注意:持久層方法的參數(shù)可以包裝類型、map等,service方法中建議不要使用包裝類型(不利于業(yè)務(wù)層的可擴(kuò)展)。
mybatis開發(fā)dao的方法有兩種:原始Dao開發(fā)和Mapper動態(tài)代理開發(fā),這兩種各有優(yōu)點。原始Dao開發(fā):程序員要寫Dao和Dao實現(xiàn),需要些較多的代碼,但是比較好理解。Mapper動態(tài)代理:程序員只需要寫Mapper接口,然后按照規(guī)范進(jìn)行配置,MyBatis就會自動實現(xiàn)類似Dao實現(xiàn),減少模板方法。mybatis官方推薦使用mapper代理方法開發(fā)mapper接口,程序員不用編寫mapper接口實現(xiàn)類,使用mapper代理方法時,輸入?yún)?shù)可以使用pojo包裝對象或map對象,保證dao的通用性。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。
原文鏈接:http://www.cnblogs.com/lcngu/p/5468295.html