3.MyBatis的查询操作

一、 单表查询

根据用户id查询用户信息的功能

Controller 实现代码如下:

@RequestMapping("/getuser")
public User getUserById(Integer id){
    return userService.getUserById(id);
}

Mapping.xml 实现代码如下:

<select id="getUserById" resultType="com.example.demo.User">
    select * from userinfo where id=#{id}
 </select>

二、 参数占位符 #{} 和 ${}

#{} 预编译处理:

MyBatis 在处理#{}时,会将SQL中的#{}替换为 ?号,

使用PreparedStatement的Set方法来赋值

${} 字符直接替换:

是MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值

适用场景:业务需要传递SQL命令只能使用${}

注意:

1.${}可以实现排序查询,使用 #{sort} 就不能实现排序查询了,

因为当使用 #{sort}查询时,如果传递的值为String 会加单引号,就会导致 sql错误。

2.如果要使用${},传递的参数一定要能被穷举,否则不可使用

三、like查询

XML配置方式:

<!-- Mapper XML -->
<select id="getUserByUsername" parameterType="String" resultType="User">
  SELECT * FROM user WHERE username LIKE '%' || ${username} || '%'
</select>

使用 '%' || ${username} || '%' 来构建动态的 LIKE 查询条件,

其中 || 用于字符串的连接操作,上述 语句是存在SQL注入风险的,只有在特定情况下,确保参数安全性,并且需要动态构建SQL语句时才考虑使用 ${}

用 #{}来解决SQL注入问题:

<!-- Mapper XML -->
<select id="getUserByUsername" parameterType="String" resultType="User">
  SELECT * FROM user WHERE username LIKE CONCAT('%', #{username}, '%')
</select>

使用 LIKE CONCAT('%', #{username}, '%') 将参数值与SQL语句进行拼接,确保了参数的安全性,来构建模糊查询的条件。

其中 % 表示通配符,可以匹配任意字符,例如 %keyword% 表示在任意位置匹配关键字

Mapper 接口:

// Mapper 接口
public interface UserDao {
    List<User> getUserByUsername(@Param("username") String username);
}

// Mapper XML 中不需要额外配置

四、 返回类型:resultType

绝大数查询场景可以使用resultType进行返回,如下代码所示:

<!-- 查询单个基本类型 -->
<select id="getTotalCount" resultType="int">
  SELECT COUNT(*) FROM users
</select>
<!-- 查询结果为Java字符串类型 -->
<select id="getRecordCount" resultType="java.lang.String">
  SELECT COUNT(*) FROM records
</select>
 
<!-- 查询单个简单对象 -->
<select id="getUserById" resultType="com.example.User">
  SELECT id, username, email FROM users WHERE id = #{id}
</select>

<!-- 查询复杂对象 -->
<select id="getUserOrder" resultType="com.example.UserOrder">
  SELECT u.id, u.username, o.order_number
  FROM users u JOIN orders o ON u.id = o.user_id
  WHERE u.id = #{userId}
</select>

<!-- 查询结果存储在集合中 -->
<select id="getAllUsers" resultType="java.util.List">
  SELECT id, username, email FROM users
</select>

优点:使用方便,可以直接定义到某个实体类

注意:需要注意的是,当使用 resultType 时,MyBatis 假设查询结果与指定的类型完全匹配。如果查询结果的列名与对象的属性名不完全一致,或者需要进行更复杂的结果映射,你可以考虑使用 resultMap 进行手动映射。

4.1 返回字典映射:resultMap

resultMap 使用场景:

字段名称与程序中的属性名不同的情况,可使用resultMap配置映射;

一对一和一对多关系可以使用resultMap映射并查询数据。

字段名和属性名不同的情况:

程序中的属性如下:

这个时候使用resultMap

mapper.xml 代码如下:

<resultMap id="BaseMap" type="com.example.demo.model.User">
    <id column="id" property="id"> </id>
    <result column="username" property="username"></result>
    <result column="pasword" property="pwd"></result>
</resultMap>
<select id="getUserById" resultMap="BaseMap">
    select * from userinfo where id=#{id}
</select>    

五、 多表查询 ( 使用@Results 注解的方式)

一对一关系:

一对一关系指的是两个表之间存在唯一的关联关系,其中一个表的一条记录对应另一个表的一条记录。在数据库中,通常使用外键来建立一对一关系。

示例案例:

假设有两个表:user 和 user_profile。每个用户只有一个用户资料。这里,user 表包含用户的基本信息,user_profile 表包含用户的详细资料。这两个表通过 user_id 字段建立了一对一关系。

CREATE TABLE user (
  id INT PRIMARY KEY,
  username VARCHAR(50),
  ...
);

CREATE TABLE user_profile (
  id INT PRIMARY KEY,
  user_id INT UNIQUE,
  full_name VARCHAR(100),
  ...
);

在 MyBatis 中,可以使用一对一关系进行联合查询,并将结果映射到一个对象中。以下是一个示例:

public class User {
  private int id;
  private String username;
  private UserProfile profile;
  // getter and setter methods
}

public class UserProfile {
  private int id;
  private int userId;
  private String fullName;
  // getter and setter methods
}
<!-- Mapper 接口 -->
public interface UserMapper {
  @Select("SELECT u.id, u.username, p.id as 'profile.id', p.full_name as 'profile.fullName' " +
          "FROM user u " +
          "JOIN user_profile p ON u.id = p.user_id " +
          "WHERE u.id = #{userId}")
  @Results({
      @Result(property = "id", column = "id"),
      @Result(property = "username", column = "username"),
      @Result(property = "profile.id", column = "profile.id"),
      @Result(property = "profile.fullName", column = "profile.fullName")
  })
  User getUserWithProfileById(@Param("userId") int userId);
}

在上述,User类代表用户,UserProfile 类代表用户资料,User类中包含一个UserProfile对象用于表示一对一关系

在UserMapper接口中,使用联合查询语句将user表与user_profile表连在一起,并使用@Results注释进行结果映射,

通过指定每个属性的映射关系,将查询结果正确的映射到User对象及其关联的UserProfile对象中。

一对多关系:

一对多关系指的是两个表之间存在一个对多关系,其中一个表的一条记录对应另一个表的多条记录。在数据库中,通常使用外键来建立一对多关系。

示例案例:

假设有两个表:department 和 employee。每个部门可以有多个员工。这里,department 表包含部门的信息,employee 表包含员工的信息,并通过 department_id 字段建立了一对多关系

CREATE TABLE department (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  ...
);

CREATE TABLE employee (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  department_id INT,
  ...
);

在MyBatis中,可以使用一对多关系进行联合查询,并将结果映射到一个对象中,其中一个对象包含一个集合来表示多的一方,以下为示例:

public class Department {
  private int id;
  private String name;
  private List<Employee> employees;
  // getter and setter methods
}

public class Employee {
  private int id;
  private String name;
  // getter and setter methods
}

Department 类代表部门,Employee 类代表员工。Department 类中包含一个 List 对象用于表示一对多关系。

<!-- Mapper 接口 -->
public interface DepartmentMapper {
  @Select("SELECT d.id, d.name, e.id as 'employees.id', e.name as 'employees.name' " +
          "FROM department d " +
          "LEFT JOIN employee e ON d.id = e.department_id " +
          "WHERE d.id = #{departmentId}")
  @Results({
      @Result(property = "id", column = "id"),
      @Result(property = "name", column = "name"),
      @Result(property = "employees", column = "id", javaType = List.class, many = @Many(select = "getEmployeesByDepartmentId"))
  })
  Department getDepartmentWithEmployeesById(@Param("departmentId") int departmentId);

  @Select("SELECT id, name FROM employee WHERE department_id = #{departmentId}")
  List<Employee> getEmployeesByDepartmentId(@Param("departmentId") int departmentId);
}

在 DepartmentMapper 接口中,使用联合查询语句将 department 表和 employee 表连接在一起,并使用 @Results 注解进行结果映射。通过指定每个属性的映射关系,将查询结果正确地映射到 Department 对象及其关联的员工集合中。

另外,通过在 @Results 注解中指定 javaType = List.class 和 many = @Many,将 getEmployeesByDepartmentId 方法与 employees 属性建立关联,并在该方法中查询指定部门的所有员工。

这样,在调用 getDepartmentWithEmployeesById 方法时,将返回一个 Department 对象,其中包含部门的信息和关联的员工列表。

总结:

一对一和一对多关系是多表查询中常见的关系类型。使用 MyBatis 可以方便地处理这些关系,通过正确的结果映射,可以将查询结果准确地映射到相应的对象及其关联对象中。

 六、一对一 MyBatis注解的方式实现多表查询

使用 MyBatis 注解方式实现多表查询可以通过以下步骤进行:

定义结果对象(POJO):首先,你需要定义一个结果对象来保存多表查询的结果。该对象应该包含你想要从多个表中检索的字段,并提供相应的 getter 和 setter 方法。

编写 SQL 查询语句:使用注解方式,你可以在 Mapper 接口的方法上直接编写 SQL 查询语句。在查询语句中,可以使用 JOIN 操作符来连接多个表,并选择需要的字段。

声明方法和参数:在 Mapper 接口中声明一个方法,并使用注解来指定对应的 SQL 查询语句和参数。方法的返回类型应该与结果对象一致,或者是结果对象的集合。

案例展示:

// 结果对象
public class UserOrder {
    private int userId;
    private String username;
    private String orderNumber;
    // 其他属性和对应的 getter/setter 方法
}

// Mapper 接口
@Mapper
public interface UserDao {
    @Select("SELECT u.user_id, u.username, o.order_number " +
            "FROM user u " +
            "JOIN orders o ON u.user_id = o.user_id " +
            "WHERE u.user_id = #{userId}")
    UserOrder getUserOrderById(@Param("userId") int userId);
}

上述示例中,

1.定义结果对象UserOrder,包含userId,username,orderNumber等属性,提供相应的getter与setter方法

2.Mapper接口中使用@Select 注解编写了一个SQL查询语句,使用JOIN操作符连接了user表与orders表,并选择了需要的字段

3.最后声明方法getUserOrderById,并使用@Param注解来指定方法参数与SQL查询语句中参数的对应关系

通过以上步骤,你就可以使用注解方式实现多表查询,并通过调用相应的方法获取查询结果

resultMap手动映射查询结果:

通过定义 resultMap,你可以明确指定查询结果与对象属性之间的映射关系,以及进行一些高级的结果处理。

  1. 指定查询结果与对象属性的映射关系:你可以定义每个属性与查询结果列之间的映射关系,包括列名、属性名、类型转换等。
  2. 处理复杂的结果映射:当查询结果与对象的结构不完全匹配时,你可以使用

 resultMap 进行复杂的结果映射,例如嵌套对象、一对多关系等。

     3.执行高级的结果处理逻辑:你可以在

 resultMap 中定义一些高级的结果处理逻辑,例如使用自定义的类型处理器、使用 SQL 函数进行计算、调用对象的方法等。

下面是案例:

<!-- Mapper XML -->
<resultMap id="userResultMap" type="com.example.User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name" />
  <result property="email" column="user_email" />
</resultMap>

<select id="getUserByUsername" parameterType="String" resultMap="userResultMap">
  SELECT user_id, user_name, user_email FROM user WHERE username LIKE CONCAT('%', #{username}, '%')
</select>

首先定义了一个名为 userResultMap 的 resultMap,类型为com.example.User

resultMap 中定义每个属性与查询结果列之间的映射关系,

使用property属性指定对象属性,使用column属性指定查询结果列(指定数据库列的属性名称)

最后,在查询语句中使用 resultMap="userResultMap" 指定使用该 resultMap 进行结果映射。

使用 resultMap 进行手动映射可以更加灵活地处理查询结果,尤其是在复杂的映射关系和结果处理逻辑时。

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值