mybatis--原始dao和代理Mapper
2016-03-06 09:25
351 查看
上一篇博客我们讲了对于mybatis的增删改,但是我们看上篇的博客,几乎每一个方法都会出现创建工厂,创建会话,关闭绘画,关闭事务等操作。那么今天我们就来封装一下,用接口实现一下mybatis的增删改查。
1.存在大量的重复代码,可以提取出来,也就是用模板方法。
2.调用sqlSession方法时,将statement硬编码了
3.调用sqlSession方法的时候,由于Session方法使用泛型,即变量类型传入错误,在编译阶段也不报错,不利于发现错误。
1.在mapper.xml中namespace中编写Mapper接口的地址
2.mapper.java接口中的方法名称和mapper.xml总的statement的id一直
3.接口中的方法的输入参数类型和mapper.xml中的statement的parameterType的类型一直
4.mapper.java中的返回值的类型和映射文件中的resultType的类型一致
以上开发规范总要对下边的代码统一的
改进以后就是我们的mapper.xml,代码如下:
你以为这样写就完了吗,确实完了,哈哈。而且这样写的好处就是我们不用写实现类,mapper代理会根据我们的statement来选择到底调用什么方法,例如我们的是Insert,那么他就会调用insert。
原始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还是做了非常大的优化的,他让我们真正的面向接口来编程,让我们的代码量减少,让我们的工作能更好的运用在业务上,还真是做到了全心全意为人民服务。相关文章推荐
- 深入浅析mybatis oracle BLOB类型字段保存与读取
- MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法
- oracle+mybatis 使用动态Sql当插入字段不确定的情况下实现批量insert
- MyBatis学习笔记(二)之关联关系
- 浅析Mybatis 在CS程序中的应用
- Java Mybatis框架入门基础教程
- Java简单实现SpringMVC+MyBatis分页插件
- MyBatis批量添加、修改和删除
- MyBatis与Hibernate的比较
- 浅析mybatis和spring整合的实现过程
- mybatis的动态sql详解(精)
- Mybatis实现增删改查及分页查询的方法
- MyBatis入门学习教程(一)-MyBatis快速入门
- Spring与Mybatis的整合方法有哪些
- 详解MyBatis直接执行SQL查询及数据批量插入
- 解决springmvc+mybatis+mysql中文乱码问题
- Spring3.1.1+MyBatis3.1.1的增、删、查、改以及分页和事务管理
- Spring+Mybatis+Mysql搭建分布式数据库访问框架的方法
- Mybatis实战教程之入门到精通(经典)
- Mybatis与Hibernate的区别