Bootstrap

(三十三)mybatis加强

mybatis加强


使用Mapper接口

相当于DAO,在接口汇总定义CRUD等方法 Mapper组件=Mapper接口+Mapper XMl文件

规范:

  • 接口的命名为XxxMapper(Xxx为实体类名),一般与对应的XML文件放在一起(编译后的字节码文件和XML放在一起就行)
  • XML命名空间nameSpace对应接口的全限定类名


定义Mapper接口: UserMapper

public interface UserMapper {void save(User user);}

定义XMl: UserMapper.xml

<insert id="save" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
INSERT INTO user(username, password) VALUES(#{username}, #{password})
</insert>
  1. useGeneratedKeys=“true” :获取数据生成主键值(获取由数据库自动生成的主键)
  2. keyProperty=“id” :设置到被保存的User对象哪个属性上id属性上(指定把获取到的主键注入到实体类的id属性上)

测试使用Mapper接口:

  @Test
    public void save() {
        SqlSession session = MyBatisUtil.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("yyy");
        user.setPassword("123");
        mapper.save(user);
        session.commit();
        session.close();
    }

这里使用了getMapper ,getMapper返回的是什么? 为什么需要向getMapper方法传递参数?

  1. getMapper返回的是上述UserMapper的实现类对象 ,这个实现类对象是由JDK动态代理创建的(以后补充动态代理)
  2. 项目中会有多个Mapper接口,传递接口的字节码就可以找到对应的接口实现类对象.


@Param注解

当传递一个 List 对象或数组对象参数给 MyBatis 时,MyBatis 会自动把它包装到一个 Map 中

List 对象会以 list 作为 key,数组对象会以 array 作为 key。我们也可以使用 @Param(给参数命名)设置key名


使用场景:

Mapper接口方法定义的参数

1.一个参数 :

1.简单类型: 分为 # , $
         1.# 不贴注解
         2.$或者标签取值 贴注解
2.Map JavaBean :不贴注解 ,因为已经进行了封装,sql可以直接引用javabean中的属性 
3.List数组:一般都会贴注解,在Mapper XMl 取值见名知意    

2.多个参数:需要贴上注解,不然会报错

原理,以登录接口为例:

User login(@Param("username") String username, @Param("password") String password);
<select id="login" resultType="cn.k.domain.User">
select id,username,password from user where username=#{username} and password=#{password}
</select>

如果login接口不使用注解的方式,由于命名空间方式只支持一个参数,那么传递的两个参数会被封装成一个Map集合;

map集合会帮我们装进去,但是是有两种方式,例如:
map.put("param1","xx")
map.put("param2","1")
map.put("arg0","xx")
map.put("arg1","1")
    
  那么Mapperxml文件中就需要写成
<select id="login" resultType="User">
select id,username,password from user where username=#{param1} and password=#{param2}
//或者
//select id,username,password from user where username=#{arg0} and password=#{arg1}
</select>

上述这种不贴注解,需要按照param1,2…这样顺序写下去,sql不直观,不小心就会报错,不写也会报错,所以我们需要采用贴注解方式来解决


#与$的区别

在sql 中有分 #和 $ , 使用#传递的参数会先转换,无论传递什么类型都会带一个单引号(’’),使用$传递的参数,直接把值作为SQL语句的一部分.

#$
简单类型(八大基本数据类型及其包装类、String、BigDecimal 等等)参数作为 值使用 $ 不支持把简单类型参数作为值
使用#,没有SQL注入的问题,相对比较安全相对不安全,可能会有sql注入问题

$:会优先取db.properties中的参数


#和$的选取

$ 取列名或者表名的时候使用,一般出现在FROM子句,GROUP BY ,ORDER BY ,SELECT子句
其他使用 # 解决


动态SQL

if where
<select id="queryByMinSalaryAndMaxSalary" resultType="Employee">
        select id, name, sn, salary, deptId
        from employee
        <where>
            <if test="minSalary != null">
                and salary >= #{minSalary}
            </if>
            <if test="maxSalary != null">
                and salary &lt;= #{maxSalary}
            </if>
        </where>
    </select>
set
<update id="update">
        update employee
        <set>
            <if test="name != null and name != ''">
                name=#{name},
            </if>
            <if test="salary != null">
                salary=#{salary},
            </if>
            <if test="sn != null">
                sn=#{sn},
            </if>
            <if test="deptId != null">
                deptId=#{deptId},
            </if>
        </set>
        where id = #{id}
    </update>
froeach

通常在构建 IN 条件语句时使用

  • Collection 要遍历list 对象 或者数组对象
    open 要遍历之前拼接字符串
    item 遍历时指定变量存到每次遍历元素
    index 遍历的索引
    separator 每遍历一个元素之后拼接字符串,除了最后一次
    close 遍历结束拼接字符串

批量删除

//批量删除
void multipleDelete(@Param("ids") Long[] ids);
<delete id="multipleDelete">
        delete
        from employee where id IN
        <foreach collection="ids" open="(" item="id" separator="," close=")">
            #{id}
        </foreach>
    </delete>        
;