MyBatis总结三:使用动态代理实现dao接口
由于我们上一篇实现MyBatis的增删改查的接口实现类的方法都是通过sqlsession调用方法,参数也都类似,所以我们使用动态代理的方式来完善这一点
MyBatis动态代理生成dao的步骤:
编写数据管理的接口 XxxMapper.java
编写接口对应的配置文件 XxxxMapper.xml
namespace必须 和 dao接口的全路径保持一致 (即物理路径的文件夹名称相同)
statement的id必须 和 dao接口的方法名保持一致
statement的resultType类型 必须 和方法返回值类型保持一致
通过 sqlSession.getMapper(类的字节码对象) 获取代理之后的Mapper实现类对象
首先我们在之前项目的基础上编写Mapper接口(代替Dao接口):
package com.zy.mapper;
import com.zy.domain.User;
import java.util.List;
public interface UserMapper {
/**
* 根据id查询用户信息
*/
public User getUserById(int id);
/**
* 查询所有用户信息
*/
public List<User> getUserList();
/**
* 添加用户信息
*/
public void addUser(User user);
/**
* 修改用户信息
*/
public void updateUser(User user);
/**
* 根据id删除用户信息
*/
public void deleteUser(int id);
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--加载外部属性-->
<properties resource="jdbc.properties"/> <!--起别名-->
<typeAliases>
<typeAlias type="com.zy.domain.User" alias="User"></typeAlias>
</typeAliases> <!--运行环境可以配置多个, default指定默认使用哪个-->
<environments default="development">
<!--配置环境, id是这个环境的唯一标识-->
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments> <!--3 指定所有的mapper文件-->
<mappers>
<!--如果只需要管理一个mapper 可以直接写如下方式 并且其物理路径不需要与其xml文件路径相同-->
<!--<mapper resource="UserMapper.xml"></mapper>-->
<!--我们如果需要统一管理所有的mapper xml 用这种方式 但是这种方式需要文件夹路径和其xml文件的name路径一致-->
<package name="com.zy.mapper" />
</mappers>
</configuration>
然后修改UserMapper.xml文件的物理路径以及内容:
由于我们mybatis-config里面映射器中使用的是package管理方式 所以mapper xml文件的物理路径需要跟其xml文件内的namespace值一致
所以把UserMapper.xml的位置改成如下:
这里需要注意一点 这个com.zy.mapper不是文件夹,是package,如果创建成普通文件夹的话,运行的时候会报 invalid bound statement (not found) 的错误

<?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">
<!--
定义所有用到的sql语句 和 映射关系
namespace : 当前这个配置文件的唯一标识, 自定义, 但是不能和其他配置文件namespace重复
-->
<mapper namespace="com.zy.mapper.UserMapper">
<!--
定义一条sql语句, 其实就是一个 statement
select 代表是查询语句, 与其类似的还有 insert, update, delete等
id : 这条sql语句的唯一标识,自定义,但是不能和其他sql语句重复
parameterType: sql语句需要的参数类型, 需要写 类的全路径
resultType: sql语句返回的结果类型
-->
<select id="getUserById" parameterType="int" resultType="com.zy.domain.User">
<!--这里写具体的sql语句, #{}是占位符, 编译时会被替换成?, 然后注入真实参数-->
select * from user where id=#{id}
</select>
<!--查询所有用户信息-->
<select id="getUserList" resultType="com.zy.domain.User">
select * from user
</select>
<!--添加用户信息-->
<insert id="addUser" parameterType="com.zy.domain.User">
insert into user (id,name,age) values (null,#{name},#{age})
</insert>
<!--修改用户信息-->
<update id="updateUser" parameterType="com.zy.domain.User">
update user set name=#{name}, age=#{age} where id=#{id}
</update>
<!--删除用户信息-->
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
</mapper>
然后进行单元测试(我们调用的时候 可以直接用接口调用方法执行sql语句了):
package com.zy.mapper; import com.zy.dao.UserDaoTest;
import com.zy.domain.User;
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 java.io.InputStream;
import java.util.List; import static org.junit.Assert.*; public class UserMapperTest {
UserMapper mapper;
@Before
public void setUp() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = UserDaoTest.class.getClassLoader().getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//使用反射
mapper = sqlSession.getMapper(UserMapper.class);
} @Test
public void getUserById() throws Exception {
User user = mapper.getUserById(1);
System.out.println(user);
} @Test
public void getUserList() throws Exception {
List<User> list = mapper.getUserList();
for (User user : list) {
System.out.println(user);
}
} @Test
public void addUser() throws Exception {
User user = new User();
user.setName("郭富城");
user.setAge(18);
mapper.addUser(user);
} @Test
public void updateUser() throws Exception {
//先查
User user = mapper.getUserById(2);
//后改
user.setName("黎明");
user.setAge(17);
mapper.updateUser(user);
} @Test
public void deleteUser() throws Exception {
mapper.deleteUser(2);
} }
MyBatis总结三:使用动态代理实现dao接口的更多相关文章
- 使用动态代理实现dao接口
使用动态代理实现dao接口的实现类 MyBatis允许只声明一个dao接口,而无需写dao实现类的方式实现数据库操作.前提是必须保证Mapper文件中的<mapper>标签的namespa ...
- MyBatis使用mapper动态代理实现DAO接口
工具: mysql 5.5.62 IDEA 参考自:https://www.cnblogs.com/best/p/5688040.html 遇到的问题: 无法读取src/main/java下配置文 ...
- Mybatis进阶学习笔记——动态代理方式开发Dao接口、Dao层(推荐第二种)
1.原始方法开发Dao Dao接口 package cn.sm1234.dao; import java.util.List; import cn.sm1234.domain.Customer; pu ...
- MyBatis使用Mapper动态代理开发Dao层
开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同原始Dao接口实现类方法. Mappe ...
- Mybatis框架基础入门(三)--Mapper动态代理方式开发
使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法. 原始Dao开发方法需要程序员编写Dao接口和Dao实现类,此方式开发Dao,存在以下问题: Dao方 ...
- mybatis 基础1(动态代理)
我目前使用的是mybatis 3.3.0版本. 可使用 1.xml文本, 2.dao类, 3.sqlSession.getMapper(Class<T> type), 生成sql类, 原理 ...
- Spring与MyBatis整合上_Mapper动态代理方式
将MyBatis与Spring进行整合,主要解决的问题就是将SqlSessionFactory对象交由Spring来管理..所以该整合,只需将SQLSessionFactory的对象生成器S ...
- MyBatis底层实现原理: 动态代理的运用
转载:https://mp.weixin.qq.com/s/_6nyhaWX15mh3mkj8Lb0Zw Mybatis中声明一个interface接口,没有编写任何实现类,Mybatis就能返回接口 ...
- MyBatis 源码分析——动态代理
MyBatis框架是如何去执行SQL语句?相信不只是你们,笔者也想要知道是如何进行的.相信有上一章的引导大家都知道SqlSession接口的作用.当然默认情况下还是使用DefaultSqlSessio ...
随机推荐
- R文件报错:cannot resolve symbol ‘R’
今天仿照别人项目,因为不太熟悉Androidstudio,所以就照着他项目结构走,结果包名跟他的不一样,项目一直报标题这个错误,网上百度了很多也没用,不过先把网上的解决方案copy一下 请注意 ① E ...
- 结合两张表person和address
Table: Person +-------------+---------+ | Column Name | Type | +-------------+---------+ | PersonId ...
- 2016-02-20WebForm登陆验证,判断用户是否登陆 PageBase类
http://blog.csdn.net/fanbin168/article/details/49404233 很多时候,WebFrom页面,我们需要判断用户是否已经登陆了.假如有很多页面,难道我们要 ...
- javascript给输入框赋值的一个误区
一. 错误的示范 如下代码所示,如果需要用javascript获取id为username1, password1的输入框的值,将其写入id为username2, password2的输入框,那么红线区 ...
- python中的list()函数和tuple()函数
tuple函数:将一个序列作为参数,并把它转化为元组,如果参数是元组,将会原样返回: >>> tuple([1,2,3]) (1, 2, 3) >>> tuple( ...
- 【VS2013编译DirectX Tutorials时遇到的错误】"const wchar_t *" 类型的实参与 "LPCSTR" 类型的形参不兼容
本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/3696367.html 通过查看LPCSTR的定义: typedef _Null_te ...
- (转) Android Service完全解析,关于服务你所需知道的一切(上)
相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的Android程序员如果连Service都没听说过的话,那确实也太逊了.Service作为Android四大组件之一,在每一个应用程序 ...
- hdoj-1285-确定比赛名次(拓扑排序)
题目链接 /* Name:hdoj-1285-确定比赛名次 Copyright: Author: Date: 2018/4/11 15:59:18 Description: 标准的拓扑排序模板题,注意 ...
- 网络爬虫必备知识之concurrent.futures库
就库的范围,个人认为网络爬虫必备库知识包括urllib.requests.re.BeautifulSoup.concurrent.futures,接下来将结对concurrent.futures库的使 ...
- ACM学习历程—HDU5696 区间的价值(分治 && RMQ && 线段树 && 动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但 ...