MyBatis學(xué)習(xí)教程之開(kāi)發(fā)Dao的方法教程
簡(jiǎn)介
使用Mybatis開(kāi)發(fā)Dao,通常有兩個(gè)方法,即原始Dao開(kāi)發(fā)方法和Mapper接口開(kāi)發(fā)方法。下面話(huà)不多說(shuō),來(lái)一起看看詳細(xì)的介紹:
主要概念介紹:
MyBatis中進(jìn)行Dao開(kāi)發(fā)時(shí)候有幾個(gè)重要的類(lèi),它們是SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession。
SqlSession中封裝了對(duì)數(shù)據(jù)庫(kù)的操作,如:查詢(xún)、插入、更新、刪除等。通過(guò)SqlSessionFactory創(chuàng)建SqlSession,而SqlSessionFactory是通過(guò)SqlSessionFactoryBuilder進(jìn)行創(chuàng)建。
1、SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于創(chuàng)建SqlSessionFacoty,SqlSessionFacoty一旦創(chuàng)建完成就不需要SqlSessionFactoryBuilder了,因?yàn)镾qlSession是通過(guò)SqlSessionFactory生產(chǎn),所以可以將SqlSessionFactoryBuilder當(dāng)成一個(gè)工具類(lèi)使用,最佳使用范圍是方法范圍即方法體內(nèi)局部變量。
2、SqlSessionFactory
SqlSessionFactory是一個(gè)接口,接口中定義了openSession的不同重載方法,SqlSessionFactory的最佳使用范圍是整個(gè)應(yīng)用運(yùn)行期間,一旦創(chuàng)建后可以重復(fù)使用,通常以單例模式管理SqlSessionFactory。
3、SqlSession
SqlSession是一個(gè)面向用戶(hù)的接口, sqlSession中定義了數(shù)據(jù)庫(kù)操作,默認(rèn)使用DefaultSqlSession實(shí)現(xiàn)類(lèi)。
SqlSession中提供了很多操作數(shù)據(jù)庫(kù)的方法:如:selectOne(返回單個(gè)對(duì)象)、selectList(返回單個(gè)或多個(gè)對(duì)象),SqlSession是線程不安全的,在SqlSesion實(shí)現(xiàn)類(lèi)中除了有接口中的方法(操作數(shù)據(jù)庫(kù)的方法)還有數(shù)據(jù)域?qū)傩裕琒qlSession最佳應(yīng)用場(chǎng)合在方法體內(nèi),定義成局部變量使用,絕對(duì)不能將SqlSession實(shí)例的引用放在一個(gè)類(lèi)的靜態(tài)字段或?qū)嵗侄沃小?/p>
打開(kāi)一個(gè) SqlSession;使用完畢就要關(guān)閉它。通常把這個(gè)關(guān)閉操作放到 finally 塊中以確保每次都能執(zhí)行關(guān)閉。
如下:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
原始Dao開(kāi)發(fā)方式
原始Dao開(kāi)發(fā)方法需要程序員編寫(xiě)Dao接口和Dao實(shí)現(xiàn)類(lèi)。
還是以前文提到的簡(jiǎn)單的增刪改查為例,來(lái)簡(jiǎn)單介紹原始Dao開(kāi)發(fā)方式。
1、映射文件
<?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獲取用戶(hù)信息 -->
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
<!-- 根據(jù)username模糊查詢(xún)用戶(hù)信息 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.luchao.mybatis.first.po.User">
select * from user where username like '%${value}%'
</select>
<!-- 添加用戶(hù)信息 -->
<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刪除用戶(hù)信息 -->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<!-- 修改用戶(hù)信息 -->
<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接口
public interface UserDao {
//根據(jù)ID查詢(xún)用戶(hù)信息
public User findUserById(int id) throws Exception;
//添加用戶(hù)信息
public void insertUser(User user) throws Exception;
//刪除用戶(hù)信息
public void deleteUser(int id) throws Exception;
}
3、Dao接口實(shí)現(xiàn)類(lèi)
public class UserDaoImpl implements UserDao{
// 需要向dao實(shí)現(xiàn)類(lèi)中注入SqlSessionFactory
// 這里通過(guò)構(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、測(cè)試代碼:
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)建會(huì)話(huà)工廠,傳入MyBatis的配置信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
//創(chuàng)建UserDao對(duì)象
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
//調(diào)用UserDao的方法,根據(jù)ID查找user
User user = userDao.findUserById(10);
//打印客戶(hù)信息
System.out.println(user);
}
}
5、原始Dao方法總結(jié):
(1)、dao接口實(shí)現(xiàn)類(lèi)方法中存在大量模板方法,如:通過(guò)SqlSessionFactory創(chuàng)建SqlSession,調(diào)用SqlSession的數(shù)據(jù)庫(kù)操作方法。
?。?)、調(diào)用sqlSession的數(shù)據(jù)庫(kù)操作方法需要指定statement的id,這里存在硬編碼。
?。?)、調(diào)用sqlsession方法時(shí)傳入的變量,由于sqlsession方法使用泛型,即使變量類(lèi)型傳入錯(cuò)誤,在編譯階段也不報(bào)錯(cuò),不利于程序員開(kāi)發(fā)。
Mapper動(dòng)態(tài)代理方式
1、實(shí)現(xiàn)原理
Mapper接口開(kāi)發(fā)方法只需要程序員編寫(xiě)Mapper接口(相當(dāng)于Dao接口),由Mybatis框架根據(jù)接口定義創(chuàng)建接口的動(dòng)態(tài)代理對(duì)象,代理對(duì)象的方法體同上邊Dao接口實(shí)現(xiàn)類(lèi)方法。這樣通過(guò)動(dòng)態(tài)代理就實(shí)現(xiàn)了將模板方法進(jìn)行封裝,只需要實(shí)現(xiàn)具體的實(shí)現(xiàn)即可。
Mapper接口開(kāi)發(fā)需要遵循以下規(guī)范:
(1)、 Mapper.xml文件中的namespace與mapper接口的類(lèi)路徑相同。
(2)、 Mapper接口方法名和Mapper.xml中定義的每個(gè)statement的id相同 。
(3)、 Mapper接口方法的輸入?yún)?shù)類(lèi)型和mapper.xml中定義的每個(gè)sql 的parameterType的類(lèi)型相同。
(4)、 Mapper接口方法的輸出參數(shù)類(lèi)型和mapper.xml中定義的每個(gè)sql的resultType的類(lèi)型相同。
2、Mapper.xml(映射文件)
映射文件與原始Dao開(kāi)發(fā)的映射文件相似,只需要將namespace定于為mapper接口全路徑。
<?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獲取用戶(hù)信息 -->
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
<!-- 根據(jù)username模糊查詢(xún)用戶(hù)信息 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.luchao.mybatis.first.po.User">
select * from user where username like '%${value}%'
</select>
<!-- 添加用戶(hù)信息 -->
<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刪除用戶(hù)信息 -->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<!-- 修改用戶(hù)信息 -->
<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(接口文件)
public interface UserMapper {
//根據(jù)ID查詢(xún)用戶(hù)信息
public User findUserById(int id) throws Exception;
//添加用戶(hù)信息
public void insertUser(User user) throws Exception;
//刪除用戶(hù)信息
public void deleteUser(int id) throws Exception;
//更新用戶(hù)信息
public void updateUser(User user) throws Exception;
//根據(jù)用戶(hù)名模糊查找
public List<User> findUserByName(String user) throws Exception;
}
接口定義有如下特點(diǎn):
?。?)、 Mapper接口方法名和Mapper.xml中定義的statement的id相同。
?。?)、 Mapper接口方法的輸入?yún)?shù)類(lèi)型和mapper.xml中定義的statement的parameterType的類(lèi)型相同。
?。?)、 Mapper接口方法的輸出參數(shù)類(lèi)型和mapper.xml中定義的statement的resultType的類(lèi)型相同。
4、加載UserMapper.xml文件
在SqlMapConfig.xml文件中加載UserMapper.xml,如下:
<mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers>
5、測(cè)試代碼:
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)建會(huì)話(huà)工廠,傳入MyBatis的配置信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception{
//獲取sqlSession對(duì)象
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper對(duì)象,MyBatis自動(dòng)生成mapper代理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//調(diào)用userMapper的方法
User user = userMapper.findUserById(10);
//關(guān)閉資源
sqlSession.close();
//打印客戶(hù)信息
System.out.println(user);
}
}
5、Mapper動(dòng)態(tài)代理總結(jié):
?。?)、動(dòng)態(tài)代理對(duì)象調(diào)用sqlSession.selectOne()和sqlSession.selectList()是根據(jù)mapper接口方法的返回值決定,如果返回list則調(diào)用selectList方法,如果返回單個(gè)對(duì)象則調(diào)用selectOne方法。
?。?)、使用mapper代理方法時(shí),輸入?yún)?shù)可以使用pojo包裝對(duì)象或map對(duì)象,保證dao的通用性。在系統(tǒng)中,dao層的代碼是被業(yè)務(wù)層公用的。即使mapper接口只有一個(gè)參數(shù),可以使用包裝類(lèi)型的pojo滿(mǎn)足不同的業(yè)務(wù)方法的需求。
注意:持久層方法的參數(shù)可以包裝類(lèi)型、map等,service方法中建議不要使用包裝類(lèi)型(不利于業(yè)務(wù)層的可擴(kuò)展)。
mybatis開(kāi)發(fā)dao的方法有兩種:原始Dao開(kāi)發(fā)和Mapper動(dòng)態(tài)代理開(kāi)發(fā),這兩種各有優(yōu)點(diǎn)。原始Dao開(kāi)發(fā):程序員要寫(xiě)Dao和Dao實(shí)現(xiàn),需要些較多的代碼,但是比較好理解。Mapper動(dòng)態(tài)代理:程序員只需要寫(xiě)Mapper接口,然后按照規(guī)范進(jìn)行配置,MyBatis就會(huì)自動(dòng)實(shí)現(xiàn)類(lèi)似Dao實(shí)現(xiàn),減少模板方法。mybatis官方推薦使用mapper代理方法開(kāi)發(fā)mapper接口,程序員不用編寫(xiě)mapper接口實(shí)現(xiàn)類(lèi),使用mapper代理方法時(shí),輸入?yún)?shù)可以使用pojo包裝對(duì)象或map對(duì)象,保證dao的通用性。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Java selenium處理極驗(yàn)滑動(dòng)驗(yàn)證碼示例
本篇文章主要介紹了Java selenium處理極驗(yàn)滑動(dòng)驗(yàn)證碼示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
解決Spring Cloud中Feign/Ribbon第一次請(qǐng)求失敗的方法
這篇文章主要給大家介紹了關(guān)于解決Spring Cloud中Feign/Ribbon第一次請(qǐng)求失敗的方法,文中給出了三種解決的方法,大家可以根據(jù)需要選擇對(duì)應(yīng)的方法,需要的朋友們下面來(lái)一起看看吧。2017-02-02
java 多線程實(shí)現(xiàn)在線咨詢(xún)(udp)
這篇文章主要介紹了java 多線程實(shí)現(xiàn)在線咨詢(xún)(udp)的示例,幫助大家更好的理解和學(xué)習(xí)Java 網(wǎng)絡(luò)編程的相關(guān)內(nèi)容,感興趣的朋友可以了解下2020-11-11
使用SpringBoot Actuator監(jiān)控應(yīng)用示例
Actuator是Spring Boot提供的對(duì)應(yīng)用系統(tǒng)的自省和監(jiān)控的集成功能,可以對(duì)應(yīng)用系統(tǒng)進(jìn)行配置查看、相關(guān)功能統(tǒng)計(jì)等。這篇文章主要介紹了使用SpringBoot Actuator監(jiān)控應(yīng),有興趣的可以了解一下2018-05-05
java token生成和校驗(yàn)的實(shí)例代碼
這篇文章主要介紹了java token生成和校驗(yàn)的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
Springboot @Transactional使用時(shí)需注意的幾個(gè)問(wèn)題記錄
本文詳細(xì)介紹了Spring Boot中使用`@Transactional`注解進(jìn)行事務(wù)管理的多個(gè)方面,包括事務(wù)的隔離級(jí)別(如REPEATABLE_READ)和傳播行為(如REQUIRES_NEW),并指出了在同一個(gè)類(lèi)中調(diào)用事務(wù)方法時(shí)可能遇到的問(wèn)題以及解決方案,感興趣的朋友跟隨小編一起看看吧2025-01-01
使用ScheduledThreadPoolExecutor踩過(guò)最痛的坑
這篇文章主要介紹了使用ScheduledThreadPoolExecutor踩過(guò)最痛的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Java實(shí)現(xiàn)公眾號(hào)功能、關(guān)注及消息推送實(shí)例代碼
公眾號(hào)開(kāi)發(fā)近些年是一個(gè)比較熱門(mén)的方向,下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)公眾號(hào)功能、關(guān)注及消息推送的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11

