mybatis多种sql执行方式

http://www.mybatis.org/mybatis-3/zh/index.html  官方中文文档

以下例子基本来自官方文档。

此篇重点讲解通过注解的方式来写sql。

首先要解释下${} #{}的区别,

sql:select * from tb_user where user_name = ${userName}

参数:userName = 'xiaoming'

执行后:select * from tb_user where user_id = ?

sql:select * from tb_user where user_name = ${userName}

参数:userName = 'xiaoming' (String)

执行后:select * from tb_user where user_id = 1

可以看出,#{} 传参可以防止sql注入攻击。那什么是sql注入攻击?

拿第二句(${})可能会被攻击的句子, 假如攻击者模拟了个 String userName = "xiaoming or 1 = 1",

sql 语句变成了:select * from tb_user where user_name = xiaoming or 1 = 1 

执行后的结果就是把tb_user表里面的数据全部取出来了

==============================================================

跳过xml方式的sql。

注解提供了一种简单的方式来实现简单映射语句,而不会引入大量的开销。

这个例子展示了如何使用 @SelectKey 注解来在插入前读取数据库序列的值:

@Insert("insert into table3 (id, name) values(#{nameId}, #{name})")
@SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class)
int insertTable3(Name name);


这个例子展示了如何使用 @SelectKey 注解来在插入后读取数据库识别列的值:

@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);

大多数对数据库的操作基本是 查询操作,下面先看下查询出来的每个字段都独自处理的方式。

@Results(id = "userResult", value = {
  @Result(property = "id", column = "uid", id = true),
  @Result(property = "firstName", column = "first_name"),
  @Result(property = "lastName", column = "last_name")
})
@Select("select * from users where id = #{id}")
User getUserById(Integer id);

@Results(id = "companyResults")
@ConstructorArgs({
  @Arg(property = "id", column = "cid", id = true),
  @Arg(property = "name", column = "name")
})
@Select("select * from company where id = #{id}")
Company getCompanyById(Integer id);


可以看到,我们使用@Results的方式,需要对取出来的每个字段,可以遇见如果我们的mapper接口几个方法就要占据了大幅度的篇幅。个人感觉这对维护一个系统并不是很好的选择。特殊的需求可以特殊处理。

单一参数使用 @SqlProvider 注解的情况

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);

class UserSqlBuilder {
  public static String buildGetUsersByName(final String name) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      if (name != null) {
        WHERE("name like #{value} || '%'");
      }
      ORDER_BY("id");
    }}.toString();
  }
}


mybatis提供了一种 SQL类的方式来定义我们需要的sql语句。sql构建器的好处就上假设我们就使用字符串拼接的方式,字符串拼接的方式最容易犯错误的地方就是 +号的左右有没有加空格。

当然你也可以写sql语句。http://www.mybatis.org/mybatis-3/zh/statement-builders.html 官方第一个例子。

多参数使用 @SqlProvider 注解

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
    @Param("name") String name, @Param("orderByColumn") String orderByColumn);

class UserSqlBuilder {

  // If not use @Param, you should be define same arguments with mapper method
  // 如果你没用@Param,你需要定义mapper上方法的参数
  public static String buildGetUsersByName(
      final String name, final String orderByColumn) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      WHERE("name like #{name} || '%'");
      ORDER_BY(orderByColumn);
    }}.toString();
  }

  // If use @Param, you can define only arguments to be used
  //如果你使用了@Param,你可以只定义你需要用到的参数。
  public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
    return new SQL(){{
      SELECT("*");
      FROM("users");
      WHERE("name like #{name} || '%'");
      ORDER_BY(orderByColumn);
    }}.toString();
  }
}

@SelectProvider 我们仔细看下,我们需要给它提供2个必要的参数,type就是你sql语句写的类,method 就是你需要调用的sql的那个方法名。

官方给的例子里面都是返回实体类,假设我们需要返回别的类,假设是对user表和role表进行一个联合查询,我需要user的名字和role的名称。那我定义了一个UserRoleDto,那要返回的时候该去找它的哪个映射?

这时候就要用到@ResultMap这个注解。

我们可以看到

它只有一个value属性。很明确,这个就是让我们去定位我们该用哪个ResultMap。

我们的ResultMap当然是定义在mapper.xml文件下的。

我们先看下mapper接口处:

我们看下SelectProvide用到的方法。

最后是我们ResultMap的定位,我们需要把它看成两部分。

先是红框框起来的,这个表示我们resultMap所在xml的namespace,后面就是我们resulMap的id

猜你喜欢

转载自blog.csdn.net/xmzyjr123/article/details/81676959