mybatis--原始dao和代理Mapper

来源:互联网 发布:vb能做到人脸识别吗 编辑:程序博客网 时间:2024/05/23 11:35

上一篇博客我们讲了对于mybatis的增删改,但是我们看上篇的博客,几乎每一个方法都会出现创建工厂,创建会话,关闭绘画,关闭事务等操作。那么今天我们就来封装一下,用接口实现一下mybatis的增删改查。

原始dao

原始的dao,我们需要dao接口和dao的实现类,代码如下:

dao接口

/** * 用户管理 * @author mengh * */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;}

dao实现类

public class UserDaoImpl implements UserDao {    //需要向dao实现类注入SqlSessionFactory    //这里通过构造函数注入    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();    }

User.xml

<mapper namespace="test">    <!-- 在映射文件中配置很多的sql -->    <!-- 需求: 通过id,查询数据库的记录 -->    <!-- 通过select执行数据库查询    id:表示映射文件的sql,称为statement的id    将来sql语句会封装到mappedstate的对象中    #{}表示一个占位符     parameterType="" 指定输入的类型,这里指定int     #{id}:其中的id标志输入的参数,参数的名称就是id,如果输入的参数是简单类型,#{}中的参数名称可以是任意类型     resultType="" 置顶输出查询的结果的所映射的java对象,这里select置顶resultType表示将单条记录所映射的java对象     -->    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">        SELECT * FROM USER WHERE ID=#{id}    </select>    <!-- 根据用户名模糊查询用户信息,可能返回多条记录        resultType:指定的就是单挑记录锁映射的java对象类型        ${}表示拼接字符串,将接收的内容,不加任何修饰的凭借到sql中        使用${}凭借sql,会引起sql注入         ${}:接受输入的内容,如果传入的是简单类型,${}只能使用value     -->    <select id="findUserByName" parameterType="String" resultType="cn.itcast.mybatis.po.User">        SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'    </select>    <!-- 添加用户        parameterType:指定输入的参数类型(包括用户信息)        #{}中指定pojo的属性名,接受到pojo对象的属性值        mybatis也是通过OGNL来获取属性的值     -->    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" ><!--        select LAST_INSERT_ID() :得到刚刚在insert进去记录的主键值,值适用于自增列 --><!--        keyProperty:将查询到的主键值设置到parameterType置顶的对象的哪个属性 --><!--        order="AFTER":select LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序 --><!--        resultType:指定结果的类型 -->        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">            select LAST_INSERT_ID()        </selectKey>        insert into User(username,birthday,sex,address) value (#{username},#{birthday},#{sex},#{address})    </insert>    <!-- 删除用户     根据id删除信息     -->    <delete id="deleteUser" parameterType="java.lang.Integer">        delete from user where id=#{id}    </delete>    <!-- 更新用户        需要用户的id和用户信息        #{id}:从传入的user实体中获取对应属性的值     -->    <update id="updateUser" parameterType="cn.itcast.mybatis.po.User">        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}  where id=#{id}    </update></mapper>

客户端

    @Override    public void deleteUser(int id) throws Exception {        SqlSession sqlSession = sqlSessionFactory.openSession();        sqlSession.delete("test.deleteUser", id);        sqlSession.commit();        sqlSession.close();    }

原声dao缺点

这样我们的做法就写好了,当然这只是传统的做法,虽然比上一篇博客每次都要去实现一下工厂好多了,但是还是有很多的缺点,如下:
1.存在大量的重复代码,可以提取出来,也就是用模板方法。
2.调用sqlSession方法时,将statement硬编码了
3.调用sqlSession方法的时候,由于Session方法使用泛型,即变量类型传入错误,在编译阶段也不报错,不利于发现错误。

Mapper代理

针对上边的不足,mybatis做了一些相应的政策,就是我们说的mapper代理,而且针对mybatis的代理,我们还需要在mapper.xml和接口上加一些规范。
1.在mapper.xml中namespace中编写Mapper接口的地址

<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

2.mapper.java接口中的方法名称和mapper.xml总的statement的id一直
3.接口中的方法的输入参数类型和mapper.xml中的statement的parameterType的类型一直
4.mapper.java中的返回值的类型和映射文件中的resultType的类型一致
以上开发规范总要对下边的代码统一的

<!-- 改进前 --><mapper namespace="cn.itcast.mybatis.mapper.UserMapper"><!-- 改进后 --><mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

改进以后就是我们的mapper.xml,代码如下:

UserMapper.xml

<!-- 命名空间,作用:对sql进行分类话的管理,sql的隔离     注意,如果使用mapper代理开发,他代表mapper接口的地址--><mapper namespace="cn.itcast.mybatis.mapper.UserMapper">    <!-- 在映射文件中配置很多的sql -->    <!-- 需求: 通过id,查询数据库的记录 -->    <!-- 通过select执行数据库查询    id:表示映射文件的sql,称为statement的id    将来sql语句会封装到mappedstate的对象中 -->    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">        SELECT * FROM USER WHERE ID=#{id}    </select>    <select id="findUserByName" parameterType="String" resultType="cn.itcast.mybatis.po.User">        SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'    </select>    <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" >        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">            select LAST_INSERT_ID()        </selectKey>        insert into User(username,birthday,sex,address) value (#{username},#{birthday},#{sex},#{address})    </insert>    <!-- 删除用户     根据id删除信息     -->    <delete id="deleteUser" parameterType="java.lang.Integer">        delete from user where id=#{id}    </delete>    <!-- 更新用户        需要用户的id和用户信息        #{id}:从传入的user实体中获取对应属性的值     -->    <update id="updateUser" parameterType="cn.itcast.mybatis.po.User">        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}  where id=#{id}    </update>

Mapper接口

//根据id查询用户    public User findUserById(int id) throws Exception;    //根据用户名查询用户信息    public List<User> findUserByName(String name) throws Exception;//      public void insertUser(User user) throws Exception;//      public void deleteUser(int id) throws Exception;

你以为这样写就完了吗,确实完了,哈哈。而且这样写的好处就是我们不用写实现类,mapper代理会根据我们的statement来选择到底调用什么方法,例如我们的是Insert,那么他就会调用insert。

客户端

@Test    public void test() throws Exception {        SqlSession sqlSession = sqlSessionFactory.openSession();        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        User user = userMapper.findUserById(1);        System.out.println(user);    }

SqlSession

Sqlsession对应着一次数据库会话。由于数据库回话不是永久的,因此Sqlsession的生命周期也不应该是永久的,相反,在你每次访问数据库时都需要创建它(当然并不是说在Sqlsession里只能执行一次sql,你可以执行多次,当一旦关闭了Sqlsession就需要重新创建它)。创建Sqlsession的地方只有一个,那就是SqlsessionFactory的openSession方法。

注意:

这里我们有的方法是查询一个用户,当然也有可能查询出来的是多个用户,没关系,如果我们这个方法查询出来的是多个实体,那么mybaits会自动让让我们的代理类实现selectList()方法,且返回值是List,如果是返回单个实体,则返回User。

小结

针对原始的jdbc和传统的dao的实现,mybaits还是做了非常大的优化的,他让我们真正的面向接口来编程,让我们的代码量减少,让我们的工作能更好的运用在业务上,还真是做到了全心全意为人民服务。

0 0