搜索
首页Javajava教程Mybatis映射文件的实例代码详解

Mybatis映射文件的实例代码详解

Mar 09, 2017 am 10:32 AM
mybatis映射文件

这篇文章主要介绍了 Mybatis映射文件实例详解,需要的朋友可以参考下

 一、输入映射

parameterType

指定输入参数的Java类型,可以使用别名或者类的全限定名。它可以接收简单类型、POJO、HashMap。

1、传递简单类型

根据用户ID查询用户信息:

<select id="findUserById" parameterType="int" resultType="com.itheima.mybatis.po.User"> 
  SELECT * FROM USER WHERE id =#{id} 
</select>

2、传递POJO对象

添加用户:

<insert id="insertUser" parameterType="com.itheima.mybatis.po.User"> 
  <selectKey keyProperty="id" resultType="int" order="AFTER"> 
   SELECT LAST_INSERT_ID() 
  </selectKey> 
  INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address}) 
</insert>

3、传递POJO包装对象

开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),
这时可以使用包装对象传递输入参数。

3.1需求

综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。

3.2 定义包装对象

一般User.java类要和数据表表字段一致,最好不要在这里面添加其他字段,在mybatis的逆向工程时,会根据表结构,生成po类,

如果在po类中扩展字段,此时会被覆盖掉。

所以针对要扩展的po类,我们需要创建一个扩展类,来继承它。

public class UserExt extends User{ 
 //这里可以定义user的一些扩展信息 
}

定义POJO包装类:

public class UserQueryVO { 
 //用户信息 
 private UserExt userExt; 
 //商品ID集合 
 private List<Integer> idList; 
 //商品信息 
 public List<Integer> getIdList() { 
  return idList; 
 } 
 public void setIdList(List<Integer> idList) { 
  this.idList = idList; 
 } 
 public UserExt getUserExt() { 
  return userExt; 
 } 
 public void setUserExt(UserExt userExt) { 
  this.userExt = userExt; 
 } 
 //订单信息 
}

3.3编写Mapper接口

//通过包装类来进行复杂的用户信息综合查询 
public List365ec941ff246bca2de9473cb1305a57 findUserList(UserQueryVO userQueryVO); 

3.4编写mapper映射文件

<!-- 通过包装类来进行复杂的用户信息综合查询 --> 
<select id="findUserList" parameterType="userQueryVO" resultType="userExt"> 
  SELECT * FROM USER WHERE sex=#{userExt.sex} AND username LIKE &#39;%${userExt.username}%&#39; 
</select>

注意:入参的类型变为UserQueryVO、结果集的类型变为UserExt,#{}里面的参数变为UserQueryVO对象中的userExt属性的sex和username子属性。

3.5编写测试代码

@Test 
public void findUserListTest() { 
 // 创建SqlSession 
 SqlSession sqlSession = sqlSessionFactory.openSession(); 
 // 通过SqlSession,获取mapper接口的动态代理对象 
 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
 //构造userQueryVO对象 
 UserQueryVO userQueryVO = new UserQueryVO(); 
 // 构造UserExt对象 
 UserExt userExt = new UserExt(); 
 userExt.setSex("1"); 
 userExt.setUsername("小明"); 
 userQueryVO.setUserExt(userExt); 
 // 调用mapper对象的方法 
 List<UserExt> list = userMapper.findUserList(userQueryVO); 
 System.out.println(list); 
 // 关闭SqlSession 
 sqlSession.close(); 
}

4、传递HashMap

同传递POJO对象一样,map的key相当于pojo的属性。

4.1映射文件

<!-- 传递hashmap综合查询用户信息 --> 
 <select id="findUserByHashmap" parameterType="hashmap" resultType="user"> 
  select * from user where id=#{<span style="color:#ff0000;">id</span>} and username like &#39;%${<span style="color:#ff0000;">username</span>}%&#39; 
 </select>

上边红色标注的id和username是hashmap的key。

4.2测试代码

Public void testFindUserByHashmap()throws Exception{ 
  //获取session 
  SqlSession session = sqlSessionFactory.openSession(); 
  //获限mapper接口实例 
  UserMapper userMapper = session.getMapper(UserMapper.class); 
  //构造查询条件Hashmap对象 
  HashMap<String, Object> map = new HashMap<String, Object>(); 
  map.put("id", 1); 
  map.put("username", "管理员"); 
   
  //传递Hashmap对象查询用户列表 
  List<User>list = userMapper.findUserByHashmap(map); 
  //关闭session 
  session.close(); 
 }

异常测试:

传递的map中的key和sql中解析的key不一致。

测试结果没有报错,只是通过key获取值为空。

二、输出映射

1、resultType

(1)使用方法

使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。

如果查询的列名和映射的pojo属性名全部不一致,那么映射的对象为空,不会创建pojo对象;

如果查询的列名和映射的pojo属性名有一个一致,那么映射的对象不为空,会创建pojo对象,但是只有映射正确的那一个属性才有值。

(2)输出简单类型

注意,对简单类型的结果映射也是有要求的,查询的列必须是一列,才能映射为简单类型。

当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型。

2.1需求

综合查询用户总数,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。

2.2Mapper映射文件

<!-- 综合查询用户信息总数,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 
<select id="findUsersCount" parameterType="UserQueryVO" 
  resultType="int"> 
  SELECT count(1) FROM USER WHERE sex = #{userExt.sex} AND username LIKE &#39;%${userExt.username}%&#39; 
</select>

2.3Mapper接口

//综合查询用户信息总数。学习:resultType输出简单类型 
public int findUsersCount(UserQueryVO vo);

2.4测试代码

@Test 
public void testFindUsersCount() { 
 // 创建SqlSession 
 SqlSession sqlSession = sqlSessionFactory.openSession(); 
 // 通过SqlSession,获取mapper接口的动态代理对象 
 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
 //构造userQueryVO对象 
 UserQueryVO userQueryVO = new UserQueryVO(); 
 // 构造UserExt对象 
 UserExt userExt = new UserExt(); 
 userExt.setSex("1"); 
 userExt.setUsername("小明"); 
 userQueryVO.setUserExt(userExt); 
 int count = mapper.findUsersCount(userQueryVO); 
 System.out.println(count); // 关闭SqlSession 
 sqlSession.close(); 
}

(3)输出POJO单个对象和列表

注意:输出单个pojo对象和pojo列表(盛放pojo对象)时,mapper映射文件中的resultType的类型是一样的,mapper接口的方法返回值不同。

3.1Mapper映射文件

<select id="findUsersByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User"> 
  SELECT * FROM USER WHERE username LIKE &#39;%${value}%&#39; 
</select>

3.2Mapper接口

1、输出单个pojo对象

//根据用户名称来模糊查询用户信息 
 public User findUsersByName(String username);

2、输出pojo列表

//根据用户名称来模糊查询用户信息列表 
 public List<User> findUsersByName(String username);

总结:同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,

会根据返回值的类型,决定调用selectOne方法还是selectList方法。

2、resultMap

resultMap可以进行高级结果映射(一对一、一对多映射)。

(1)使用方法

如果查询出来的列名和属性名不一致,通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。

1、  定义resultMap

2、  使用resultMap作为statement的输出映射类型。

(2)需求

把下面SQL的输出结果集进行映射

SELECT id id_,username username_,sex sex_FROM USER WHERE id = 1

(3)Mapper映射文件

定义resultMap:

<!-- 定义resultMap --> 
<!-- 
 [id]:定义resultMap的唯一标识 
 [type]:定义该resultMap最终映射的pojo对象 
 [id标签]:映射结果集的唯一标识列,如果是多个字段联合唯一,则定义多个id标签 
 [result标签]:映射结果集的普通列 
 [column]:SQL查询的列名,如果列有别名,则该处填写别名 
 [property]:pojo对象的属性名 
--> 
<resultMap type="user" id="userResultMap"> 
 <id column="id_" property="id"/> 
 <result column="username_" property="username"/> 
 <result column="sex_" property="sex"/> 
</resultMap>

定义statement:

<!-- 根据ID查询用户信息(学习resultMap) --> 
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap"> 
  SELECT id id_,username username_,sex sex_ FROM USER WHERE id = #{id} 
</select>

(4)Mapper接口定义  

 //根据ID查询用户信息(学习resultMap) 
 public User findUserByIdResultMap(int id);<strong> 
</strong>

定义Statement使用resultMap映射结果集时,Mapper接口定义方法的返回值类型为mapper映射文件中resultMap的type类型。

(5)测试代码

@Test 
public void findUserByIdResultMapTest() { 
 // 创建SqlSession 
 SqlSession sqlSession = sqlSessionFactory.openSession(); 
 // 通过SqlSession,获取mapper接口的动态代理对象 
 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
 // 调用mapper对象的方法 
 User user = userMapper.findUserByIdResultMap(1); 
 System.out.println(user); 
 // 关闭SqlSession 
 sqlSession.close(); 
}

三、动态SQL

1、If和where

Ø  If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。
注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘';
Ø  Where标签:会去掉条件中的第一个and符号。

(1)需求

用户信息综合查询列表和用户信息综合查询总数这两个statement的定义使用动态SQL。

(2)映射文件

<!-- 综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 
<select id="findUsersByQueryVO" parameterType="cn.itcast.mybatis.po.QueryUserVO" 
  resultType="User"> 
  SELECT * FROM USER 
 <where> 
  <if test="userExt != null"> 
   <if test="userExt.sex != null and userExt.sex != &#39;&#39;"> 
    AND sex = #{userExt.sex} 
   </if> 
   <if test="userExt.username != null and userExt.username != &#39;&#39;"> 
    AND username LIKE &#39;%${userExt.username}%&#39; 
   </if> 
  </if> 
 </where> 
</select> 
<!-- 综合查询用户信息总数,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 
<select id="findUsersCount" parameterType="QueryUserVO" 
  resultType="int"> 
 SELECT count(1) FROM USER 
 <where> 
  <if test="userExt != null"> 
   <if test="userExt.sex != null and userExt.sex != &#39;&#39;"> 
    AND sex = #{userExt.sex} 
   </if> 
   <if test="userExt.username != null and userExt.username != &#39;&#39;"> 
    AND username LIKE &#39;%${userExt.username}%&#39; 
   </if> 
  </if> 
 </where> 
</select>

(3)Mapper接口

//通过包装类来进行复杂的用户信息综合查询 
public List<UserExt> findUserList(UserQueryVO userQueryVO); 
//综合查询用户总数 
public int findUsersCount(UserQueryVO userQueryVO);

(4)测试代码

不传用户名:

@Test 
 public void testFindUserList() throws Exception{ 
  // 创建UserMapper对象 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  // 由mybatis通过sqlsession来创建代理对象 
  UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
  QueryUserVO vo = new QueryUserVO(); 
  User user = new User(); 
  //此处使用动态SQL,不传username参数 
  user.setSex("1"); 
//  user.setUsername("小明"); 
  vo.setUser(user); 
  List<User> list = mapper.findUserList(vo); 
  System.out.println(user); 
  sqlSession.close(); 
 }

输出的SQL如下(也不包含用户名):

通过测试可以得知,打印出的SQL语句确实会随着条件的满足情况而不一样。

2、SQL片段

Mybatis提供了SQL片段的功能,可以提高SQL的可重用性。

2.1定义SQL片段

使用sql标签来定义一个SQL片段:

<!-- 定义SQL片段 --> 
<!-- 
 [sql标签]:定义一个SQL片段 
 [id]:SQL片段的唯一标识 
 建议: 
  1、SQL片段中的内容最好是以单表来定义 
  2、如果是查询字段,则不要写上SELECT 
  3、如果是条件语句,则不要写上WHERE 
 --> 
<sql id="select_user_where"> 
 <if test="userExt != null"> 
  <if test="userExt.sex != null and userExt.sex != &#39;&#39;"> 
   AND sex = #{userExt.sex} 
  </if> 
  <if test="userExt.username != null and userExt.username != &#39;&#39;"> 
   AND username LIKE &#39;%${userExt.username}%&#39; 
  </if> 
 </if> 
</sql>

2.2引用SQL片段

使用4801eb3c8c45c8edef439cb1d2a07f8a 来引用SQL片段:

<!-- 根据用户id来查询用户信息(使用SQL片段) --> 
<!-- 
 [include标签]:引用已经定义好的SQL片段 
 [refid]:引用的SQL片段id 
--> 
<select id="findUserList" parameterType="userQueryVO" resultType="userExt"> 
 SELECT * FROM USER 
<where> 
  <include refid="select_user_where"/> 
 </where> 
</select> 
<!-- 综合查询用户信息总数,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 
<select id="findUsersCount" parameterType="QueryUserVO" 
  resultType="int"> 
 SELECT count(1) FROM USER 
 <where> 
  <include refid="select_user_where"/> 
 </where> 
</select>

3、foreach

向sql传递数组或List时,mybatis使用foreach解析数组里的参数并拼接到SQL中。

(1)传递pojo对象中的list集合

1.1需求

在用户查询列表和查询总数的statement中增加多个id输入查询。

1.2SQL

SELECT * FROM user WHERE id IN (1,10,16)

1.3定义pojo中的list属性

package com.itheima.mybatis.po; 
import java.util.List; 
/** 
 * <p>Title: UserQueryVO</p> 
 * <p>Description: TODO(这里用一句话描述这个类的作用) <p> 
 */ 
public class UserQueryVO { 
 //用户信息 
 private UserExt userExt; 
 //商品ID集合 
 private List<Integer> idList; 
 //商品信息 
 public List<Integer> getIdList() { 
  return idList; 
 } 
 public void setIdList(List<Integer> idList) { 
  this.idList = idList; 
 } 
 public UserExt getUserExt() { 
  return UserExt; 
 } 
 public void setUserExt(UserExt userExt) { 
  this.UserExt = UserExt; 
 } 
 //订单信息 
}

1.4映射文件

<!-- [foreach标签]:表示一个foreach循环 --> 
<!-- [collection]:集合参数的名称,如果是直接传入集合参数,则该处的参数名称只能填写[list]。 --> 
<!-- [item]:每次遍历出来的对象 --> 
<!-- [open]:开始遍历时拼接的串 --> 
<!-- [close]:结束遍历时拼接的串 --> 
<!-- [separator]:遍历出的每个对象之间需要拼接的字符 --> 
<if test="idList != null and idList.size > 0"> 
<foreach collection="idList" item="id" open="AND id IN (" close=")" separator=","> 
  #{id} 
</foreach> 
</if>

1.5Mapper接口

//根据用户ID的集合查询用户列表(学习foreach标签之通过POJO对象传ID集合) 
public List<UserExt> findUserList(UserQueryVO vo);

1.6测试代码

@Test 
public void testFindUserList() { 
  // 创建SqlSession 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  // 通过SqlSession,获取mapper接口的动态代理对象 
  UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
  // 构造QueryUserVO对象 
  QueryUserVO vo = new QueryUserVO(); 
  // UserExt ext = new UserExt(); 
  // ext.setUsername("小明"); 
  // ext.setSex("1"); 
  // vo.setUserExt(ext); 
  // 创建用户ID集合,然后设置到QueryUserVO对象中 
  List<Integer> idList = new ArrayList<Integer>(); 
  idList.add(1); 
  idList.add(10); 
  idList.add(16); 
  vo.setIdList(idList); 
  // 调用mapper代理对象的方法 
  List<UserExt> list = mapper.findUserList(vo); 
  System.out.println(list); 
  // 关闭SqlSession 
  sqlSession.close(); 
}

(2)直接传递List集合

2.1需求

根据用户ID的集合查询用户列表

2.2SQL

SELECT * FROM user WHERE id IN (1,10,16)

2.3映射文件

<!-- 根据用户ID的集合查询用户列表(学习foreach标签之直接传ID集合) --> 
<!--  
  [foreach标签]:表示一个foreach循环 
  [collection]:集合参数的名称,如果是直接传入集合参数,则该处的参数名称只能填写[list]。 
  [item]:定义遍历集合之后的参数名称 
  [open]:开始遍历之前需要拼接的SQL串 
  [close]:结束遍历之后需要拼接的SQL串 
  [separator]:遍历出的每个对象之间需要拼接的字符 
 --> 
<select id="findUsersByIdList" parameterType="java.util.List" resultType="user"> 
  SELECT * FROM USER 
  <where> 
    <if test="list != null and list.size > 0"> 
      <foreach collection="list" item="id" open="AND id IN (" close=")" separator=","> 
        #{id} 
      </foreach> 
    </if> 
  </where> 
</select>

2.4Mapper接口

//根据用户ID的集合查询用户列表(学习foreach标签之直接传ID集合) 
public List<User> findUsersByIdList (List<Integer> idList);

2.5测试代码

@Test 
public void findUsersByIdListTest() { 
  // 创建SqlSession 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  // 通过SqlSession,获取mapper接口的动态代理对象 
  UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 
  // 构造List<Integer>集合 
  List<Integer> idList = new ArrayList<Integer>(); 
  idList.add(1); 
  idList.add(10); 
    idList.add(16); 
  // 调用mapper对象的方法 
  List<User> list = userMapper.findUsersByIdList (idList); 
  System.out.println(list); 
  // 关闭SqlSession 
  sqlSession.close(); 
}


以上是Mybatis映射文件的实例代码详解的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
为什么Java是开发跨平台桌面应用程序的流行选择?为什么Java是开发跨平台桌面应用程序的流行选择?Apr 25, 2025 am 12:23 AM

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runanywhere”哲学。1)itusesbytbytybytecebytecodethatrunsonanyjvm-platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

讨论可能需要在Java中编写平台特定代码的情况。讨论可能需要在Java中编写平台特定代码的情况。Apr 25, 2025 am 12:22 AM

在Java中编写平台特定代码的原因包括访问特定操作系统功能、与特定硬件交互和优化性能。1)使用JNA或JNI访问Windows注册表;2)通过JNI与Linux特定硬件驱动程序交互;3)通过JNI使用Metal优化macOS上的游戏性能。尽管如此,编写平台特定代码会影响代码的可移植性、增加复杂性、可能带来性能开销和安全风险。

与平台独立性相关的Java开发的未来趋势是什么?与平台独立性相关的Java开发的未来趋势是什么?Apr 25, 2025 am 12:12 AM

Java将通过云原生应用、多平台部署和跨语言互操作进一步提升平台独立性。1)云原生应用将使用GraalVM和Quarkus提升启动速度。2)Java将扩展到嵌入式设备、移动设备和量子计算机。3)通过GraalVM,Java将与Python、JavaScript等语言无缝集成,增强跨语言互操作性。

Java的强键入如何有助于平台独立性?Java的强键入如何有助于平台独立性?Apr 25, 2025 am 12:11 AM

Java的强类型系统通过类型安全、统一的类型转换和多态性确保了平台独立性。1)类型安全在编译时进行类型检查,避免运行时错误;2)统一的类型转换规则在所有平台上一致;3)多态性和接口机制使代码在不同平台上行为一致。

说明Java本机界面(JNI)如何损害平台独立性。说明Java本机界面(JNI)如何损害平台独立性。Apr 25, 2025 am 12:07 AM

JNI会破坏Java的平台独立性。1)JNI需要特定平台的本地库,2)本地代码需在目标平台编译和链接,3)不同版本的操作系统或JVM可能需要不同的本地库版本,4)本地代码可能引入安全漏洞或导致程序崩溃。

是否有任何威胁或增强Java平台独立性的新兴技术?是否有任何威胁或增强Java平台独立性的新兴技术?Apr 24, 2025 am 12:11 AM

新兴技术对Java的平台独立性既有威胁也有增强。1)云计算和容器化技术如Docker增强了Java的平台独立性,但需要优化以适应不同云环境。2)WebAssembly通过GraalVM编译Java代码,扩展了其平台独立性,但需与其他语言竞争性能。

JVM的实现是什么,它们都提供了相同的平台独立性?JVM的实现是什么,它们都提供了相同的平台独立性?Apr 24, 2025 am 12:10 AM

不同JVM实现都能提供平台独立性,但表现略有不同。1.OracleHotSpot和OpenJDKJVM在平台独立性上表现相似,但OpenJDK可能需额外配置。2.IBMJ9JVM在特定操作系统上表现优化。3.GraalVM支持多语言,需额外配置。4.AzulZingJVM需特定平台调整。

平台独立性如何降低发展成本和时间?平台独立性如何降低发展成本和时间?Apr 24, 2025 am 12:08 AM

平台独立性通过在多种操作系统上运行同一套代码,降低开发成本和缩短开发时间。具体表现为:1.减少开发时间,只需维护一套代码;2.降低维护成本,统一测试流程;3.快速迭代和团队协作,简化部署过程。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。