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


说明: 本文大部分内容都是跟随者传播智课的教学视频学习而来,可以看做是翻译文章,只是自己吸收之后又书写一遍,加深自己的知识理解。

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