mybatis入門基礎(二)----原始dao的開發和mapper代理開發

阿赫瓦里發表於2015-06-28

  承接上一篇 mybatis入門基礎(一)

  看過上一篇的朋友,肯定可以看出,裡面的MybatisService中存在大量的重複程式碼,看起來不是很清楚,但第一次那樣寫,是為了解mybatis的執行步驟,先苦後甜嘛!

一:原始dao開發方法

  概要:1.在上篇中搭建好的框價中編寫dao介面和dao實現類

     2.向dao介面實現類中注入SqlSessionFactory,在方法體內通過SqlSessionFactory建立sqlSession.

  • DAO介面類UserDAO.java  
package com.mybatis.dao;
import java.util.List;
import com.mybatis.entity.User;
/**
 * 
 * @ClassName: UserDAO
 * @Description: TODO(使用者管理DAO介面)
 * @author warcaft
 * @date 2015-6-27 下午10:23:42
 * 
 */
public interface UserDAO {
    /** 根據ID查詢使用者資訊*/
    public User findUserById(Integer id);

    /**根據使用者名稱稱模糊查詢使用者資訊*/
    public List<User>  findUserByName(String username);

    /** 新增使用者*/
    public void insertUser(User user);

    /** 根據ID刪除使用者*/
    public void deleteUser(Integer id);

    /** 根據ID更新使用者*/
    public void updateUser(User user);
}
  • dao實現類UserDaoImpl.java 
package com.mybatis.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.mybatis.entity.User;
/**
 * 
 * @ClassName: UserDaoImpl
 * @Description: TODO(使用者管理介面的實現類)
 * @author warcaft
 * @date 2015-6-27 下午10:29:35
 * 
 */
public class UserDaoImpl implements UserDAO {
    private SqlSessionFactory sqlSessionFactory;
    // 需要向dao實現類中注入SqlSessionFactory
    // 通過構造方法注入
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User findUserById(Integer id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", id);
        // 釋放資源
        sqlSession.close();
        return user;
    }

    @Override
    public List<User> findUserByName(String username) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession
                .selectList("test.findUserByName", username);

        // 提交事務
        sqlSession.commit();
        // 釋放資源
        sqlSession.close();
        return list;
    }

    @Override
    public void insertUser(User user) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 執行插入操作
        sqlSession.insert("test.insertUser", user);
        // 提交事務
        sqlSession.commit();
        // 釋放資源
        sqlSession.close();
    }

    @Override
    public void deleteUser(Integer id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 執行插入操作
        sqlSession.delete("test.deleteUser", id);
        // 提交事務
        sqlSession.commit();
        // 釋放資源
        sqlSession.close();
    }

    @Override
    public void updateUser(User user) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 執行插入操作
        sqlSession.update("test.updateUser", user);
        // 提交事務
        sqlSession.commit();
        // 釋放資源
        sqlSession.close();
    }

}
  • JunitTest測試UserDaoImplTest.java
package com.mybatis.dao.test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import com.mybatis.dao.UserDaoImpl;
import com.mybatis.entity.User;

public class UserDaoImplTest {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void setUp() throws Exception {
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void findUserByIdTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        User user = userDao.findUserById(1);
        System.out.println(user);
    }

    @Test
    public void findUserByNameTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        List<User> list = userDao.findUserByName("小");
        System.out.println(list);
    }

    @Test
    public void insertUserTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        User user = new User();
        user.setUsername("張三丰");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("武當山");
        userDao.insertUser(user);
    }

    @Test
    public void deleteUserTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        userDao.deleteUser(8);
    }

    @Test
    public void updateUserTest() {
        UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory);
        User user = new User();
        user.setId(1);
        user.setUsername("王六");
        user.setSex("2");
        user.setAddress("天津");
        user.setBirthday(new Date());
        userDao.updateUser(user);
    }
}

才上面的程式碼可以看出,比起之前那個MybatisService.java類裡面的內容稍微清晰了點吧。但依然存在以下幾個問題:

  1.dao介面中存在大量模版方法,能否把這些程式碼提出來,減少我們的工作量

  2.呼叫sqlSession方法時將statement的id硬編碼了

  3.呼叫sqlSession傳入的變數,由於sqlSession方法使用泛型,即使變數型別傳入錯誤,在編譯階段也不報錯,不利於程式開發。

所以我們帶著這幾個問題看看mapper代理開發的方法,是否能解決這些問題呢?

二:mapper代理方法(只需要mapper介面,相當於dao介面)

1.概要:(1).編寫XXXmapper.xml的對映檔案

    (2).編寫mapper介面需要遵循一些開發規範,mybatis可以自動生成mapper介面實現類代理物件。

2.開發規範:

  (1).在XXXmapper.xml中namespace等於mapper介面地址;

  

      (2).XXXmapper.java介面中的方法和mapper.xml中的statement的Id一致。

  (3).mapper.java介面中的方法輸入引數和mapper.xml中statement的parameterType指定的型別一致。

  (4).mapper.java介面中的方法的返回值型別和mapper.xml中statement的resultType指定的型別一致。

  

  

小結:以上的開發規範主要是對下面的程式碼進行統一生成 

    SqlSession sqlSession = sqlSessionFactory.openSession();
    User user = sqlSession.selectOne("test.findUserById", id);
  ......

3.UserMapper.java類程式碼

package com.mybatis.mapper;

import java.util.List;

import com.mybatis.entity.User;

/**
 * 
 * @ClassName: UserDAO
 * @Description: TODO(使用者管理mapper介面)
 * @author warcaft
 * @date 2015-6-27 下午10:23:42
 * 
 */
public interface UserMapper {
    /** 根據ID查詢使用者資訊 */
    public User findUserById(int id);

    /** 根據使用者名稱稱模糊查詢使用者資訊 */
    public List<User> findUserByName(String username);

    /** 新增使用者 */
    public void insertUser(User user);

    /** 根據ID刪除使用者 */
    public void deleteUser(Integer id);

    /** 根據ID更新使用者 */
    public void updateUser(User user);

}
View Code

4.將原來的User.xml拷貝修改名稱為UserMapper.xml,只需修改此行程式碼即可

<!-- namespace名稱空間,作用就是對sql進行分類化的管理,理解為sql隔離
    注意:使用mapper代理開發時,namespace有特殊作用,namespace等於mapper介面地址
 -->
<mapper namespace="com.mybatis.mapper.UserMapper">

5.在SqlMapConfig.xml中載入UserMapper.xml

<!-- 載入對映檔案 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>

6.Junit測試UserMapperTest.java

package com.mybatis.dao.test;

import java.io.InputStream;
import java.util.Date;
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.Before;
import org.junit.Test;

import com.mybatis.entity.User;
import com.mybatis.mapper.UserMapper;

public class UserMapperTest {

    private SqlSessionFactory sqlSessionFactory;

    // 此方法是在執行findUserByIdTest之前執行
    @Before
    public void setUp() throws Exception {
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 建立SqlSessionFcatory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testFindUserById() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Usermapper物件,mybatis自動生成mapper代理物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(1);
        System.out.println(user);
        sqlSession.close();
    }

    @Test
    public void testFindUserByName() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Usermapper物件,mybatis自動生成mapper代理物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = mapper.findUserByName("小");
        System.out.println(list);
        sqlSession.close();
    }

    @Test
    public void testDeleteUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Usermapper物件,mybatis自動生成mapper代理物件
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUser(6);
        sqlSession.commit();
        sqlSession.close();
    }
    
    @Test
    public void testInsertUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Usermapper物件,mybatis自動生成mapper代理物件
        User user = new User();
        user.setUsername("者別");
        user.setSex("1");
        user.setAddress("蒙古乞顏部落");
        user.setBirthday(new Date());
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.insertUser(user);
        sqlSession.commit();
        sqlSession.close();
    }
    
    @Test
    public void testUpdateUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 建立Usermapper物件,mybatis自動生成mapper代理物件
        User user = new User();
        user.setId(11);//必須設定Id
        user.setUsername("神箭手者別");
        user.setSex("1");
        user.setAddress("蒙古乞顏部落");
        user.setBirthday(new Date());
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser(user);
        sqlSession.commit();
        sqlSession.close();
    }

}
View Code

7.小結

  (1).代理物件內部呼叫selectOne()和selectList():如果mapper物件返回單個pojo物件(非集合物件)代理物件內部通過selectOne查詢資料庫,如果mapper方法返回集合物件,代理物件內部通過selectList查詢資料庫。

  (2).mapper介面中的方法引數只能有一個是否影響系統開發:

  mapper介面方法引數只能有一個,系統是否不利於維護?

  回答:系統框架中,dao層的程式碼是被業務層公用的。機試mapper介面只有一個引數,可以使用包裝型別的pojo滿足不同的業務方法的需求。

 

相關文章