MyBatis中实现一对多和多对一的处理

  1. 所谓的一对多就是一个对象对待多个对象,就如同我们的一个老师要教多个学生一样;
  2. 而所谓的多对一就是多个对象对待一个对象,就如同多个学生要和一个老师学习一样;

一对多应用需要用  collection  处理

1.创建编译环境

public class Teacher {
    private int id;
    private String name;

    //一个老师对应对个学生
    private List<Student> students;
}

2.编写接口

package com.zhang.dao;

import com.zhang.pojo.Teacher;

public interface TeacherDao {

    //获得一个老师下的所有学生信息; 老师是包含学生的集合;
    Teacher getTeacher(int id);

    Teacher getTeacherTwo(int id);
}

3.编写对应的mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zhang.dao.TeacherDao">
    <!--一对多的处理-->
    <!--面向对象方式解决-->
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.name sname,s.id sid,t.id tid, t.name tname
        from mybatis.student as s,mybatis.teacher as t
        where s.tid = t.id and t.id = #{id}
    </select>
    <resultMap id="TeacherStudent" type="Teacher">
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <id property="id" column="sid"/>
            <result property="name" column="sname"/>
        </collection>
    </resultMap>

    <!--数据库思想-->
    <select id="getTeacherTwo" resultMap="TeacherStudent2">
        select * from mybatis.teacher where id = #{id}
    </select>
    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="T2"/>
    </resultMap>
    <select id="T2" resultType="Student">
        select * from mybatis.student where tid = #{id}
    </select>

</mapper>

4.编写测试类

package com.zhang.dao;

import com.zhang.pojo.Teacher;
import com.zhang.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;


public class TeacherDaoTest {
    @Test
    public void getTeacher(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
        Teacher teacher = mapper.getTeacher(1);

        System.out.println(teacher.getName());
        System.out.println(teacher.getStudents());
    }

    @Test
    public void getTeacherTwo(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
        Teacher teacher = mapper.getTeacherTwo(1);

        System.out.println(teacher.getName());
        System.out.println(teacher.getStudents());
    }
}

多对一处理需要使用  assocation  标签关联数据库处理

在mybatis中处理多对一的时候,使用的是关联映射的思想处理;一般使用数据库思想(联表查询),oop思想(关联对象)

处理方式一:

1.编写接口代码

List<Student> getStudents();

2.编写与数据库关联的查询

<!--遇到问题:学生类中关联老师: 多个学生对应一个老师 -->
<!--<select id="getStudents" resultType="Student">-->
    <!--select s.id,s.name,t.name from mybatis.student as s,mybatis.teacher as t-->
    <!--where s.tid = t.id-->
<!--</select>-->


<!--按查询结果嵌套处理,模拟数据库思想;
-->
<select id="getStudents" resultMap="StudentTeacher">
    select * from mybatis.student
</select>

<resultMap id="StudentTeacher" type="Student">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <!--属性和字段对应  , 类和表对应  , 对象和记录
    关联一个字段
    需求:拿到老师这个类的属性

    association : 关联,多对一
        column : 数据库对应的列名
        property : 对应属性名
        javaType : 多对一字段对应的Java类型
        select : 关联一个语句
    -->
    <association column="tid" property="teacher" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
    select * from mybatis.teacher where id = #{id}
</select>

3.编写测试类

public void UserTest(){
@Test
    public void getStudents(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        List<Student> students = mapper.getStudents();
        for (Student student : students) {
            System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
        }
  }
  }

处理方式二:

1.编写接口

List<Student> getStudentsTwo();

2.编写对应的配置文件

<!-- 一个resultMap解决 , 模拟面向对象的思想-->
<select id="getStudentsTwo" resultMap="StudentTeacher2">
    select s.id,s.name,t.name as tname from mybatis.student as s, mybatis.teacher as t
    where s.tid = t.id
</select>

<!--设置结果集映射ResultMap -->
<resultMap id="StudentTeacher2" type="Student">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <!--直接关联一个老师-->
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

3.编写测试类

public void UserTest(){
@Test
public void getStudentsTwo(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao mapper = sqlSession.getMapper(StudentDao.class);
    List<Student> students = mapper.getStudentsTwo();
    for (Student student : students) {
        System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
    }
}
}

动态SQL&缓存

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。

动态SQL就是指根据不同查询条件,生成不同的SQL语句

在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

if

参数test:里面的表达式如果为ture则执行,否则不执行

if(title != null)
<if test="title != null">
AND title like #{title}
</if>

choose

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
    
    
    switch (exp){
    	case 1:
    		break;
    	case 2:
    		break;
    }
    
</select>

trim[where,set]

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>
<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

foreach

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

编译代码测试

1.编写接口

//模糊查询,可以通过自定义条件查询
List<User> getUserByLike(Map<String,Object> map);

2.编写配置文件的映射文件

<select id="getUser" resultType="User">
    select * from mybatis.user
</select>

<select id="getUserByLike" resultType="User" parameterType="Map">
    select * from mybatis.user
    <where>
        <if test="name!=null">
            name like CONCAT('%',#{name},'%')
        </if>
        <if test="id!=null">
            and id = #{id}
        </if>
    </where>
</select>

3.编写测试类

@Test
public void getUserByLike(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    UserDao mapper = sqlSession.getMapper(UserDao.class);

    Map<String,Object> map = new HashMap<String,Object>();

    map.put("name","秦");
    map.put("id",1);

    List<User> users = mapper.getUserByLike(map);
    for (User user : users) {
        System.out.println(user);
    }
}

如果是太过复杂的逻辑不建议使用动态的SQL,

缓存

在开启缓存前需要在映射文件中 ,添加一个标签

<!--开启缓存-->
<cache/>

如果CRUD操作要结果需要缓存。可以使用useCache;

<!--
useCache: 是否开启缓存
使用缓存可以解决问题:
    查询出来的结果暂时保存着,消耗内存资源;
    如果短时间查询同样的语句比较多,可以提高速度;
-->
<select id="getUser" resultType="User" useCache="true">
    select * from mybatis.user
</select>

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要使用 MyBatis Plus 实现一对多查询,你可以使用 MyBatis Plus 提供的 `@TableField` 注解和 `@TableName` 注解来定义关联关系。下面是一个示例: ```java // 定义主表实体类 @TableName("order") public class Order { @TableId private Long id; private String orderNo; // 定义关联字段 @TableField(exist = false) private List<OrderItem> orderItems; // getter 和 setter 方法 } // 定义关联表实体类 @TableName("order_item") public class OrderItem { @TableId private Long id; private Long orderId; private String productName; // getter 和 setter 方法 } ``` 然后,你可以使用 MyBatis Plus 提供的方法来进行一对多查询。下面是一个示例: ```java public List<Order> getOrdersWithItems() { return orderMapper.selectList(new QueryWrapper<Order>().lambda().list().stream() .map(order -> { order.setOrderItems(orderItemMapper.selectList(new QueryWrapper<OrderItem>() .lambda() .eq(OrderItem::getOrderId, order.getId()))); return order; }) .collect(Collectors.toList())); } ``` 在这个示例,我们首先使用 `orderMapper.selectList()` 查询出所有的主表记录,并使用 Java 8 的流式操作进行处理。在流的 `map` 操作,我们通过 `order.getId()` 获取当前订单的 ID,然后使用 `orderItemMapper.selectList()` 查询关联表的所有记录,并将其设置到 `order` 对象的 `orderItems` 属性。最后,我们通过 `collect(Collectors.toList())` 方法将结果收集为一个 `List<Order>`。 这样,我们就可以在一对多查询获取到所有主表记录以及对应的关联表记录。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值