mybatis学习之原始开发DAO与mapper代理开发DAO的区别

本文介绍了MyBatis中原始DAO开发与Mapper代理开发的区别。在原始开发方式下,开发者需要编写DAO接口和实现类,存在模板代码重复和SQLID硬编码等问题。而Mapper代理方式则简化了这一过程,只需定义接口,通过映射文件与XML配置实现SQL操作。文章详细阐述了Mapper代理的配置和使用,并讨论了相关问题,如方法参数限制等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、SqlSession使用的范围

1.1 SqlSessionFactoryBuilder

通过 SqlSessionFactoryBuilder创建会话工厂 SqlSessionFactory
SqlSessionFactoryBuilder当成一个 工具类来使用,不需要使用单例模式管理 SqlSessionFactoryBuilder。
在需要创建 SqlSessionFactory时,只需要 new一次 SqlSessionFactoryBuilder即可

1.2 SqlSessionFactory

通过 SQLSessionFactory创建 SqlSession,可以使用单例模式进行管理 SqlSessionFactory(一旦创建,一直使用一个实例)

将来和spring整合后,使用单例模式进行管理 SqlSessionFactory

1.3SqlSession

SqlSession是一个面向用户(开发者)的接口
SqlSession中提供了很多操作数据库的方法:selectOne(返回单个),selectList(返回单个或多个).等。。
SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法),还有数据域的属性
SqlSession最佳的应用场合在方法体内,定义成局部变量使用

2、原始开发DAO的方法(需要开发者编写DAO接口类和DAO实现类)

2.1思路

开发者需要编写DAO接口类和DAO实现类
需要向DAO实现类中注入 SqlSessionFactory,在方法体内通过 SQLSessionFactory创建 SQLSession

2.2 DAO接口类

新建包dao,新建接口类UserDao,代码如下:
public interface UserDao {
    //根据ID查询用户的信息
    public User findUserById(int id) throws Exception;

    //添加用户
    public void insertUser(User user) throws Exception; 

    //删除用户
    public void deleteUser(int id) throws Exception;
}

2.3 DAO实现类

新建实现类UserDaoImpl,代码如下:
public class UserDaoImpl  implements UserDao{
    @Override
    public User findUserById(int id) throws Exception {
        return null;
    }

    @Override
    public void insertUser(User user) throws Exception {

    }

    @Override
    public void deleteUser(int id) throws Exception {

    }
}
因为这里需要向DAO实现类中注入 SqlSessionFactory,这里没有跟spring进行整合,所以使用构造函数的方法来进行注入
    private SqlSessionFactory sqlSessionFactory;
    public UserDaoImpl (SqlSessionFactory sqlSessionFactory){
        this.sqlSessionFactory = sqlSessionFactory;
    }

将三个方法实现操作编写完成
    @Override
    public User findUserById(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById",id);
        //释放资源
        sqlSession.close();
        return user;
    }
    
    @Override
    public void insertUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行插入操作
        sqlSession.insert("test.insertUser",user);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }

    @Override
    public void deleteUser(int id) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行删除操作
        sqlSession.delete("test.deleteUser",id);
        //提交事务
        sqlSession.commit();
        //释放资源
        sqlSession.close();
    }
可以看到在此处还是有很多重复操作的地方,虽然很简便,但是仍有代码冗余。

2.4 原始DAO的开发问题

  1. DAO的方法实现类存在大量的模板方法,设想能否将这些代码提取出来,大大减轻开发者的工作量
  2. 调用SQLSession方法时,将statement的ID硬编码了
  3. 调用SQLSession方法时,由于SQLSession方法使用泛型,即使传入变量的类型是错误的,在编译阶段不会报错,不利于开发者开发。

3、mapper代理的方法(开发者只需要编写mapper接口(相当于DAO接口))

3.1 思路(mapper代理开发规范)

开发者需要编写mapper.xml映射文件类
开发者需要mapper接口 需要遵循一些 开发的规范,mybatis可以自动生成mapper实现类的代理对象
开发规范:
1、在mapper.xml中,namespace 等于 mapper 接口的地址
2、在mapper.java接口中的方法名和mapper.xml中statement的id一致
3、mapper接口中,方法的输入参数类型和mapper.xml中的statement的parameterType一致
4、mapper接口中,方法的返回值类型和mapper.xml中statement的resultType一致

3.2 映射文件UserMapper.xml的配置

<mapper namespace="mapper.UserMapper">
    <!-- 在映射文件中配置很多sql语句 -->
    <!--
    需求:通过id查询用户数据
    -->
    <!--
    通过select来执行数据库的查询操作
    ID:标识映射文件中的sql,成为statementid
    将sql语句封装到mappedStatement对象中
    parameterType: 指定输入参数的类型,这里指定为int型
    #{}表示一个占位符
    #{id},其中的id表示接受输入的参数,参数名称为id
    resultType : 指定sql输出结果所映射的java对象类型,这里select指定resultType表示单条记录所映射成的java对象
    -->
    <select id="findUserById" parameterType="int" resultType="pojo.User">
        SELECT * FROM USER WHERE id = #{id}
    </select>
</mapper>

3.3 mapper接口类UserMapper.java的配置

    //根据ID查询用户的信息
    public User findUserById(int id) throws Exception;

    //添加用户
    public void insertUser(User user) throws Exception;

    //更新用户
    public void updateUser(User user) throws Exception;

    //删除用户
    public void deleteUser(int id) throws Exception;


3.4 在 SqlMapConfig.xml中添加 映射文件UserMapper.xml

	<mapper resource="mapper/UserMapper.xml"></mapper>

3.5总结

以上开发规范,主要就是对下面的代码进行统一的生成:
User user = sqlSession.selectOne("test.findUserById",id);
sqlSession.insert("test.insertUser",user);
sqlSession.delete("test.deleteUser",id);等

3.6测试

使用juint单元测试进行测试,代码如下:
public class test extends TestCase {
    private SqlSessionFactory sqlSessionFactory;
    @Before
    public void setUp() throws Exception{
        //mybatis配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建会话工厂,传入mybatis的配置信息
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testFindUserByid() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //创建一个UserMapper的对象,mybatis自动生成mapper代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用UserMapper的方法
        User user = userMapper.findUserById(1);
        System.out.println(user);
    }
}
得到结果:
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1263877414.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4b553d26]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id = ? 
DEBUG [main] - ==> Parameters: 28(Integer)
DEBUG [main] - <==      Total: 1
User{id=28, username='fjnmbb124', sex='1', birthday=Mon Jun 19 00:00:00 CST 2017, address='湖南长沙'}

Process finished with exit code 0

3.7一些问题的总结

3.7.1 代理对象内部调用selectOne或者selectList
如果mapper方法返回单个的pojo对象(非集合对象),代理对象就会调用selectOne来查询数据库
如果mapper方法返回多个的pojo对象(集合对象),代理对象就会调用selectList来查询数据库
3.7.2 mapper接口方法参数只能有一个,是否影响系统开发
mapper接口方法输入参数只能有一个,是否会不利于开发者扩展维护?
系统框架中,DAO层中的代码,一定是被业务层共用的代码
即使mapper接口中 只有一个参数,可以使用 包装类型的pojo(pojo包pojo,,实现万能参数)来满足不同的业务方法的需求、
注意:持久层方法的参数可以用包装类型、map等,但在services方法中建议不要使用包装类型 (不利于业务层的可扩展性)。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值