Mapper动态代理开发方式
实现原理:
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象。
Mapper接口开发需要遵循以下规范:
1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同。
3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同。
4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。
一、定义UserMapper.xml映射文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 7 注意:使用mapper代理方法开发,namespace有特殊重要的作用 8 namespace为其接口地址 另外接口中的方法名要和配置文件中的statement id一致 方法中形参类型也要和parametertype一致 9 返回值类型也要与配置文件中resultType指定的类型一致 遵循该规范 mybatis可以自动生成mapper接口的实现类代理对象 --> 10 <mapper namespace="cn.itcast.mybatis.mapper.UserMapper"> 11 12 <!-- 定义sql片段 id:sql片段的唯 一标识 经验:是基于单表来定义sql片段,这样话这个sql片段可重用性才高 在sql片段中不要包括 13 where --> 14 <sql id="query_user_where"> 15 <if test="userCustom!=null"> 16 <if test="userCustom.sex!=null and userCustom.sex!=''"> 17 and user.sex = #{userCustom.sex} 18 </if> 19 <if test="userCustom.username!=null and userCustom.username!=''"> 20 and user.username LIKE '%${userCustom.username}%' 21 </if> 22 <!-- <if test="ids!=null"> 使用 foreach遍历传入ids collection:指定输入 对象中集合属性 item:每个遍历生成对象中 23 open:开始遍历时拼接的串 close:结束遍历时拼接的串 separator:遍历的两个对象中需要拼接的串 使用实现下边的sql拼接: AND 24 (id=1 OR id=10 OR id=16) <foreach collection="ids" item="user_id" open="AND 25 (" close=")" separator="or"> 每个遍历需要拼接的串 id=#{user_id} </foreach> 实现 “ and 26 id IN(1,10,16)”拼接 <foreach collection="ids" item="user_id" open="and id IN(" 27 close=")" separator=","> 每个遍历需要拼接的串 #{user_id} </foreach> </if> --> 28 </if> 29 </sql> 30 31 32 <!-- 定义resultMap 将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系 33 type:resultMap最终映射的java对象类型,可以使用别名 id:对resultMap的唯一标识 --> 34 <resultMap type="user" id="userResultMap"> 35 <!-- id表示查询结果集中唯一标识 column:查询出来的列名 property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系 36 (对应关系) --> 37 <id column="id_" property="id" /> 38 <!-- result:对普通名映射定义 column:查询出来的列名 property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系 39 (对应关系) --> 40 <result column="username_" property="username" /> 41 42 </resultMap> 43 44 <select id="findUserByIdResultMap" parameterType="int" 45 resultMap="userResultMap"> 46 select id id_ ,username username_ from user where id=#{id} 47 </select> 48 49 <!-- 在 映射文件中配置很多sql语句 --> 50 <!-- 需求:通过id查询用户表的记录 --> 51 <!-- 通过 select执行数据库查询 id:标识 映射文件中的 sql 将sql语句封装到mappedStatement对象中,所以将id称为statement的id 52 parameterType:指定输入 参数的类型,这里指定int型 #{}表示一个占位符号 #{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 53 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称 resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。 --> 54 <select id="findUserById" parameterType="int" resultType="user"> 55 select 56 * from user where id=#{id} 57 </select> 58 59 <!-- 用户信息综合查询 #{userCustom.sex}:取出pojo包装对象中性别值 ${userCustom.username}:取出pojo包装对象中用户名称 --> 60 <select id="findUserList" 61 parameterType="cn.itcast.mybatis.po.UserQueryVo" 62 resultType="cn.itcast.mybatis.po.UserCustom"> 63 SELECT * FROM USER 64 <!-- where可以自动去掉条件中的第一个and --> 65 <where> 66 <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前边加namespace --> 67 <include refid="query_user_where"></include> 68 <!-- 在这里还可以引用其它的sql片段 --> 69 </where> 70 </select> 71 72 <!-- 根据用户名称模糊查询用户信息,可能返回多条 resultType:指定就是单条记录所映射的java对象 类型 ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。 73 使用${}拼接sql,引起 sql注入 ${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value --> 74 <select id="findUserByName" parameterType="java.lang.String" 75 resultType="user"> 76 select * from user where username like '%${value}%' 77 </select> 78 <!-- 添加用户 parameterType:指定输入 参数类型是pojo(包括 用户信息) #{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值 --> 79 <insert id="insertUser" 80 parameterType="cn.itcast.mybatis.po.User"> 81 <!-- 将插入数据的主键返回,返回到user对象中 SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键 82 keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性 order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序 83 resultType:指定SELECT LAST_INSERT_ID()的结果类型 --> 84 <selectKey keyProperty="id" order="AFTER" 85 resultType="java.lang.Integer"> 86 SELECT LAST_INSERT_ID() 87 </selectKey> 88 insert into user(username,birthday,sex,address) 89 value(#{username},#{birthday},#{sex},#{address}) 90 </insert> 91 92 <delete id="deleteUser" parameterType="int"> 93 delete from user where 94 id=#{id} 95 </delete> 96 97 <update id="updateUser" parameterType="user"> 98 update user set 99 username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} 100 where id = #{id} 101 </update> 102 </mapper>
二、定义UserMapper.java接口文件
1 package cn.itcast.mybatis.mapper; 2 3 import java.util.List; 4 5 import cn.itcast.mybatis.po.User; 6 import cn.itcast.mybatis.po.UserCustom; 7 import cn.itcast.mybatis.po.UserQueryVo; 8 9 public interface UserMapper { 10 //用户信息的高级查询 11 public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception; 12 // 根据id查询用户信息 13 public User findUserById(int id) throws Exception; 14 15 // 根据id查询用户信息,使用resultMap输出 16 public User findUserByIdResultMap(int id) throws Exception; 17 18 // 根据用户名列查询用户列表 19 public List<User> findUserByName(String name) throws Exception; 20 21 // 插入用户 22 public void insertUser(User user) throws Exception; 23 24 // 删除用户 25 public void deleteUser(int id) throws Exception; 26 }
接口定义有如下特点:
1、 Mapper接口方法名和Mapper.xml中定义的statement的id相同
2、 Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
3、 Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
三、在SqlMapConfig.xml文件中加载映射文件
1 <!-- 加载映射文件 --> 2 <mappers> 3 <mapper resource="mapper/UserMapper.xml"/> 4 </mappers>
四、程序测试
1 package cn.itcast.mybatis.first; 2 3 import java.io.InputStream; 4 import java.util.List; 5 6 import org.apache.ibatis.io.Resources; 7 import org.apache.ibatis.session.SqlSession; 8 import org.apache.ibatis.session.SqlSessionFactory; 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 10 11 import cn.itcast.mybatis.mapper.UserMapper; 12 import cn.itcast.mybatis.po.User; 13 import cn.itcast.mybatis.po.UserCustom; 14 import cn.itcast.mybatis.po.UserQueryVo; 15 16 public class MybatisFirst2 { 17 public static void main(String[] args) throws Exception { 18 // mybatis配置文件 19 String resource = "sqlMapConfig.xml"; 20 // 得到配置文件流 21 InputStream inputStream = Resources.getResourceAsStream(resource); 22 // 创建会话工厂,传入mybatis文件的配置信息 23 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 24 // 通过工厂得到Sqlsession 25 SqlSession session = sqlSessionFactory.openSession(); 26 27 28 UserMapper userMapper = session.getMapper(UserMapper.class); 29 // User user = userMapper.findUserByIdResultMap(25); 30 UserQueryVo userQueryVo = new UserQueryVo(); 31 UserCustom userCustom = new UserCustom(); 32 userCustom.setSex("1"); 33 // userCustom.setUsername("三"); 34 userQueryVo.setUserCustom(userCustom); 35 List<UserCustom> userList = userMapper.findUserList(userQueryVo); 36 session.commit(); 37 // 释放资源 38 session.close(); 39 System.out.println(userList); 40 41 } 42 }
tips:mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。