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. Exploring Matrix

    import java.util.Scanner; public class J714 { /** * @taking input from user */ public static void ma ...

  2. 多线程合集(一)---信号量,锁,以及并发编程,自定义任务调度和awaiter

    引言 在后端开发中,多线程技术总是后端开发中常用到的技术,那什么是多线程呢,在操作系统中,程序运行的最小单位是进程,那线程则是进程里面的最小单位,关系是一对多的关系,而线程的调度,是由操作系统的时间片 ...

  3. [bzoj4557]侦察守卫

    令g[i][j]表示覆盖了i的子树中距离i大于等于j的所有点,f[i][j]表示覆盖了i的子树和子树外距离i小于等于j的所有点,有递推式$f[i][j]=min(f[i][j]+g[son][j],f ...

  4. IDEA生成doc文档-生成chm文档

    首先,打开IDEA,并找到Tools -> Generate JavaDoc- 可供查询的chm比那些HTML页面好看多了. 如果您用过JDK API的chm文档,那么您一定不会拒绝接受其它第三 ...

  5. vue文件引入

    <template> <div class="hello"> <h1>{{ msg }}</h1> <!-- <h1&g ...

  6. CF1477A Nezzar and Board

    考虑 \(2x - y\) 我们改为 \(x + (x - y)\) 是一个更好的形式. 我们可以表示一个数为\(x_i + \sum_{j,k}(x_j - x_k) = K\) 我们考虑移到 \( ...

  7. 洛谷 P6860 - 象棋与马(找性质+杜教筛)

    题面传送门 首先我们来探究一下什么样的 \((a,b)\) 满足 \(p(a,b)=1\).不难发现只要点 \((1,0)\) 能够到达,那么网格上所有点都能到达,因为由于 \((1,0)\) 能够到 ...

  8. 【比较基因组】McScan jcvi比较两个基因组共线性细节记录

    目录 软件的安装 基因组的准备 一些细节 建议和示例 软件的安装 Python版McScan(jcvi工具包):https://github.com/tanghaibao/jcvi 以前只有pytho ...

  9. 富集分析DAVID、Metascape、Enrichr、ClueGO

    前言 一般我们挑出一堆感兴趣的基因想临时看看它们的功能,需要做个富集分析.虽然公司买了最新版的数据库,如KEGG,但在集群跑下来嫌麻烦.这时网页在线或者本地化工具派上用场了. DAVID DAVID地 ...

  10. Python time&datetime模块

    1.time&datetime模块 time&datetime是时间模块,常用以处理时间相关问题 time.time() #返回当前时间的时间戳timestamp time.sleep ...