Mybatis开发dao的方法通常用两种,一种是传统DAO的方法,另一种是基于mapper代理的方法。

一、传统DAO方式开发

1、sql语句映射文件编写

User.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,做sql隔离 -->
<mapper namespace="test">
<!--
id:sql语句唯一标识
parameterType:指定传入参数类型(pojo类中对应的类型,不是数据库中的类型)
resultType:返回结果集类型
#{}:占位符,如果传入的类型是基本类型(string,long,double,int,boolean,float等),那么#{}中变量名称可以任意
-->
<select id="findUserById" parameterType="java.lang.Integer" resultType="cn.itheima.pojo.User">
SELECT * FROM user WHERE id=#{id}
</select> <!--
如果返回的结果为集合,resultType中也是配置为集合中泛型的类型,即resultType="cn.itheima.pojo.User"
${}:拼接符,如果传入的类型是基本类型(string,long,double,int,boolean,float等),那么${}中变量名称必须是value
-->
<select id="findUserByUserName" parameterType="java.lang.String" resultType="cn.itheima.pojo.User">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select> <!--
如果传入的是pojo类型,则#{}中变量名称必须是pojo中对应的属性.属性.属性......
如果要返回数据库自增主键,可以使用SELECT LAST_INSERT_ID()
-->
<insert id="insertUser" parameterType="cn.itheima.pojo.User">
<!-- 执行SELECT LAST_INSERT_ID()数据库函数,返回自增的主键
keyProperty:将返回的主键放入传入的参数的Id中保存(保存到user对象中的id属性)
order:当前函数相对于insert语句的执行顺序,在insert前执行用BEFORE,在insert后执行用AFTER
resultType:id的类型,也就是keyProperty中属性类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
</insert> <delete id="deleteUserById" parameterType="java.lang.Integer">
DELETE FROM user WHERE id=#{id}
</delete> <update id="updateUserById" parameterType="cn.itheima.pojo.User">
UPDATE user SET username=#{username} WHERE id=#{id}
</update>
</mapper>

2、配置User.xml映射信息

在Sqlconfig.xml文件中引入User.xml

<mappers>
<mapper resource="User.xml"/>
</mappers>

3、编写DAO接口和实现类

UserDAO.java

package cn.itheima.dao;

import java.util.List;

import cn.itheima.pojo.User;

public interface UserDAO {

    User findUserById(Integer id);

    List<User> findUserByUserName(String username);
}

UserDAOImpl.java

package cn.itheima.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import cn.itheima.pojo.User; public class UserDAOImpl implements UserDAO { private SqlSessionFactory sqlSessionFactory;
// 通过构造方法注入
public UserDAOImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(Integer id) {
// SqlSession是线程不安全的,所以最佳使用范围是方法里
SqlSession session = sqlSessionFactory.openSession();
User user = session.selectOne("test.findUserById", id);
return user;
}
@Override
public List<User> findUserByUserName(String username) {
SqlSession session = sqlSessionFactory.openSession();
List<User> userList = session.selectList("test.findUserByUserName", username);
return userList;
}
}

4、测试

package mybatis0523;

import java.io.InputStream;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import cn.itheima.dao.UserDAO;
import cn.itheima.dao.UserDAOImpl;
import cn.itheima.pojo.User; public class UserDAOTest { private SqlSessionFactory sqlSessionFactory; // 在测试方法前执行的方法
@Before
public void setUp() throws Exception {
String resource = "sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} @Test
public void testFindUserById() throws Exception {
// 将初始化好的sqlSessionFactory注入到实现类中
UserDAO userDAO = new UserDAOImpl(sqlSessionFactory);
User user = userDAO.findUserById(1);
System.out.println(user);
} @Test
public void testFindUserByUserName() throws Exception {
UserDAO userDAO = new UserDAOImpl(sqlSessionFactory);
List<User> userList = userDAO.findUserByUserName("王");
System.out.println(userList);
}
}

二、Mapper代理方式开发

1、实现原理

Mapper接口开发方法只需要编写Mapper接口(实际上相当于DAO接口)然后由Mybatis根据接口定义创建接口的动态代理对象。换句话说也就是不用自己编写DAO接口的实现类了。

2、Map接口编写规则

(1)映射文件中的namespace要等于接口的全路径
(2)映射文件中的sql语句id要等于接口的方法名称
(3)映射文件中传入参数类型要等于接口方法中传入参数的类型
(4)映射文件中返回结果集类型要等于接口方法的返回值类型

3、编写Mapper接口(相当与传统的DAO接口)

package cn.itheima.mapper;

import java.util.List;

import cn.itheima.pojo.User;

public interface UserMapper {

    User findUserById(Integer id);

    List<User> findUserByUserName(String username);

    void insertUser(User user);

    void updateUserById(User user);
}

4、编写映射文件

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper接口代理实现编写规则:
1、映射文件中的namespace要等于接口的全路径
2、映射文件中的sql语句id要等于接口的方法名称
3、映射文件中传入参数类型要等于接口方法中传入参数的类型
4、映射文件中返回结果集类型要等于接口方法的返回值类型
-->
<mapper namespace="cn.itheima.mapper.UserMapper">
<!--
id:sql语句唯一标识
parameterType:指定传入参数类型(pojo类中对应的类型,不是数据库中的类型)
resultType:返回结果集类型
#{}:占位符,如果传入的类型是基本类型(string,long,double,int,boolean,float等),那么#{}中变量名称可以任意
-->
<select id="findUserById" parameterType="java.lang.Integer" resultType="cn.itheima.pojo.User">
SELECT * FROM user WHERE id=#{id}
</select> <!--
如果返回的结果为集合,resultType中也是配置为集合中泛型的类型,即resultType="cn.itheima.pojo.User"
${}:拼接符,如果传入的类型是基本类型(string,long,double,int,boolean,float等),那么${}中变量名称必须是value
-->
<select id="findUserByUserName" parameterType="java.lang.String" resultType="cn.itheima.pojo.User">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select> <!--
如果传入的是pojo类型,则#{}中变量名称必须是pojo中对应的属性.属性.属性......
如果要返回数据库自增主键,可以使用SELECT LAST_INSERT_ID()
-->
<insert id="insertUser" parameterType="cn.itheima.pojo.User">
<!-- 执行SELECT LAST_INSERT_ID()数据库函数,返回自增的主键
keyProperty:将返回的主键放入传入的参数的Id中保存(保存到user对象中的id属性)
order:当前函数相对于insert语句的执行顺序,在insert前执行用BEFORE,在insert后执行用AFTER
resultType:id的类型,也就是keyProperty中属性类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})
</insert> <delete id="deleteUserById" parameterType="java.lang.Integer">
DELETE FROM user WHERE id=#{id}
</delete> <update id="updateUserById" parameterType="cn.itheima.pojo.User">
UPDATE user SET username=#{username} WHERE id=#{id}
</update>
</mapper>

5、配置UserMapper.xml映射信息

在SqlConfig.xml中引入

<mappers>
<!--
使用class属性引入接口的全路径名称:
使用规则:
1、接口的名称和映射文件名称要完全一致
2、接口和映射文件要放在同一个目录下
-->
<mapper class="cn.itheima.mapper.UserMapper"/>
</mappers>

6、测试

package mybatis0523;

import java.io.InputStream;
import java.util.List; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import cn.itheima.mapper.UserMapper;
import cn.itheima.pojo.User; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; // 在测试方法前执行的方法
@Before
public void setUp() throws Exception {
String resource = "sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} @Test
public void testFindUserById() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
} @Test
public void testFindUserByUserName() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> userList = userMapper.findUserByUserName("王");
System.out.println(userList);
} }

三、总结

原始DAO开发存在一些问题:

1、存在一定量的模板代码。比如:通过SqlSessionFactory创建SqlSession;调用SqlSession的方法操作数据库;关闭Sqlsession。

2、存在一些硬编码。调用SqlSession的方法操作数据库时,需要指定statement的id,这里存在了硬编码。

Mapper代理的开发方式,只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。

要实现mapper代理的开发方式,需要遵循一些开发规范:

1、mapper接口的全限定名要和mapper映射文件的namespace的值相同。

2、mapper接口的方法名称要和mapper映射文件中的statement的id相同。

3、mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。

4、  mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致。

通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:

1、 模板代码已经去掉。

2、 剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。

Mybatis中原生DAO实现和Mapper动态代理实现的更多相关文章

  1. MyBatis开发Dao的原始Dao开发和Mapper动态代理开发

    目录 咳咳...初学者看文字(Mapper接口开发四个规范)属实有点费劲,博主我就废了点劲做了如下图,方便理解: 原始Dao开发方式 1. 编写映射文件 3.编写Dao实现类 4.编写Dao测试 Ma ...

  2. 【mybatis深度历险系列】深入浅出mybatis中原始dao的开发和mapper代理开发

    使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法.mybatis在进行dao开发的时候,涉及到三姐妹,分别是SqlSessionFactoryBuilder ...

  3. Mybatis框架基础入门(三)--Mapper动态代理方式开发

    使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法. 原始Dao开发方法需要程序员编写Dao接口和Dao实现类,此方式开发Dao,存在以下问题: Dao方 ...

  4. 8.Mapper动态代理

    在前面例子中自定义 Dao 接口实现类时发现一个问题:Dao 的实现类其实并没有干什么 实质性的工作, 它仅仅就是通过 SqlSession 的相关 API 定位到映射文件 mapper 中相应 id ...

  5. Mybatis框架三:DAO层开发、Mapper动态代理开发

    这里是最基本的搭建:http://www.cnblogs.com/xuyiqing/p/8600888.html 接下来做到了简单的增删改查:http://www.cnblogs.com/xuyiqi ...

  6. MyBatis开发Dao层的两种方式(Mapper动态代理方式)

    MyBatis开发原始Dao层请阅读我的上一篇博客:MyBatis开发Dao层的两种方式(原始Dao层开发) 接上一篇博客继续介绍MyBatis开发Dao层的第二种方式:Mapper动态代理方式 Ma ...

  7. MyBatis使用Mapper动态代理开发Dao层

    开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同原始Dao接口实现类方法. Mappe ...

  8. 02.MyBatis在DAO层开发使用的Mapper动态代理方式

    在实际开发中,Mybatis作用于DAO层,那么Service层该如何调用Mybatis Mybatis鼓励使用Mapper动态代理的方式 Mapper接口开发方法只需要程序员编写Mapper接口(相 ...

  9. Mybatis之旅第二篇-Mapper动态代理方式

    一.引言 通过上一篇mybatis的入门学习,我们已经会使用mybatis实现简单的增删改查,但是我们也发现了用原始Dao开发的一些问题: Dao方法体存在重复代码:通过SqlSessionFacto ...

随机推荐

  1. SQLServer创建约束

    --创建数据库create database studentson primary(    name=stu_data,    filename='f:\SQL\stu_data.mdf',    s ...

  2. SpringCloud升级之路2020.0.x版-40. spock 单元测试封装的 WebClient(下)

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们继续上一节,继续使用 spock 测试我们自己封装的 WebClient 测试针对 r ...

  3. 5、使用ZSetOperations(有序)操作redis(Zset有序集合)

    文章来源:https://www.cnblogs.com/shiguotao-com/p/10564454.html 方法 c参数 s说明   void set(K key, V value); ke ...

  4. C/C++ Qt 自定义Dialog对话框组件应用

    在上一篇博文 <C/C++ Qt 标准Dialog对话框组件应用> 中我给大家演示了如何使用Qt中内置的标准对话框组件实现基本的数据输入功能. 但有时候我们需要一次性修改多个数据,使用默认 ...

  5. java8两个字段进行排序问题

    //这个解决问题 Comparator<Anjianxinxi> getLianriqi = Comparator.comparing(Anjianxinxi::getLianriqi). ...

  6. springboot增加多端口管理

    目标是这样的: 方法 方法还是比较简单的1.点击菜单栏:Views -> Tool Windows -> Services:中文对应:视图 -> 工具窗口 -> 服务:快捷键是 ...

  7. javascript-初级-day02-this关键字

    day01-获取元素的第二种方法 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-T ...

  8. 一个 Linux 后台程序编程案例分析

    Linux 下的一个进程打开一个日志文件,不定期地往该文件里写入日志.此时可以在控制台使用 mv 命令给该日志文件改个名字或者用 rm 命令把这个日志文件删除掉.Linux 下是允许这么干的!对于改日 ...

  9. 8.3 k8s部署jenkins,通过pv/pvc结合NFS服务器持久化

    1.制作jenkins docker镜像 1.1 下载jenkins wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war-stable/2.30 ...

  10. 使用 CSS 轻松实现一些高频出现的奇形怪状按钮

    背景 在群里会有同学问相关的问题,怎么样使用 CSS 实现一个内切角按钮呢.怎么样实现一个带箭头的按钮呢? 本文基于一些高频出现在设计稿中的,使用 CSS 实现稍微有点难度和技巧性的按钮,讲解使用 C ...