SSM - Springboot - sistema full stack MyBatis-Plus (16)

Capítulo 3MyBatis

3. Mapeamento de múltiplas tabelas MyBatis

2. Mapeamento um para um

2.1 Descrição dos requisitos
  • Consulte o pedido com base no ID e nas informações do usuário associado ao pedido!
2.2 Interface do OrderMapper
public interface OrderMapper {
    
    
  Order selectOrderWithCustomer(Integer orderId);
}
2.3 Arquivo de configuração OrderMapper.xml
<!-- 创建resultMap实现“对一”关联关系映射 -->
<!-- id属性:通常设置为这个resultMap所服务的那条SQL语句的id加上“ResultMap” -->
<!-- type属性:要设置为这个resultMap所服务的那条SQL语句最终要返回的类型 -->
<resultMap id="selectOrderWithCustomerResultMap" type="order">

  <!-- 先设置Order自身属性和字段的对应关系 -->
  <id column="order_id" property="orderId"/>

  <result column="order_name" property="orderName"/>

  <!-- 使用association标签配置“对一”关联关系 -->
  <!-- property属性:在Order类中对一的一端进行引用时使用的属性名 -->
  <!-- javaType属性:一的一端类的全类名 -->
  <association property="customer" javaType="customer">

    <!-- 配置Customer类的属性和字段名之间的对应关系 -->
    <id column="customer_id" property="customerId"/>
    <result column="customer_name" property="customerName"/>

  </association>

</resultMap>

<!-- Order selectOrderWithCustomer(Integer orderId); -->
<select id="selectOrderWithCustomer" resultMap="selectOrderWithCustomerResultMap">

  SELECT order_id,order_name,c.customer_id,customer_name
  FROM t_order o
  LEFT JOIN t_customer c
  ON o.customer_id=c.customer_id
  WHERE o.order_id=#{orderId}

</select>
  • Para o relacionamento correspondente, consulte a figura abaixo:

Insira a descrição da imagem aqui

2.4 Arquivo mapeador de registro global Mybatis
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>

  <!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>

</mappers>
Programa de teste de 2,5 junho
@Slf4j
public class MyBatisTest {
    
    

    private SqlSession session;
    // junit会在每一个@Test方法前执行@BeforeEach方法

    @BeforeEach
    public void init() throws IOException {
    
    
        session = new SqlSessionFactoryBuilder()
                .build(
                        Resources.getResourceAsStream("mybatis-config.xml"))
                .openSession();
    }

    @Test
    public void testRelationshipToOne() {
    
    

      OrderMapper orderMapper = session.getMapper(OrderMapper.class);
      // 查询Order对象,检查是否同时查询了关联的Customer对象
      Order order = orderMapper.selectOrderWithCustomer(2);
      log.info("order = " + order);

    }

    // junit会在每一个@Test方法后执行@@AfterEach方法
    @AfterEach
    public void clear() {
    
    
        session.commit();
        session.close();
    }
}
2.6 Palavras-chave
  • Na associação "um para um", temos muitas configurações, mas as únicas palavras-chave são: associação e javaType

3. Mapeamento para muitos

3.1 Descrição dos requisitos
  • Consulte clientes e informações de pedidos relacionados ao cliente!
3.2 Interface do CustomerMapper
public interface CustomerMapper {
    
    

  Customer selectCustomerWithOrderList(Integer customerId);

}
3.3 Arquivo CustomerMapper.xml
<!-- 配置resultMap实现从CustomerOrderList的“对多”关联关系 -->
<resultMap id="selectCustomerWithOrderListResultMap"

  type="customer">

  <!-- 映射Customer本身的属性 -->
  <id column="customer_id" property="customerId"/>

  <result column="customer_name" property="customerName"/>

  <!-- collection标签:映射“对多”的关联关系 -->
  <!-- property属性:在Customer类中,关联“多”的一端的属性名 -->
  <!-- ofType属性:集合属性中元素的类型 -->
  <collection property="orderList" ofType="order">

    <!-- 映射Order的属性 -->
    <id column="order_id" property="orderId"/>

    <result column="order_name" property="orderName"/>

  </collection>

</resultMap>

<!-- Customer selectCustomerWithOrderList(Integer customerId); -->
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
  SELECT c.customer_id,c.customer_name,o.order_id,o.order_name
  FROM t_customer c
  LEFT JOIN t_order o
  ON c.customer_id=o.customer_id
  WHERE c.customer_id=#{
    
    customerId}
</select>
  • Para o relacionamento correspondente, consulte a figura abaixo:

Insira a descrição da imagem aqui

3.4 Arquivo mapeador de registro global Mybatis
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
  <!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>
  <mapper resource="mappers/CustomerMapper.xml"/>
</mappers>
Programa de teste de 3,5 junho
@Test
public void testRelationshipToMulti() {
    
    

  CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
  // 查询Customer对象同时将关联的Order集合查询出来
  Customer customer = customerMapper.selectCustomerWithOrderList(1);
  log.info("customer.getCustomerId() = " + customer.getCustomerId());
  log.info("customer.getCustomerName() = " + customer.getCustomerName());
  List<Order> orderList = customer.getOrderList();
  for (Order order : orderList) {
    
    
    log.info("order = " + order);
  }
}
3.6 Palavras-chave
  • No relacionamento “para-muitos”, também existem muitas configurações, mas as mais críticas são: “coleção” e “ofType”

4. Resumo do mapeamento multitabelas

4.1 Otimização de mapeamento multitabela
atributo de configuração Atribuir significado Valor opcional valor padrão
autoMappingBehavior Especifica como MyBatis deve mapear colunas automaticamente para campos ou propriedades. NONE significa desativar o mapeamento automático; PARTIAL mapeará automaticamente apenas os campos que não possuem mapeamentos de resultados aninhados definidos. FULL mapeia automaticamente qualquer conjunto de resultados complexo (aninhado ou não). NENHUM, PARCIAL, COMPLETO PARCIAL
  • Podemos definir autoMappingBehavior como completo e, ao executar o mapeamento resultMap de várias tabelas, podemos omitir a tag de resultado que está em conformidade com as regras de mapeamento de nomenclatura de colunas e atributos (nome da coluna = nome do atributo ou ativar o mapeamento de caso de camelo ou personalizar o mapeamento) !

  • Modifique mybatis-sconfig.xml:

<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>
  • Modifique teacherMapper.xml
<resultMap id="teacherMap" type="teacher">
    <id property="tId" column="t_id" />
    <!-- 开启自动映射,并且开启驼峰式支持!可以省略 result!-->
<!--        <result property="tName" column="t_name" />-->
    <collection property="students" ofType="student" >
        <id property="sId" column="s_id" />
<!--            <result property="sName" column="s_name" />-->
    </collection>
</resultMap>
4.2 Resumo do mapeamento multitabelas
relação de conexão Palavras-chave do item de configuração Arquivo de configuração e local específico
Um a um tag de associação/atributo javaType/atributo de propriedade Dentro da tag resultMap no arquivo de configuração do Mapper
para muitos tag de coleção/atributo ofType/atributo de propriedade Dentro da tag resultMap no arquivo de configuração do Mapper

4. Declarações dinâmicas MyBatis

1. Requisitos e introdução da declaração dinâmica

  • Muitas vezes encontramos muitas situações em que as consultas são feitas com base em muitas condições de consulta, como a procura de emprego no Zhaopin Recruitment. Muitas vezes há situações em que muitas condições não têm valor.Como devemos completar a instrução SQL final em segundo plano?

Insira a descrição da imagem aqui

  • SQL dinâmico é um dos recursos poderosos do MyBatis. Se utilizou JDBC ou outras estruturas semelhantes,deve compreender como é doloroso unir instruções SQL de acordo com diferentes condições.Por exemplo,certifique-se de não se esquecer de adicionar os espaços necessários ao unir,e tenha cuidado para remover a vírgula do último nome da coluna na lista. Usando SQL dinâmico, você pode se livrar completamente dessa dor.
  • Usar SQL dinâmico não é fácil, mas MyBatis torna esse recurso significativamente mais fácil de usar com a poderosa linguagem SQL dinâmica que pode ser usada em qualquer instrução de mapa SQL.
  • Se você já usou JSTL ou qualquer processador de texto baseado em uma linguagem semelhante a XML, os elementos SQL dinâmicos podem parecer familiares para você. Nas versões anteriores do MyBatis, demorava para entender um grande número de elementos. Com a ajuda de poderosas expressões baseadas em OGNL, MyBatis 3 substituiu a maioria dos elementos anteriores e simplificou bastante os tipos de elementos. Agora, os tipos de elementos a serem aprendidos são menos da metade dos originais.

2. tags se e onde

  • O cenário mais comum para usar SQL dinâmico é incluir parte de uma cláusula where/if baseada em condições. por exemplo:
<!-- List<Employee> selectEmployeeByCondition(Employee employee); -->
<select id="selectEmployeeByCondition" resultType="employee">
    select emp_id,emp_name,emp_salary from t_emp
    <!-- where标签会自动去掉“标签体内前面多余的and/or” -->
    <where>
        <!-- 使用if标签,让我们可以有选择的加入SQL语句的片段。这个SQL语句片段是否要加入整个SQL语句,就看if标签判断的结果是否为true -->
        <!-- 在if标签的test属性中,可以访问实体类的属性,不可以访问数据库表的字段 -->
        <if test="empName != null">
            <!-- 在if标签内部,需要访问接口的参数时还是正常写#{} -->
            or emp_name=#{empName}
        </if>
        <if test="empSalary &gt; 2000">
            or emp_salary>#{empSalary}
        </if>
        <!--
         第一种情况:所有条件都满足 WHERE emp_name=? or emp_salary>?
         第二种情况:部分条件满足 WHERE emp_salary>?
         第三种情况:所有条件都不满足 没有where子句
         -->
    </where>
</select>

3. definir etiqueta

<!-- void updateEmployeeDynamic(Employee employee) -->
<update id="updateEmployeeDynamic">
    update t_emp
    <!-- set emp_name=#{empName},emp_salary=#{empSalary} -->
    <!-- 使用set标签动态管理set子句,并且动态去掉两端多余的逗号 -->
    <set>
        <if test="empName != null">
            emp_name=#{empName},
        </if>
        <if test="empSalary &lt; 3000">
            emp_salary=#{empSalary},
        </if>
    </set>
    where emp_id=#{empId}
    <!--
         第一种情况:所有条件都满足 SET emp_name=?, emp_salary=?
         第二种情况:部分条件满足 SET emp_salary=?
         第三种情况:所有条件都不满足 update t_emp where emp_id=?
            没有set子句的update语句会导致SQL语法错误
     -->
</update>

4. etiqueta de corte (entenda)

  • Use a tag trim para controlar se ambas as extremidades da parte condicional contêm determinados caracteres

    • atributo prefixo: especifica o prefixo a ser adicionado dinamicamente
    • atributo suffix: especifica o sufixo a ser adicionado dinamicamente
    • Atributo prefixOverrides: Especifique o prefixo a ser removido dinamicamente, use "|" para separar possíveis valores múltiplos
    • Atributo suffixOverrides: Especifique o sufixo a ser removido dinamicamente, use "|" para separar possíveis valores múltiplos
<!-- List<Employee> selectEmployeeByConditionByTrim(Employee employee) -->
<select id="selectEmployeeByConditionByTrim" resultType="com.atguigu.mybatis.entity.Employee">
    select emp_id,emp_name,emp_age,emp_salary,emp_gender
    from t_emp

    <!-- prefix属性指定要动态添加的前缀 -->
    <!-- suffix属性指定要动态添加的后缀 -->
    <!-- prefixOverrides属性指定要动态去掉的前缀,使用“|”分隔有可能的多个值 -->
    <!-- suffixOverrides属性指定要动态去掉的后缀,使用“|”分隔有可能的多个值 -->
    <!-- 当前例子用where标签实现更简洁,但是trim标签更灵活,可以用在任何有需要的地方 -->
    <trim prefix="where" suffixOverrides="and|or">
        <if test="empName != null">
            emp_name=#{empName} and
        </if>
        <if test="empSalary &gt; 3000">
            emp_salary>#{empSalary} and
        </if>
        <if test="empAge &lt;= 20">
            emp_age=#{empAge} or
        </if>
        <if test="empGender=='male'">
            emp_gender=#{empGender}
        </if>
    </trim>
</select>

5. escolha / quando / caso contrário marque

  • Entre as múltiplas condições de ramificação, apenas uma é executada.

    • Execute julgamentos condicionais sequencialmente de cima para baixo
    • A primeira ramificação encontrada que satisfaça a condição será tomada
    • Filiais seguintes à filial adotada não serão consideradas
    • Se todas as ramificações quando não forem satisfeitas, execute a ramificação caso contrário
<!-- List<Employee> selectEmployeeByConditionByChoose(Employee employee) -->
<select id="selectEmployeeByConditionByChoose" resultType="com.atguigu.mybatis.entity.Employee">
    select emp_id,emp_name,emp_salary from t_emp
    where
    <choose>
        <when test="empName != null">emp_name=#{empName}</when>
        <when test="empSalary &lt; 3000">emp_salary &lt; 3000</when>
        <otherwise>1=1</otherwise>
    </choose>

    <!--
     第一种情况:第一个when满足条件 where emp_name=?
     第二种情况:第二个when满足条件 where emp_salary < 3000
     第三种情况:两个when都不满足 where 1=1 执行了otherwise
     -->
</select>

6. etiqueta foreach

6.1 Uso básico
  • Exemplo usando inserção em lote
<!--
    collection属性:要遍历的集合
    item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象
    separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符
    open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串
    close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串
    index属性:这里起一个名字,便于后面引用
        遍历List集合,这里能够得到List集合的索引值
        遍历Map集合,这里能够得到Map集合的key
 -->
<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
    <!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
    (#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
</foreach>
6.2 Coisas a serem observadas ao atualizar em lote
  • O exemplo acima de inserção em lote é essencialmente uma instrução SQL, enquanto a implementação da atualização em lote requer que várias instruções SQL sejam reunidas e separadas por ponto e vírgula. Ou seja, várias instruções SQL são enviadas ao mesmo tempo para execução do banco de dados. Neste momento, você precisa definir o endereço URL das informações de conexão do banco de dados:
alex.dev.url=jdbc:mysql:///mybatis-example?allowMultiQueries=true
  • A tag foreach correspondente é a seguinte:
<!-- int updateEmployeeBatch(@Param("empList") List<Employee> empList) -->
<update id="updateEmployeeBatch">
    <foreach collection="empList" item="emp" separator=";">
        update t_emp set emp_name=#{emp.empName} where emp_id=#{emp.empId}
    </foreach>
</update>
6.3 Sobre o atributo de coleção da tag foreach
  • Se a anotação @Param não for usada para especificar um nome específico para o parâmetro do tipo Lista na interface, então coleção ou lista poderá ser usada por padrão no atributo de coleção para se referir à coleção de lista. Isso pode ser visto através das informações de exceção:
Parameter 'empList' not found. Available parameters are [arg0, collection, list]
  • No desenvolvimento real, para evitar certos mal-entendidos causados ​​por expressões obscuras, é recomendado usar a anotação @Param para declarar claramente o nome da variável e, em seguida, referenciar os parâmetros recebidos no atributo de coleção da tag foreach de acordo com o nome especificado pela anotação @Param.

7. fragmento SQL

7.1 Extraia fragmentos SQL duplicados
<!-- 使用sql标签抽取重复出现的SQL片段 -->
<sql id="mySelectSql">
    select emp_id,emp_name,emp_age,emp_salary,emp_gender from t_emp
</sql>
7.2 Faça referência ao fragmento SQL extraído
<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>

Guess you like

Origin blog.csdn.net/sgsgkxkx/article/details/133499371