mybatis 利用DAO 與利用 mapper代理 進行開發

mybatis 利用DAO 與利用 mapper代理 進行開發

mybatis 利用DAO開發的一般步驟

思路:程序員需要寫dao接口和dao實現類。
需要向dao實現類中注入SqlSessionFactory,在方法體內通過SqlSessionFactory創建SqlSession

  1. 配置SqlMapConfig 與 User.xml
  2. 定義操作接口及其實現類
  3. 外部調用

對user表進行操作的接口

public interface UserOperation {
    User queryUserById(int id);
    List<User> queryUserByName(String name);
    void insertUser();
    void deleteUser();
    void modifyUser();
}

接口的實現類

public class UserOperatorImpl implements UserOperation {
    //需要持有一個sqlSessionFactory,以用來方便在每一個方法內產生sqlSession
    private SqlSessionFactory sqlSessionFactory;
    public UserOperatorImpl(SqlSessionFactory sqlSessionFactory){
        this.sqlSessionFactory = sqlSessionFactory;
    }
    @Override
    public User queryUserById(int id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("queryUserById",id);
        sqlSession.close();
        return user;

    }
    @Override
    public List<User> queryUserByName(String name) {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    List<User> users = sqlSession.selectList("queryUserByName", "王五");
    sqlSession.close();
    return users;
}
  }

外部調用

public class MybatisDaoTest {
    private static SqlSessionFactory sqlSessionFactory = null;

    // 單例模式管理sqlSessionFactory,雙重檢鎖法
    public static SqlSessionFactory getSqlSessionFactory() {
        if (sqlSessionFactory == null) {
            synchronized (MybatisDaoTest.class) {
                if (sqlSessionFactory == null) {
                    try {
                        String resource = "SqlmapConfig.xml";

                        // 得到配置文件流
                        InputStream inputStream = null;
                        inputStream = Resources.getResourceAsStream(resource);

                        // 創建會話工廠,傳入mybatis的配置文件信息
                        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                                .build(inputStream);

                        return sqlSessionFactory;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        return sqlSessionFactory;
    }

    @Test
    public void queryUserById() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        UserOperation userOperation = new UserOperatorImpl(sqlSessionFactory);
        User user = userOperation.queryUserById(1);
        System.out.println(user.getUsername());
    }
    @Test
    public void queryUserByName() throws IOException {
    SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    UserOperation userOperation = new UserOperatorImpl(sqlSessionFactory);
    List<User> users = userOperation.queryUserByName("王五");
    for (int i = 0; i < users.size(); i++){
        System.out.println(users.get(i).getUsername());
    }

}
}

那麼從上面代碼看,原生的DAO的開發方式有什麼缺點呢

  1. dao接口實現類UserOperatorImpl, 其各個實現方法中存在大量模板方法,(比如獲取sqlSession,關閉sqlSession),設想能否將這些代碼提取出來,大大減輕程序員的工作量。
  2. 調用sqlsession方法時將statement的id(即SQL語句的唯一標識)硬編碼了,比如selectOne方法中的第一個參數(”test.queryUserById”)硬編碼,
  3. 調用sqlsession方法時傳入的變量,比如selectOne方法中的參數,第一個爲sql的id,第二個參數爲Object 類型,由於sqlsession方法使用泛型,即使變量類型傳入錯誤(比如 int 值寫成 String值),在編譯階段也不報錯,不利於程序員開發。

使用mapper代理進行開發

程序員只需要使用mapper接口,並不需要接口的具體實現就可以實現對數據庫表的增刪查改

當程序員遵循一定的開發規範,則mybatis可以自動生成mapper接口實現類代理對象,將配置好的mapper.xml文件加載到SqlMapConfig中即可

開發規範如下
1. 在mapper.xml中namespace等於mapper接口地址,即接口類的reference

// mapper中的配置
<mapper namespace="com.dustin.mapper.UserMapper">
    <!--通過id 查詢用戶信息-->
    <select id="queryUserById" parameterType="int" resultType="com.dustin.dao.User">
        select * from user where id = #{id}
    </select>
    <select id="queryUserByName" parameterType="java.lang.String" resultType="com.dustin.dao.User">
    select * from User where username like '%${value}%'
</select>
</mapper>
// UserMapper 中的方法
public interface UserMapper {
    User queryUserById(int id);
    List<User> queryUserByName(String name);
  }
  1. id 要等於接口類UserMapper 中的方法名 即 queryUserById 就是接口類中的一個方法
  2. parameterType 要等於接口類中方法的參數類型
  3. resultType 要等於接口類中的方法的返回類型

如何調用?

// 獲取一個sqlSession
SqlSession sqlSession = getSqlSessionFactory().openSession();
// 生成一個mapper代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.queryUserById(1);

疑惑
1. 傳入的參數類型是否只能是一個?
yes,接口只有一個參數,但是可以使用包裝類型的pojo滿足不同的業務方法的需求
2. 返回值是單個對象還是List是怎樣判斷的?內部是如何知道是使用selectOne 還是selectList的?
其實是動態代理+反射, 通過看定義的方法返回的是單個對象還是一個List來判定到底是使用selectOne 還是selectList


說明: 本文大部分內容都是跟隨者傳播智課的教學視頻學習而來,可以看做是翻譯文章,只是自己吸收之後又書寫一遍,加深自己的知識理解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章