1.原始Dao开发方式

原始Dao开发方法需要程序员编写Dao接口和Dao实现类。
1.映射文件:(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获取用户信息 ,返回一条数据-->
<!-- 通过<select>进行数据库查询
id:标识映射文件中的sql
将sql语句封装到mappedStatement对象中,所以将id称为statement的id
parameterType:指定输入参数的类型
#{}:表示一个占位符
#{id}:其中的id表示接收输入的参数,参数的名称就是id,如果输入参数为简单类型,#{}中的参数名可以任意,可以value也可以其它名称。
resultType:指定sql输出结果的所映射的java对象类型。select指定resultType表示将单条记录映射成的java对象。-->
<select id="findUserById" parameterType="int" resultType="com.huihui.pojo.User">select * from user where id=#{id}
</select>
<!-- 自定义条件查询用户列表,可能返回多条 -->
<!--
${}:表示拼接sql串,将接收到的参数的内容不加任何修饰拼接到sql中。
使用${}拼接sql,可能引起sql注入
${value}:接收输入参数的内容,如果传入的类型是简单类型,${}中只能使用value-->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="com.huihui.pojo.User">select * from user where username like '%${value}%'
</select><!-- 添加用户 -->
<!--
parameterType:指定输入参数类型为pojo
#{}中指定pojo的属性名,接收到pojo对象的属性值-->
<insert id="insertUser" parameterType="com.huihui.pojo.User" >insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})<!-- selectKey将主键返回,需要再返回 --><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">select LAST_INSERT_ID()</selectKey>
</insert><!-- 删除用户 -->
<!-- 根据id删除用户,需要输入id值 -->
<delete id="deleteUser" parameterType="java.lang.Integer">delete from user where id = #{id}
</delete><!-- 更新用户 -->
<!-- 根据id更新用户,需要传入用户的id和用户的更新信息(也就是传入User对象,但是user对象中的id必须存在) -->
<update id="updateUser" parameterType="com.huihui.pojo.User">update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
</mapper>

2.Dao接口:

package com.huihui.dao;import java.util.List;import com.huihui.pojo.User;public interface UserDao {//根据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;}

3.Dao接口实现类:

package com.huihui.dao;import java.util.List;import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;import com.huihui.pojo.User;public class UserDaoImpl implements UserDao{//需要向dao实现类中注入SqlSessionFactory//这里通过构造方法注入private SqlSessionFactory sqlSessionFactory;public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}@Overridepublic User findUserById(int id) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();User user = sqlSession.selectOne("test.findUserById", id);//释放资源sqlSession.close();return user;}@Overridepublic void insertUser(User user) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();sqlSession.insert("test.insertUser", user);//提交事务sqlSession.commit();//释放资源sqlSession.close();}@Overridepublic void deleteUser(int id) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();sqlSession.delete("test.deleteUser", id);//提交事务sqlSession.commit();//释放资源sqlSession.close();}@Overridepublic List<User> findUserByName(String name) throws Exception {SqlSession sqlSession = sqlSessionFactory.openSession();sqlSession.selectList("test.findUserByUsername", name);//释放资源sqlSession.close();return null;}}

4.加载user.xml文件
修改SqlMapConfig.xml文件:

  <!-- 加载映射文件 --><mappers><mapper resource="sqlmap/user.xml"/></mappers>

5.测试代码:

public class UserDaoImplTest {private SqlSessionFactory sqlSessionFactory;@Before//此方法是运行下面的测试用例的方法之前执行的public void setUp() throws Exception{//创建sqlSessionFactory//mybatis配置文件路径String resource = "SqlMapConfig.xml";//得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//创建会话工厂,传入mybatis的配置文件信息sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testFindUserById() throws Exception{//创建一个userDao的对象UserDao userDao = new UserDaoImpl(sqlSessionFactory);//调用UserDao方法User user = userDao.findUserById(1);System.out.println(user);}@Testpublic void testFindUserByName() throws Exception{//创建一个userDao对象UserDao userDao = new UserDaoImpl(sqlSessionFactory);//调用UserDao方法List<User> list = userDao.findUserByName("张");System.out.println(list.size());}
}  

分析原始Dao开发方式存在的问题:

原始Dao开发中存在以下问题:

  1. Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
  2. 调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不利于开发维护。
  3. 调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。

2.mapper动态代理的方法

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

Mapper接口开发需要遵循以下规范:

  1. Mapper.xml文件中的namespace与mapper接口的类路径相同。
  2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
  4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

只有遵循以上规范,mybatis才可以自动生成mapper接口的实现类代理对象。
其实以上的规范主要为了相对于dao实现类中的以下方法进行了自动生成:

User user = sqlSession.selectOne("test.findUserById", id);sqlSession.insert("test.insertUser", user);sqlSession.delete("test.deleteUser", id);sqlSession.selectList("test.findUserByUsername", name);
...

1.映射文件(UserMapper.xml文件):
定义mapper映射文件UserMapper.xml(内容同User.xml一样),需要修改namespace的值为UserMapper接口路径。将UserMapper.xml放在classpath下mapper目录下。

<?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语句,后面会讲另一层非常重要的作用(需要修改namespace的值为UserMapper接口路径)。 -->
<mapper namespace="com.huihui.mapper.UserMapper"><!-- 根据Id获取用户信息 ,返回一条数据-->
<!-- 通过<select>进行数据库查询
id:标识映射文件中的sql
将sql语句封装到mappedStatement对象中,所以将id称为statement的id
parameterType:指定输入参数的类型
#{}:表示一个占位符
#{id}:其中的id表示接收输入的参数,参数的名称就是id,如果输入参数为简单类型,#{}中的参数名可以任意,可以value也可以其它名称。
resultType:指定sql输出结果的所映射的java对象类型。select指定resultType表示将单条记录映射成的java对象。-->
<select id="findUserById" parameterType="java.lang.Integer" resultType="com.huihui.pojo.User">select * from user where id=#{id}
</select>
<!-- 自定义条件查询用户列表,可能返回多条 -->
<!--
${}:表示拼接sql串,将接收到的参数的内容不加任何修饰拼接到sql中。
使用${}拼接sql,可能引起sql注入
${value}:接收输入参数的内容,如果传入的类型是简单类型,${}中只能使用value-->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="com.huihui.pojo.User">select * from user where username like '%${value}%'
</select><!-- 添加用户 -->
<!--
parameterType:指定输入参数类型为pojo
#{}中指定pojo的属性名,接收到pojo对象的属性值-->
<insert id="insertUser" parameterType="com.huihui.pojo.User" >insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})<!-- selectKey将主键返回,需要再返回 --><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">select LAST_INSERT_ID()</selectKey>
</insert><!-- 删除用户 -->
<!-- 根据id删除用户,需要输入id值 -->
<delete id="deleteUser" parameterType="java.lang.Integer">delete from user where id = #{id}
</delete><!-- 更新用户 -->
<!-- 根据id更新用户,需要传入用户的id和用户的更新信息(也就是传入User对象,但是user对象中的id必须存在) -->
<update id="updateUser" parameterType="com.huihui.pojo.User">update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
</mapper>

2.接口(UserMapper.java文件)
接口定义有如下特点:

  1. Mapper接口方法名和Mapper.xml中定义的statement的id相同
  2. Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
  3. Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
package com.huihui.mapper;import java.util.List;import com.huihui.pojo.User;/*** mapper接口,相当于dao接口* 用户管理* @author 62347**/
public interface UserMapper {//根据id查询用户信息public User findUserById(int id) throws Exception;//根据用户名列查询用户列表public List<User> findUserByUsername(String name) throws Exception;//添加用户信息public void insertUser(User user) throws Exception;//删除用户信息public void deleteUser(int id) throws Exception;}

3.加载UserMapper.xml文件

  <!-- 加载映射文件 --><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>

4.测试代码:

package com.huihui.mapper;import java.io.InputStream;
import java.util.Date;
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 com.huihui.pojo.User;public class UserMapperTest {private SqlSessionFactory sqlSessionFactory;@Before//此方法是运行下面的测试用例的方法之前执行的public void setUp() throws Exception{//创建sqlSessionFactory//mybatis配置文件路径String resource = "SqlMapConfig.xml";//得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);//创建会话工厂,传入mybatis的配置文件信息sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}@Testpublic void testFindUserById() throws Exception {//通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();//创建UserMapper对象,mybatis自动生成mapper代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = userMapper.findUserById(30);System.out.println(user);sqlSession.close();}@Testpublic void testFindUserByName() throws Exception {//通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();//创建UserMapper对象,mybatis自动生成mapper代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List<User> list = userMapper.findUserByUsername("张");System.out.println(list.size());sqlSession.close();}@Testpublic void testInsertUser() throws Exception {//通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();//创建UserMapper对象,mybatis自动生成mapper代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = new User();user.setSex("2");user.setBirthday(new Date());user.setAddress("北京丰台");user.setUsername("哒哒哒");userMapper.insertUser(user);sqlSession.commit();//提交事务sqlSession.close();}@Testpublic void testDeleteUser() throws Exception {//通过会话工厂得到会话SqlSession sqlSession = sqlSessionFactory.openSession();//创建UserMapper对象,mybatis自动生成mapper代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);userMapper.deleteUser(30);sqlSession.commit();//提交事务sqlSession.close();}}

重点说明:

  1. selectOne和selectList
    动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。
  2. mapper接口输入参数只能有一个,是否不利于系统扩展维护?
    系统框架中,dao层的代码是被业务层公用的。即使mapper接口中只有一个参数,也可以使用包装类型的pojo满足不同的业务方法的需求。
    注意:持久层中方法的参数可以是包装类型(eg:map,…..),但是service方法中不建议使用包装类型(原因:不利于业务层的可扩展)。

原始dao和Mapper动态代理的开放方式---Mybatis学习笔记(六)相关推荐

  1. Mybatis DAO开发--Mapper动态代理开发方式

    Mybatis DAO开发–Mapper动态代理开发方式 第一步:jar包 创建lib目录,引入相应的jar包,本节课用到的案例引入的jar包就是spring整合mybatis要用到的全部jar包. ...

  2. 【Mybatis学习笔记】Mapper动态代理四项原则和注意事项

    如果使用原始的DAO,要自己对其进行实现,而如果使用Mybatis的Mapper动态代理,就可以让Mybatis自动帮你实现DAO接口. Mapper动态代理的四项原则 1.接口方法名需要与Mappe ...

  3. MyBatis之Mapper动态代理开发

    MyBatis之Mapper动态代理开发 2017/9/30 1.SqlSession的使用范围 1.SqlSessionFactoryBuilder SqlSessionFactoryBuilder ...

  4. 【Java】Mybatis mapper动态代理方式

    前言 我们在使用Mybatis的时候,获取需要执行的SQL语句的时候,都是通过调用xml文件来获取,例如:User user = (User) sqlSession.selectOne("c ...

  5. Mybaits之Mapper动态代理开发

    Mybaits之Mapper动态代理开发 开发规范: Mapper接口开发方法只需要程序员与Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法 ...

  6. Spring 整合Mybatis Mapper动态代理方法

    先看项目目录结构 很清爽了 最重要的Spring的核心配置文件,看一下 <?xml version="1.0" encoding="UTF-8"?> ...

  7. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)--动态SQL 转载于:https://www.cnblogs.com/MrSaver/p/7453949.html

  8. 中国移动物联网开放平台OneNET学习笔记(1)——设备接入(MQTT协议)OneNET Studio篇

    一.平台简介 中国移动物联网开放平台(OneNET) 是中移物联网有限公司基于物联网技术和产业特点打造的开放平台和生态环境,适配各种网络环境和协议类型,支持各类传感器和智能硬件的快速接入和大数据服务, ...

  9. MyBatis DAO层开发——Mapper动态代理方式

    SqlMapConfig.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE conf ...

最新文章

  1. 转帖 javascript事件监听
  2. 所引用的程序集没有强命名解决方法
  3. 偷天换日——新型浏览器劫持木马“暗影鼠”分析
  4. Kafka源码深度解析-序列3 -Producer -Java NIO
  5. ssh 在远程主机执行本地脚本
  6. recyclerview 加载fragment_恢复 RecyclerView 的滚动位置
  7. Java语言实现hello world代码
  8. java自行车起源_自行车的起源
  9. php输出mysql查返回行_php-MySQL简单查询返回零行
  10. Vim命令大全(linux)
  11. linux redis玂家链接不上,Unicode编码的熟悉与研究过程(内附全部汉字编码列表)...
  12. 【软件测试之项目实战】
  13. 画fits图像上的极小值点
  14. 计算机科学基础 浙大学分,Zju生存指南-学(上)
  15. egret实现微信排行榜功能 (2018-8-20)
  16. 漫画趣解大数据算法建模:买瓜
  17. 一英国公司打造极速家庭宽带:每秒1G
  18. 【JavaWeb】Servlet系列——HttpServletRequest接口详解
  19. HDR视频的编码参数详解
  20. 计算机考研与就业的利弊分析,考研和就业怎么选择 考研和就业的利弊分析

热门文章

  1. 在node.js中如何使用ES6模块化
  2. webpack4.x版本与webpack-cli高版本之间存在的bug
  3. 计算机有什么知识,计算机基础知识有什么
  4. Vue2.0+vuex+H5实现音乐播放及歌曲切换功能的方法及原理解释
  5. PHP调用数据库数据乱码问题
  6. OpenStack、KVM、Docker——Docker之后还需要OpenStack吗?
  7. Photoshop扣除特定颜色背景
  8. Nginx综合介绍以及配置文件详解
  9. MFC ListCtrl和IP控件的使用杂记
  10. swift UI专项训练20 WebView浏览器