DAO(Data Access Object,資料通路對象),主要的功能是用于進行資料操作的,在程式的标準開發架構中屬于資料層的操作。
資料開發結構:
資源層是資料庫的操作層,裡面可以進行各種資料庫的存儲,但是這些資料存儲的時候肯定是依靠SQL語句,資料層通過一個專門的資料庫元件完成對資料庫的操作
業務層是整個項目的核心
DAO組成
DatabaseConnection:專門負責資料庫打開與關閉操作的類
VO:主要由屬性,setter, getter方法組成,VO類中的屬性與表中的字段相對應,每一個VO類的對象都表示表中的每一條記錄;
DAO:主要定義操作的接口,定義一系列資料庫的原子性操作,例如增删改查等;
Impl: DAO接口的真實實作類,主要完成具體資料庫操作,但不負責資料庫的打開和關閉;
Proxy:代理實作類,主要完成資料庫的打開和關閉并且調用真實實作類對象的操作;
Factory: 工廠類,通過工廠類取得一個DAO的執行個體化對象。
對于包的命名:
在使用DAO時對包有嚴格的命名
資料庫連接配接: xxx.dbc.DatabaseConnection
DAO接口: xxx.dao.IXxxDAO
DAO接口真實實作類:xxx.dao.impl.XxxDAOImpl
DAO接口代理實作類:xxx.dao.proxy.XxxDAOProxy
VO類: xxx.vo.Xxx, VO命名要與表的命名一緻
工廠類:xxx.factory.DAOFactory.
實施DAO模式 (Implementing DAO pattern)
使用上述元件,讓我們嘗試實作DAO模式。 我們将在這裡使用3個元件:
1.從一層轉移到另一層的book模型。
2.bookdao接口提供了靈活的設計和要實作的API。
3.BookDaoImpl具體類,它是bookdao接口的實作
DAO模式的優勢
使用DAO模式有很多優點。 讓我們在這裡聲明其中一些:
在更改持久性機制時,服務層甚至不必知道資料來自何處。 例如,如果您正在考慮從使用MySQL過渡到MongoDB,則所有更改僅需要在DAO層中完成。
DAO模式強調應用程式不同元件之間的低耦合。 是以,View層不依賴于DAO層,而僅Service層依賴于DAO層,即使依賴于接口,也不依賴于具體的實作。
由于持久性邏輯是完全獨立的,是以為單個元件編寫單元測試要容易得多。 例如,如果将JUnit和Mockito用于測試架構,則可以輕松模拟應用程式的各個元件。
當我們以DAO模式使用接口時,它還強調了“使用接口代替實作”的風格,這是一種出色的OOPs程式設計風格。
什麼情況下産生模式
當我們的業務和資料都要處理的時候,但是業務和資料都是不同的實作方式,但是它們之間又有聯系,是以這裡就産生了解耦概念。單獨封裝一個類來處理資料的代碼
當處理業務和資料的代碼在一起的時候,會出現以下情況:
1.維護困難因為每該一次資料都會影響業務代碼。
2.代碼複用比較低
3.編寫業務層代碼的人員必須要懂各種資料儲存方式
MyBatis開發Dao模式過程
Mybatis架構根據接口定義建立接口的動态代理對象,代理對象的方法體同上邊Dao接口實作類方法。
使用mapper代理的方法來開發dao時,程式員隻需要幹兩件事即可:
1、編寫mapper.xml映射檔案 2、編寫mapper接口(相當于dao接口)
Mapper接口開發需要遵循以下四個規範(建議初學者結合下圖了解): 1、Mapper.xml檔案中的namespace與mapper接口的類路徑相同。 2、Mapper接口方法名和Mapper.xml中定義的每個statement的id相同 3、Mapper接口方法的輸入參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同 4、Mapper接口方法的輸出參數類型和mapper.xml中定義的每個sql的resultType的類型相同
Mapper接口開發四個規範屬實有點費勁,我就在掘金上廢了點勁找到了圖,友善了解:
原始Dao開發方式
原始Dao開發方法需要程式員編寫Dao接口和Dao實作類。
-
編寫映射檔案
編寫映射檔案如下:(也可以使用入門程式完成的映射檔案)
<?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">;
<!-- namespace:命名空間,用于隔離sql,還有一個很重要的作用,後面會講 -->
<mapper namespace="test">
<!-- 根據id查詢使用者 -->
<select id="queryUserById" parameterType="int"
resultType="com.gx.mybatis.pojo.User">
select * from user where id = #{id}
</select>
<!-- 根據username模糊查詢使用者 -->
<select id="queryUserByUsername" parameterType="string"
select * from user where username like '%${value}%'
<!-- 儲存使用者 -->
<insert id="saveUser" parameterType="com.gx.mybatis.pojo.User">
<selectKey keyProperty="id" keyColumn="id" order="AFTER"
resultType="int">
SELECT 1576193
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
-
編寫Dao接口
先進行DAO的接口開發,編碼如下:
public interface UserDao {
/**
- 根據id查詢使用者
- @param id
-
@return
*/
User queryUserById(int id);
- 根據使用者名模糊查詢使用者
- @param username
List<User> queryUserByUsername(String username);
- 儲存使用者
- @param user
void saveUser(User user);
}
3.編寫Dao實作類
編寫的Dao實作類如下
public class UserDaoImpl implements UserDao {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super();
this.sqlSessionFactory = sqlSessionFactory;
@Override
public User queryUserById(int id) {
// 建立SqlSession
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 執行查詢邏輯
User user = sqlSession.selectOne("queryUserById", id);
// 釋放資源
sqlSession.close();
return user;
public List<User> queryUserByUsername(String username) {
List<User> list = sqlSession.selectList("queryUserByUsername", username);
return list;
public void saveUser(User user) {
// 執行儲存邏輯
sqlSession.insert("saveUser", user);
// 送出事務
sqlSession.commit();
4.編寫Dao測試
建立一個JUnit的測試類,對UserDao進行測試(充當main方法),測試代碼如下:
public class UserDaoTest {
@Before
public void init() throws Exception {
// 建立SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 加載SqlMapConfig.xml配置檔案
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 建立SqlsessionFactory
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
@Test
public void testQueryUserById() {
// 建立DAO
UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
// 執行查詢
User user = userDao.queryUserById(1);
System.out.println(user);
public void testQueryUserByUsername() {
List<User> list = userDao.queryUserByUsername("五");
for (User user : list) {
public void testSaveUser() {
// 建立儲存對象
User user = new User();
user.setUsername("孫尚香腸");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("蜀國");
// 執行儲存
userDao.saveUser(user);
Mapper動态代理方式
1.定義Mapper.xml(映射檔案)
定義mapper映射檔案UserMapper.xml 将UserMapper.xml放在config下mapper目錄下,效果如下:
2、編寫UserMapper.xml配置檔案内容:
<!-- namespace:命名空間,用于隔離sql -->
<!-- 還有一個很重要的作用,使用動态代理開發DAO,1. namespace必須和Mapper接口類路徑一緻 -->
<mapper namespace="com.gx.mybatis.mapper.UserMapper">
<!-- 根據使用者id查詢使用者 -->
<!-- 2. id必須和Mapper接口方法名一緻 -->
<!-- 3. parameterType必須和接口方法參數類型一緻 -->
<!-- 4. resultType必須和接口方法傳回值類型一緻 -->
<!-- 根據使用者名查詢使用者 -->
select 1576193
insert into user(username,birthday,sex,address) values
(#{username},#{birthday},#{sex},#{address});
3.編寫UserMapper(接口檔案)
建立UserMapper接口代碼如下:
public interface UserMapper {
- 根據id查詢
- 根據使用者名查詢使用者
4.加載UserMapper.xml檔案
修改SqlMapConfig.xml檔案,添加以下所示的内容:
<!-- 加載映射檔案 -->
<mappers>
<mapper resource="sqlmap/User.xml" />
<mapper resource="mapper/UserMapper.xml" />
</mappers>
5.編寫測試
編寫的測試方法如下:
public class UserMapperTest {
// 擷取sqlSession,和spring整合後由spring管理
// 從sqlSession中擷取Mapper接口的代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 執行查詢方法
User user = userMapper.queryUserById(1);
// 和spring整合後由spring管理
List<User> list = userMapper.queryUserByUsername("五");
user.setUsername("劉備胎");
user.setSex("2");
user.setAddress("鼠國");
userMapper.saveUser(user);