mapper代理:

1.在mapper.xml中namespace等于mapper接口地址

<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
      注意:使用mapper代理方法开发 namespace有特殊重要作用,namespace等于mapper接口 地址-->

<mapper namespace="cn.xbq.mybatis.mapper.UserMapper">

2.mapper.java接口中的方法名和mapper.xml中statement的id一致

3 - .mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定类型一致

4.mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定类型一致。

<select id="findUserById" parameterType="int" resultType="cn.xbq.po.User">
</select>

//根据id查询用户信息
public User findUserById(int id) throws Exception;

5.总结:

以上开发规范主要是对下边的代码进行统一生成:
           User user = sqlSession.selectOne("test.findUserById",id);
           sqlSession.insert("test.insertUser",user);
           …………

6.测试:

记得加载mapper.xml

@Test
public void testFindUserById() throws Exception {
   SqlSession sqlSession = sqlSessionFactory.openSession();
   //创建UserMapper对象,mybatis自动生成mapper代理对象
   UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
   //调用userMapper的方法
   User user = userMapper.findUserById(1);
   System.out.println(user);
}

整个的接口:

public interface UserMapper {
   //根据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;  
}

7.代理对象内部调用selectOne或selectList

如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。
如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库

8.mapper接口方法参数只能有一个是否影响系统开发

mapper接口方法参数只能有一个,系统是否不利于扩展维护
系统框架中,dao层的代码是被业务层公用的。
即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
注意:持久层方法的参数可以包装类型,map…,service方法中建议不要使用包装类型(不利于业务层的可扩展)

9.sqlMapConfig.xml

mybatis的全局配置文件sqlMapConfig.xml,配置如下:
           properties(属性)
           setting(全局配置参数)
           typeAliases(类型别名)
           typeHandlers(类型处理器)
           objectFactory(对象工厂)
           plugins(插件)
           environments(环境集合属性对象)
           environment(环境子属性对象)
           transactionManager(事务管理)
           dataSource(数据源)
           mappers(映射器)

10.properties属性:

需求:
将数据库连接参数单独配置在db.properties中,只需要在sqlMapConfig.xml中加载db.properties的属性值。
在sqlMapConfig.xml中就不需要对数据库连接参数硬编码。
将数据库连接参数只配置在db.properties中,原因:方便对参数进行统一管理,其他xml可以引用该db.properties。

<!-- 
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis
jdbc.username = root
jdbc.password = 123456
-->

<!-- 加载属性文件-->
<properties resource="db.properties"></properties>

在sqlMapConfig.xml加载属性文件:

<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC"/>

<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
   <property name="driver" value="${jdbc.driver}">
   <property name="url" value="${jdbc.url}">
   <property name="username" value="${jdbc.username}">
   <property name="password" value="${jdbc.password}">
</dataSource>

properties特性:
注意:mybatis将按照下面的顺序来加载属性:
在properties元素体内定义的属性首先被读取
然后会读取properties元素中resource或URL加载的属性,他会覆盖已读取的同名属性
最后读取parameterType传递的属性,他会覆盖已读取的同名属性
因此:
通过parameterType传递的属性具有最高优先级,resource或URL加载的属性次之,
最低优先级的是properties元素体内定义的属性。

<!-- 加载属性文件-->
<properties resource="db.properties">
   <!-- properties中还可以配置一些属性名和属性值-->
   <!-- <property name="jdbc.driver" value="" />-->
</properties>

建议:
不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。
在properties文件中定义属性名要有一定的特殊性,如:xxx.xxx.xxx
setting全局参数配置:
mybatis框架在运行时可以调整一些运行参数。
比如:开启二级缓存、开启延迟加载…..
全局参数将会影响mybatis的运行行为
typeAliases(别名)重点
1.需求:
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型,需要resultType指定输出结果的映射类型。
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
2.mybatis默认支持别名:
3.单个别名定义:

<!-- 别名定义-->
<typeAliases>
  <!-- 针对单个别名定义
  type:类型的路径
  alias:别名
  -->
  <typeAlias type="cn.xbq.mybatis.po.User" alias="User" />
</typeAliases>

引用别名:

<select id="findUserById" parameterType="int" resultType="user">
   select * from user where id=#{value}
</select>

批量别名的定义(常用):

<!-- 批量别名定义
指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大写或小写)
-->
<package name="cn.xbq.mybatis.po" />

typeHandlers(类型处理器)
mybatis中通过typeHandlers完成jdbc类型和Java类型的转换
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义。
mappers(映射配置)
1.通过resource加载单个映射文件

<!-- 通过resource方法一次加载一个映射文件-->
<mapper resource="mapper/UserMapper.xml" />

2.通过mapper接口来加载

<!-- 通过mapper接口加载映射文件
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名保持一致,且在一个目录中上边的规范的前提是:使用的是mapper代理方法
 -->
 <mapper class="cn.xbq.mybatis.mapper.UserMapper" />

按照上面的规范,将mapper.java和mapper.xml放在一个目录,且同名:

<!-- 
cn.xbq.mybatis.mapper
  UserMapper.java
  UserMapper.xml 
-->

3.批量加载mapper(推荐使用):

<!-- 批量加载mapper
指定mapper接口的包名,mybatis自动扫描包下边所有的mapper接口进行加载
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
上边规范的前提是:使用的是mapper代理方法
-->
<package name="cn.xbq.mybatis.mapper" />

11.输入映射

通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型
1.传递pojo的包装对象
1.1:需求:
完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其他信息,比如商品、订单的)
1.2:定义包装类型pojo:
针对上边需求,建议使用自定义的包装类型的pojo
在包装类型的pojo中将复杂的查询条件包装进去。

public class UserQueryVo {
   //在这里包装所需要的查询条件
   //用户查询条件
   private UserCustom userCustom;
   public UserCustom getUserCustom() {
      return userCustom;
   }
   public void setUserCustom(UserCustom userCustom) {
      this.userCustom = userCustom;
   }
}

1.3 mapper.xml

<!-- 用户信息查询
 #{userCustom.sex}:取出pojo包装对象中性别值
 ${userCustom.username}:取出pojo包装对象中用户名称
 -->
 <select id="findUserList" parameterType="cn.xbq.mybatis.po.UserQueryVo" resultType="cn.xbq.mybatis.po.UserCustom">
 select * from user where user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'
 </select>

1.4 mapper.java

//用户信息综合查询
public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;

@Test
public void testFindUserList() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //创建UserMapper对象,mybatis自动生成mapper对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //创建包装对象,设置查询条件
    UserQueryVo userQueryVo = new UserQueryVo();
    UserCustom userCustom = new UserCustom();
    userCustom.setSex("1");
    userCustom.setUsername("卡啦啦啦啦");
    userQueryVo.setUserCustom(userCustom);
    //调用userMapper的方法
    List<UserCustom> list = userMapper.findUserList(userQueryVo);
    System.out.println(list);
}

1.5:小节:
查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。

12.输出pojo对象和pojo列表

不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType 指定的类型是一样的。
在mapper.java指定的方法返回值类型不一样。
1.输出单个pojo对象,方法返回值是单个对象类型。

//根据id查询用户信息
public User findUserById(int id) throws Exception;

2.输出pojo对象list,方法返回值是List

//根据用户名列查询用户列表
public List<User> findUserByName(String name) throws Exception;

生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList(返回集合对象调用)

13. resultType:

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

14. resultMap

mybatis中使用resultMap完成高级输出结果映射。
1.resultMap使用方法:
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap列名和pojo属性名之间做一个映射关系。
1.1:定义resultMap:

<!-- 
定义resultMap
将select id id_,username username_ from user 和 user类中的属性作一个映射关系
type:resultMap最终映射的Java对象类型,可以使用别名
id:对resultMap的唯一标识
-->
<resultMap type="user" id="userResultMap">
   <!-- id表示查询结果集中唯一标识
   column:查询出来的列名
   property:type指定的pojo类型中的属性名
   最终resultMap对column和property作一个映射关系(对应关系)
   -->
   <id column="id_" property="id">
   <!--
   result:对普通名映射定义
   column:查询出来的列名
   property:type指定的pojo类型中属性名
   最终resultMap对column和property作一个映射关系(对应关系)
   -->
   <result column="username_" property="usrname" />
</resultMap>

1.2使用resultMap作为statement的输出映射类型:

<!-- 使用resultMap进行输出映射
resultMap:指定定义的resultMap的id,如果这个resultMap在其他的mapper文件,前边需要加namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
select id id_,username usernmae_ from user where id=#{value}
</select>

1.3测试:

@Test
public void testFindUserList() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //创建UserMapper对象,mybatis自动生成mapper对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //调用userMapper的方法
    User user = userMapper.findUserByIdResultMap(1);
    System.out.println(user);
}

1.4:总结:
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系。

15:动态sql:

1.什么是动态sql:
mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。
2.需求:
用户信息综合查询列表和用户信息查询列表总数这两个statement的定义使用动态sql。
对查询条件进行判断,如果输入参数不为空才进行查询条件拼接。
3. mapper.xml

<!-- 
用户信息综合查询
#{userCustom.sex}:取出pojo包装对象中性别值
${userCustom.username}:取出pojo包装对象中用户名称
-->
<select id="findUserList" parameterType="cn.xbq.mybatis.po.UserQueryVo" resultType="cn.xbq.mybatis.po.UserCustom">
select * from user
<!-- 
where可以自动去掉条件中的第一个and
-->
<where>
  <if test="userCustom!=null">
     <if test="userCustom.sex!=null and userCustom.sex!="">
         and user.sex = #{userCustom.sex}
     </if>
     <if test="userCustom.username!=null and userCustom.username!="">
         and user.username like '%${usrCustom.username}%'
     </if>
   </if>
</where>

4.测试代码:

//用户信息的综合查询
@Test
public void testFindUserList() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //创建UserMapper对象,mybatis自动生成mapper对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //创建包装对象,设置查询条件
    UserQueryVo userQueryVo = new UserQueryVo();
    UserCustom userCustom = new UserCustom();
    userCustom.setSex("1");
    userCustom.setUsername("卡啦啦啦啦");
    userQueryVo.setUserCustom(userCustom);
    //调用userMapper的方法
    List<UserCustom> list = userMapper.findUserList(userQueryVo);
    System.out.println(list);
}

16.sql片段:

1.需求:
将上边实现的动态sql判断代码块抽取出来,组成一个sql片段,其他的statement中就可以引用sql片段。
方便程序员进行开发。
2.定义sql片段:

<!-- 
定义sql片段
id:sql片段的唯一标识
经验:是基于单表来定义sql片段,这样话这个sql片段可重用性才高
在sql片段中不要包括where
-->
<sql id="query_user_where">
  <if test="userCustom!=null">
     <if test="userCustom.sex!=null and userCustom.sex!="">
         and user.sex = #{userCustom.sex}
     </if>
     <if test="userCustom.username!=null and userCustom.username!="">
         and user.username like '%${usrCustom.username}%'
     </if>
   </if>
</sql>

3.引用sql片段:
在mapper.xml中定义的statement中引用sql片段:

<!-- 
用户信息综合查询
#{userCustom.sex}:取出pojo包装对象中性别值
${userCustom.username}:取出pojo包装对象中用户名称
-->
<select id="findUserList" parameterType="cn.xbq.mybatis.po.UserQueryVo" resultType="cn.xbq.mybatis.po.UserCustom">
select * from user
<!-- 
where可以自动去掉条件中的第一个and
-->
<where>
   <!-- 引用sql片段的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->
   <include refid="query_user_where"></include>
   <!-- 在这里还要引用其他的sql片段-->
</where>
<!-- 
用户信息综合查询
parameterType:指定输入类型和findUserList一样
resultType:输出结果类型
-->
<select id="findUserList" parameterType="cn.xbq.mybatis.po.UserQueryVo" resultType="cn.xbq.mybatis.po.UserCustom">
select count(*) from user
<!-- 
where可以自动去掉条件中的第一个and
-->
<where>
   <!-- 引用sql片段的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->
   <include refid="query_user_where"></include>
   <!-- 在这里还要引用其他的sql片段-->
</where>

17:foreach

向sql传递数组或者List,mybatis使用foreach解析
1.需求:
在用户查询列表和查询总数的statement中增加多个id输入查询。
sql语句如下:
select * from user where id=1 or id=10 or id=16
select * from userwhere id in(1,10,16)

<if test="ids!=null">
<!-- 使用foreach遍历传入ids
collection:指定输入对象中集合属性
item:每个遍历生成对象中
open:开始遍历时拼接的串
close:结束遍历时拼接的串
separator:遍历的两个对象中需要拼接的串
-->
<!-- 使用实现下边的sql拼接:
and (id=1 or id=10 or id=16)
-->
<foreach collection="ids" item="user_id" open="and("close=")" separator="or">
    <!-- 每个遍历需要拼接的串 -->
    id=#{user_id}
</foreach>  
</if>

2.测试代码:

SqlSession sqlSession = sqlSessionFactory.openSession();

    //创建UserMapper对象,mybatis自动生成mapper对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //创建包装对象,设置查询条件
    UserQueryVo userQueryVo = new UserQueryVo();
    UserCustom userCustom = new UserCustom();
    userCustom.setSex("1");
    userCustom.setUsername("小明");
    //传入多个id
    List<Integer> ids = new ArrayList<Integer>();
    ids.add(1);
    ids.add(10);
    ids.add(16);
    //将id通过userQueryVo传入statement中
    userQueryVo.setIds(ids);
    userQueryVo.setUserCustom(userCustom);
    //调用userMapper的方法
    List<UserCustom> list = userMapper.findUserList(userQueryVo);