一文搞定MyBatis各种标签

    技术2024-01-05  101

    文章目录

    select标签使用 Map 接口传递多个参数使用 Java Bean 传递多个参数 insert、update、delete和sql标签< insert>元素1)主键(自动递增)回填2)自定义主键 < update>与< delete>元素< sql> 元素 if标签choose、when、otherwise标签trim、where、set标签< trim>元素< where> 元素< set>元素 foreach标签bind标签

    select标签

    在 SQL 映射文件中 < select> 元素用于映射 SQL 的 select 语句,其示例代码如下:

    <!--根据uid查询一个用户信息 --> <select id="selectUserById" parameterType="Integer" resultType="com.mybatis.po.MyUser"> select * from user where uid = #{uid} </select>

    在上述示例代码中,id 的值是唯一标识符,它接收一个 Integer 类型的参数,返回一个 MyUser 类型的对象,结果集自动映射到 MyUser 属性。

    < select> 元素除了有上述示例代码中的几个属性以外,还有一些常用的属性,如表 1 所示。

    属性名称描 述id它和 Mapper 的命名空间组合起来使用,是唯一标识符,供 MyBatis 调用parameterType表示传入 SQL 语句的参数类型的全限定名或别名。它是一个可选属性,MyBatis 能推断出具体传入语句的参数resultTypeSQL 语句执行后返回的类型(全限定名或者别名)。如果是集合类型,返回的是集合元素的类型,返回时可以使用 resultType 或 resultMap 之一resultMap它是映射集的引用,与 < resultMap> 元素一起使用,返回时可以使用 resultType 或 resultMap 之一flushCache用于设置在调用 SQL 语句后是否要求 MyBatis 清空之前查询的本地缓存和二级缓存,默认值为 false,如果设置为 true,则任何时候只要 SQL 语句被调用都将清空本地缓存和二级缓存useCache启动二级缓存的开关,默认值为 true,表示将査询结果存入二级缓存中timeout用于设置超时参数,单位是秒(s),超时将抛出异常fetchSize获取记录的总条数设定statementType告诉 MyBatis 使用哪个 JDBC 的 Statement 工作,取值为 STATEMENT(Statement)、 PREPARED(PreparedStatement)、CALLABLE(CallableStatement)resultSetType这是针对 JDBC 的 ResultSet 接口而言,其值可设置为 FORWARD_ONLY(只允许向前访问)、SCROLL_SENSITIVE(双向滚动,但不及时更新)、SCROLLJNSENSITIVE(双向滚动,及时更新)

    使用 Map 接口传递多个参数

    在实际开发中,查询 SQL 语句经常需要多个参数,例如多条件查询。当传递多个参数时,< select> 元素的 parameterType 属性值的类型是什么呢?在 MyBatis 中允许 Map 接口通过键值对传递多个参数。

    假设数据操作接口中有个实现查询陈姓男性用户信息功能的方法:

    public List< MyUser> selectAllUser(Map<String,Object> param);

    此时,传递给映射器的是一个 Map 对象,使用它在 SQL 文件中设置对应的参数,对应 SQL 文件的代码如下:

    <!-- 查询陈姓男性用户信息 --> <select id="selectAllUser" resultType="com.mybatis.po.MyUser"> select * from user where uname like concat('%',#{u_name},'%') and usex = #{u_sex} </select>

    在上述 SQL 文件中,参数名 u_name 和 u_sex 是 Map 的 key。

    为了测试该示例,首先创建一个 Web 应用 mybatisDemo02,将 mybatisDemo01 应用的所有 JAR 包复制到 /WEB-INF/lib 下,同时将 mybatisDemo01 应用的 src 目录下的所有包和文件复制到 mybatisDemo02 应用的 src 目录下。

    然后将 com.mybatis 包中的 SQL 映射文件 UserMapper.xml 中的“查询所有用户信息”的代码片段修改为上述“查询陈姓男性用户信息”的代码片段,最后将 com.controller 包中 UserController 的代码简单修改即可运行测试类了。

    com.controller 包中 UserController 的代码片段如下:

    @Controller("UserController") public class UserController { private UserDao userDao; public void test(){ ... //查询多个用户 Map<String,Object> map = new HashMap<>(); map.put("u_name","陈"); map.put("u_sex","男"); List<MyUser> list = userDao.seleceAllUser(map); for(MyUser myUser : list) { System.out.println(myUser); } ... } }

    Map 是一个键值对应的集合,使用者要通过阅读它的键才能了解其作用。另外,使用 Map 不能限定其传递的数据类型,所以业务性不强,可读性较差。如果 SQL 语句很复杂,参数很多,使用 Map 将很不方便。幸运的是,MyBatis 还提供了使用 Java Bean 传递多个参数的形式。

    使用 Java Bean 传递多个参数

    首先在 myBatisSemo02 应用的 src 目录下创建一个名为 com.pojo 的包,在包中创建一个 POJO 类 SeletUserParam,代码如下:

    package com.pojo; public class SeletUserParam { private String u_name; private String u_sex; // 此处省略setter和getter方法 }

    接着将 Dao 接口中的 selectAllUser 方法修改为如下:

    public List< MyUser> selectAllUser(SelectUserParam param);

    然后将 com.mybatis 包中的 SQL 映射文件 UserMapper.xml 中的“查询陈姓男性用户信息”的代码修改为如下:

    <select id="selectAllUser" resultType="com.po.MyUser" parameterType="com.pojo.SeletUserParam"> select * from user where uname like concat('%',#{u_name},'%') and usex=#{u_sex} </select>

    最后将 com.controller 包中 UserController 的“查询多个用户”的代码片段做如下修改:

    SeletUserParam su = new SelectUserParam(); su.setU_name("陈"); su.setU_sex("男"); List<MyUser> list = userDao.selectAllUser(su); for (MyUser myUser : list) { System.out.println(myUser); }

    在实际应用中是选择 Map 还是选择 Java Bean 传递多个参数应根据实际情况而定,一般建议选择 Java Bean。

    insert、update、delete和sql标签

    < insert>元素

    < insert> 元素用于映射插入语句,MyBatis 执行完一条插入语句后将返回一个整数表示其影响的行数。它的属性与 < select> 元素的属性大部分相同,在本节讲解它的几个特有属性。

    keyProperty:该属性的作用是将插入或更新操作时的返回值赋给 PO 类的某个属性,通常会设置为主键对应的属性。如果是联合主键,可以将多个值用逗号隔开。keyColumn:该属性用于设置第几列是主键,当主键列不是表中的第 1 列时需要设置。如果是联合主键,可以将多个值用逗号隔开。useGeneratedKeys:该属性将使 MyBatis 使用 JDBC 的 getGeneratedKeys()方法获取由数据库内部产生的主键,例如 MySQL、SQL Server 等自动递增的字段,其默认值为 false。

    1)主键(自动递增)回填

    MySQL、SQL Server 等数据库的表格可以采用自动递增的字段作为主键,有时可能需要使用这个刚刚产生的主键,用于关联其他业务。

    首先为 com.mybatis 包中的 SQL 映射文件 UserMapper.xml 中 id 为 addUser 的 < insert> 元素添加 keyProperty 和 useGeneratedKeys 属性,具体代码如下:

    <!--添加一个用户,成功后将主键值返回填给uid(po的属性)--> <insert id="addUser" parameterType="com.po.MyUser" keyProperty="uid" useGeneratedKeys="true"> insert into user (uname,usex) values(#{uname},#{usex}) </insert>

    然后在 com.controller 包的 UserController 类中进行调用,具体代码如下:

    // 添加一个用户 MyUser addmu = new MyUser(); addmu.setUname("陈恒"); addmu.setUsex("男"); int add = userDao.addUser(addmu); System.out.println("添加了" + add + "条记录"); System.out.println("添加记录的主键是" + addmu.getUid());

    2)自定义主键

    如果在实际工程中使用的数据库不支持主键自动递增(例如 Oracle),或者取消了主键自动递增的规则,可以使用 MyBatis 的 < selectKey> 元素来自定义生成主键。具体配置示例代码如下:

    <!-- 添加一个用户,#{uname}为 com.mybatis.po.MyUser 的属性值 --> <insert id="insertUser" parameterType="com.po.MyUser"> <!-- 先使用selectKey元素定义主键,然后再定义SQL语句 --> <selectKey keyProperty="uid" resultType="Integer" order="BEFORE"> select if(max(uid) is null,1,max(uid)+1) as newUid from user) </selectKey> insert into user (uid,uname,usex) values(#{uid},#{uname},#{usex}) </insert>

    在执行上述示例代码时,< selectKey> 元素首先被执行,该元素通过自定义的语句设置数据表的主键,然后执行插入语句。

    < selectKey> 元素的 keyProperty 属性指定了新生主键值返回给 PO 类(com.po.MyUser)的哪个属性。

    order 属性可以设置为 BEFORE 或 AFTER。BEFORE 表示先执行 < selectKey> 元素然后执行插入语句。AFTER 表示先执行插入语句再执行 < selectKey> 元素。

    < update>与< delete>元素

    < update> 和 < delete> 元素比较简单,它们的属性和 < insert> 元素、< select> 元素的属性差不多,执行后也返回一个整数,表示影响了数据库的记录行数。配置示例代码如下:

    <!-- 修改一个用户 --> <update id="updateUser" parameterType="com.po.MyUser"> update user set uname = #{uname},usex = #{usex} where uid = #{uid} </update> <!-- 删除一个用户 --> <delete id="deleteUser" parameterType="Integer"> delete from user where uid = #{uid} </delete>

    < sql> 元素

    < sql> 元素的作用在于可以定义 SQL 语句的一部分(代码片段),以方便后面的 SQL 语句引用它,例如反复使用的列名。

    在 MyBatis 中只需使用 < sql> 元素编写一次便能在其他元素中引用它。配置示例代码如下:

    <sql id="comColumns">id,uname,usex</sql> <select id="selectUser" resultType="com.po.MyUser"> select <include refid="comColumns"> from user </select>

    在上述代码中使用 < include> 元素的 refid 属性引用了自定义的代码片段。

    if标签

    开发人员通常根据需求手动拼接 SQL 语句,这是一个极其麻烦的工作,而 MyBatis 提供了对 SQL 语句动态组装的功能,恰能解决这一问题。

    MyBatis 的动态 SQL 元素与 JSTL 或 XML 文本处理器相似,常用 < if>、< choose>、< when>、< otherwise>、< trim>、< where>、< set>、< foreach> 和 < bind> 等元素。

    动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分,所以在 MyBatis 中 < if> 元素是最常用的元素,它类似于 Java 中的 if 语句。在 myBatisDemo03 应用中测试 < if> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用 if 元素根据条件动态查询用户信息--> <select id="selectUserByIf" resultType="com.po.MyUser" parameterType="com.po.MyUser"> select * from user where 1=1 <if test="uname!=null and uname!=''"> and uname like concat('%',#{uname},'%') </if > <if test="usex !=null and usex !=''"> and usex=#{usex} </if > </select>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public List<MyUser> selectUserByIf(MyUser user);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    // 使用 if 元素查询用户信息 MyUser ifmu=new MyUser(); ifmu.setUname ("张"); ifmu.setUsex ("女"); List<MyUser> listByif=userDao.selectUserByIf(ifmu); System.out.println ("if元素================"); for (MyUser myUser:listByif) { System.out.println(myUser); }

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    choose、when、otherwise标签

    有些时候不想用到所有的条件语句,而只想从中择取一二,针对这种情况,MyBatis 提供了 < choose> 元素,它有点像 Java 中的 switch 语句。在 myBatisDemo03 应用中测试 < choose> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用choose、when、otherwise元素根据条件动态查询用户信息--> <select id="selectUserByChoose" resultType="com.po.MyUser" parameterType= "com.po.MyUser"> select * from user where 1=1 <choose> <when test="uname!=null and uname!=''"> and uname like concat('%',#{uname},'%') </when> <when test="usex!=null and usex!=''"> and usex=#{usex} </when> <otherwise> and uid > 10 </otherwise> </choose> </select>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public List<MyUser> selectUserByChoose(MyUser user);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    // 使用 choose 元素查询用户信息 MyUser choosemu=new MyUser(); choosemu.setUname(""); choosemu.setUsex(""); List<MyUser> listByChoose = UserDao.selectUserEyChoose(choosemu); System.out.println ("choose 元素================"); for (MyUser myUser:listByChoose) { System.out.println(myUser); }

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    trim、where、set标签

    < trim>元素

    < trim> 元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix。

    可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides。正因为 < trim> 元素有这样的功能,所以也可以非常简单地利用 < trim> 来代替 < where> 元素的功能。

    在 myBatisDemo03 应用中测试 < trim> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用trim元素根据条件动态查询用户信息--> <select id="selectUserByTrim" resultType="com.po.MyUser"parameterType="com.po.MyUser"> select * from user <trim prefix="where" prefixOverrides = "and | or"> <if test="uname!=null and uname!=''"> and uname like concat('%',#{uname},'%') </if> <if test="usex!=null and usex!=''"> and usex=#{usex} </if> </trim> </select>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public List<MyUser> selectUserByTrim(MyUser user);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    // 使用trim元素查询用户信息 MyUser trimmu=new MyUser(); trimmu.setUname ("张"); trimmu.setUsex("男"); List<MyUser> listByTrim=userDao.selectUserByTrim(trimmu); System.out.println ("trim 元素========================="); for (MyUser myUser:listByTrim) { System.out.println(myUser); }

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    < where> 元素

    < where> 元素的作用是会在写入 < where> 元素的地方输出一个 where 语句,另外一个好处是不需要考虑 < where> 元素里面的条件输出是什么样子的,MyBatis 将智能处理。如果所有的条件都不满足,那么 MyBatis 就会查出所有的记录,如果输出后是以 and 开头的,MyBatis 会把第一个 and 忽略。

    当然如果是以 or 开头的,MyBatis 也会把它忽略;此外,在 < where> 元素中不需要考虑空格的问题,MyBatis 将智能加上。

    在 myBatisDemo03 应用中测试 < where> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用where元素根据条件动态查询用户信息--> <select id="selectUserByWhere" resultType="com.po.MyUser" parameterType="com.po.MyUser"> select * from user <where> <if test="uname != null and uname ! = ''"> and uname like concat('%',#{uname},'%') </if> <if test="usex != null and usex != '' "> and usex=#{usex} </if > </where> </select>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public List<MyUser> selectUserByWhere(MyUser user);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    // 使用where元素查询用户信息 MyUser wheremu=new MyUser(); wheremu.setUname ("张"); wheremu.setUsex("男"); List<MyUser> listByWhere=userDao.selectUserByWhere(wheremu); System.out.println ("where 元素========================="); for (MyUser myUser:listByWhere) { System.out.println(myUser); }

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    < set>元素

    在动态 update 语句中可以使用 < set> 元素动态更新列。在 myBatisDemo03 应用中测试 < set> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用set元素动态修改一个用户--> <update id="updateUserBySet" parameterType="com.po.MyUser"> update user <set> <if test="uname!=null">uname=#{uname}</if> <if test="usex!=null">usex=#{usex}</if> </set> where uid=#{uid} </update>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public int updateUserBySet(MyUser user);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    // 使用set元素查询用户信息 MyUser setmu=new MyUser(); setmu.setUid (1); setmu.setUname("张九"); int setup=userDao.updateUserBySet(setmu); System.out.println ("set 元素修改了"+setup+"条记录"); System.out.println ("=========================")

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    foreach标签

    < foreach> 元素主要用在构建 in 条件中,它可以在 SQL 语句中迭代一个集合。

    < foreach> 元素的属性主要有 item、index、collection、open、separator、close。

    item 表示集合中每一个元素进行迭代时的别名。index 指定一个名字,用于表示在迭代过程中每次迭代到的位置。open 表示该语句以什么开始。separator 表示在每次进行迭代之间以什么符号作为分隔符。close 表示以什么结束。

    在使用 < foreach> 元素时,最关键、最容易出错的是 collection 属性,该属性是必选的,但在不同情况下该属性的值是不一样的,主要有以下 3 种情况:

    如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。

    在 myBatisDemo03 应用中测试 < foreach> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用foreach元素查询用户信息--> <select id="selectUserByForeach" resultType="com.po.MyUser" parameterType= "List"> select * from user where uid in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> # {item} </foreach> </select>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public List<MyUser> selectUserByForeach(List<Integer> listId);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    //使用foreach元素查询用户信息 List<Integer> listId=new ArrayList<Integer>(); listId.add(34); listId.add(37); List<MyUser> listByForeach = userDao.selectUserByForeach(listId); System.out.println ("foreach元素================"); for(MyUser myUser : listByForeach) { System.out.println(myUser); }

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    bind标签

    在进行模糊查询时,如果使用“${}”拼接字符串,则无法防止 SQL 注入问题。如果使用字符串拼接函数或连接符号,但不同数据库的拼接函数或连接符号不同。

    例如 MySQL 的 concat 函数、Oracle 的连接符号“||”,这样 SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利于代码的移植。幸运的是,MyBatis 提供了 < bind> 元素来解决这一问题。

    在 myBatisDemo03 应用中测试 < bind> 元素,具体过程如下:

    1)添加 SQL 映射语句

    在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射语句:

    <!--使用bind元素进行模糊查询--> <select id="selectUserByBind" resultType="com.po.MyUser" parameterType= "com.po.MyUser"> <!-- bind 中的 uname 是 com.po.MyUser 的属性名--> <bind name="paran_uname" value="'%' + uname + '%'"/> select * from user where uname like #{paran_uname} </select>

    2)添加数据操作接口方法

    在 com.dao 包的 UserDao 接口中添加如下数据操作接口方法:

    public List<MyUser> selectUserByBind(MyUser user);

    3)调用数据操作接口方法

    在 com.controller 包的 UserController 类中添加如下程序调用数据操作接口方法。

    // 使用bind元素查询用户信息 MyUser bindmu=new MyUser(); bindmu.setUname ("张"); List<MyUser> listByBind=userDao.selectUserByBind(bindmu); System.out.println ("bind 元素========================="); for (MyUser myUser:listByBind) { System.out.println(myUser); }

    4)测试动态 SQL 语句

    运行 com.controller 包中的 TestController 主类,测试动态 SQL 语句。

    Processed: 0.008, SQL: 9