Mybatis: 接口編程的實現

實現基於接口編程的關鍵在於DAO是一個代理類, 所以DAO 不該該由用戶進行實例化, 應該由框架提供統一的工廠類用來獲取DAO. 工廠類中根據DAO類型生成對應的動態代理類返回用戶.sql

// Mapper工廠類(負責生成DAO的動態代理對象)
public class MapperFactory {

    // SQL會話工廠類
    private SqlSessionFactory sqlSessionFactory;

    // 經過SQL會話工廠類實例化
    public MapperFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    // 根據DAO類型獲取DAO的動態代理類
    public <T> T getMapper(Class<T> clazz) {
        SqlSession session = this.sqlSessionFactory.getSession();
        return new MapperProxy(session).getMapper(clazz);
    }
    
}
複製代碼

在獲取DAO時經過工廠類獲取, 此時獲取的是DAO的代理類.數據庫

UserDAO userDAO = new MapperFactory(sf).getMapper(UserDAO.class);
複製代碼

當調用DAO中的接口時, 會自動執行動態代理類中的invoke方法. 在invoke方法中執行數據庫操做便可.編程

// Mapper動態代理類
public class MapperProxy implements InvocationHandler {

    // SQL會話
    private SqlSession sqlSession;

    // 經過SQL會話實例化
    public MapperProxy(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    // 獲取動態代理類
    @SuppressWarnings("unchecked")
    public <T> T getMapper(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, this);
    }

    // 執行接口時進入該方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 接口中方法名稱和SQL節點ID相同
        String statementId = method.getName();
        // 根據方法名稱便可獲取對應的SQL節點信息
        MappedStatement ms = sqlSession.getConfig().getMappedStatement(statementId);

        if (ms == null) {
            throw new RuntimeException("無對應的SQL, id:" + statementId);
        }

        String type = ms.getStatementType();
        Object param = (args != null) ? args[0] : null;

        // 根據SQL類型執行對應的數據庫操做方法
        if ("insert".equals(type)) {
            return sqlSession.insert(statementId, param);
        } else if ("update".equals(type)) {
            return sqlSession.update(statementId, param);
        } else if ("delete".equals(type)) {
            return sqlSession.delete(statementId, param);
        } else if ("select".equals(type)) {
            return sqlSession.selectList(statementId, param);
        }

        return null;
    }

}
複製代碼

測試bash

public static void main(String[] args) {

        // 建立SQL會話工廠
        SqlSessionFactory sf = new SqlSessionFactoryBean("*_mapper.xml").build();
        MapperFactory factory = new MapperFactory(sf);

        // 經過工廠類獲取DAO
        UserDAO userDAO = factory.getMapper(UserDAO.class);

        // 調用DAO中方法
        int count = userDAO.insertUser(new User(1L, "zhangsan", 20, "sssss", "ok"));
        List<User> userList = userDAO.selectUser();

        // 輸出查詢結果
        System.out.println(count);

        for (User u : userList) {
            System.out.println("| " + u.getId() + " | " + u.getUname() + " | ");
        }

    }
複製代碼
相關文章
相關標籤/搜索