SSM - Springboot - Sistema de pila completa MyBatis-Plus (16)

Capítulo 3MyBatis

3. Mapeo de tablas múltiples MyBatis

2. Mapeo uno a uno

2.1 Descripción de requisitos
  • ¡Consulta el pedido en función del ID y la información del usuario asociado al pedido!
2.2 Interfaz OrderMapper
public interface OrderMapper {
    
    
  Order selectOrderWithCustomer(Integer orderId);
}
2.3 Archivo de configuración 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 conocer la relación correspondiente, consulte la siguiente figura:

Insertar descripción de la imagen aquí

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

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

</mappers>
Programa de prueba 2.5 junit
@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 Palabras clave
  • En la asociación "uno a uno", tenemos muchas configuraciones, pero las únicas palabras clave son: asociación y javaType

3. Mapeo de muchos

3.1 Descripción de requisitos
  • ¡Consulte clientes e información de pedidos relacionados con los clientes!
3.2 Interfaz de CustomerMapper
public interface CustomerMapper {
    
    

  Customer selectCustomerWithOrderList(Integer customerId);

}
3.3 Archivo 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 conocer la relación correspondiente, consulte la siguiente figura:

Insertar descripción de la imagen aquí

3.4 Archivo Mapper de registro global de Mybatis
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
  <!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>
  <mapper resource="mappers/CustomerMapper.xml"/>
</mappers>
Programa de prueba 3.5 junit
@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 Palabras clave
  • En la relación "a muchos", también hay muchas configuraciones, pero las más críticas son: "colección" y "ofType"

4. Resumen del mapeo de tablas múltiples

4.1 Optimización del mapeo de múltiples tablas
atributo de configuración Significado del atributo Valor opcional valor por defecto
comportamiento de mapeo automático Especifica cómo MyBatis debería asignar automáticamente columnas a campos o propiedades. NONE significa desactivar la asignación automática; PARTIAL solo asignará automáticamente campos que no tengan asignaciones de resultados anidadas definidas. FULL asigna automáticamente cualquier conjunto de resultados complejo (anidado o no). NINGUNO, PARCIAL, COMPLETO PARCIAL
  • Podemos configurar autoMappingBehavior al máximo y, al realizar el mapeo resultMap de varias tablas, podemos omitir la etiqueta de resultado que se ajusta a las reglas de mapeo de nombres de atributos y columnas (nombre de columna = nombre de atributo, o activar el mapeo de casos de camello o personalizar el mapeo) !

  • Modifique mybatis-sconfig.xml:

<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>
  • Modificar profesorMapper.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 Resumen del mapeo de tablas múltiples
relación de conexión Palabras clave del elemento de configuración Archivo de configuración y ubicación específica.
Cara a cara etiqueta de asociación/atributo javaType/atributo de propiedad Dentro de la etiqueta resultMap en el archivo de configuración de Mapper
demasiados etiqueta de colección/atributo ofType/atributo de propiedad Dentro de la etiqueta resultMap en el archivo de configuración de Mapper

4. Declaraciones dinámicas MyBatis

1. Requisitos e introducción de la declaración dinámica

  • A menudo nos encontramos con muchas situaciones en las que las consultas se realizan en función de muchas condiciones de consulta, como la búsqueda de empleo en Zhaopin Recruitment. A menudo hay situaciones en las que muchas condiciones no tienen valor ¿Cómo debemos completar la declaración SQL final en segundo plano?

Insertar descripción de la imagen aquí

  • SQL dinámico es una de las poderosas características de MyBatis. Si ha utilizado JDBC u otros marcos similares, debe comprender lo doloroso que es unir declaraciones SQL de acuerdo con diferentes condiciones. Por ejemplo, asegúrese de no olvidar agregar los espacios necesarios al unir y tenga cuidado de eliminar la coma del último nombre de columna en la lista. Con SQL dinámico, puede deshacerse completamente de este dolor.
  • Trabajar con SQL dinámico no es fácil, pero MyBatis hace que esta característica sea mucho más fácil de usar con el poderoso lenguaje SQL dinámico que se puede usar en cualquier declaración asignada de SQL.
  • Si ha utilizado JSTL o cualquier procesador de texto basado en un lenguaje similar a XML antes, los elementos SQL dinámicos pueden resultarle familiares. En versiones anteriores de MyBatis, se necesitaba tiempo para comprender una gran cantidad de elementos. Con la ayuda de potentes expresiones basadas en OGNL, MyBatis 3 ha reemplazado la mayoría de los elementos anteriores y ha simplificado enormemente los tipos de elementos. Ahora los tipos de elementos a aprender son menos de la mitad de los originales.

2. etiquetas si y dónde

  • El escenario más común para usar SQL dinámico es incluir parte de una cláusula dónde/si basada en condiciones. Por ejemplo:
<!-- 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. establecer 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 recorte (comprender)

  • Utilice la etiqueta de recorte para controlar si ambos extremos de la parte condicional contienen ciertos caracteres

    • atributo de prefijo: especifica el prefijo que se agregará dinámicamente
    • atributo de sufijo: especifica el sufijo que se agregará dinámicamente
    • Atributo prefixOverrides: especifique el prefijo que se eliminará dinámicamente, utilice "|" para separar posibles valores múltiples
    • Atributo suffixOverrides: especifique el sufijo que se eliminará dinámicamente, utilice "|" para separar posibles valores múltiples
<!-- 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. elegir / cuando / de lo contrario etiquetar

  • Entre múltiples condiciones de bifurcación, solo se ejecuta una.

    • Realizar juicios condicionales secuencialmente de arriba a abajo.
    • Se tomará la primera rama encontrada que cumpla la condición.
    • Las ramas siguientes a la rama adoptada no serán consideradas.
    • Si no se cumplen todas las ramas cuando, ejecute la rama de lo contrario
<!-- 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 para cada uno

6.1 Uso básico
  • Ejemplo de uso de inserción por lotes
<!--
    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 Cosas a tener en cuenta al actualizar por lotes
  • El ejemplo anterior de inserción por lotes es esencialmente una declaración SQL, mientras que la implementación de la actualización por lotes requiere que se reúnan varias declaraciones SQL y se separen por punto y coma. Es decir, se envían varias declaraciones SQL a la vez para que las ejecute la base de datos. En este momento, debe configurar la dirección URL de la información de conexión de la base de datos:
alex.dev.url=jdbc:mysql:///mybatis-example?allowMultiQueries=true
  • La etiqueta foreach correspondiente es la siguiente:
<!-- 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 Acerca del atributo de colección de la etiqueta foreach
  • Si la anotación @Param no se usa para especificar un nombre específico para el parámetro de tipo Lista en la interfaz, entonces se puede usar colección o lista de manera predeterminada en el atributo de colección para hacer referencia a la colección de listas. Esto se puede ver a través de la información de excepción:
Parameter 'empList' not found. Available parameters are [arg0, collection, list]
  • En el desarrollo real, para evitar ciertos malentendidos causados ​​por expresiones oscuras, se recomienda utilizar la anotación @Param para declarar claramente el nombre de la variable y luego hacer referencia a los parámetros entrantes en el atributo de colección de la etiqueta foreach de acuerdo con nombre especificado por la anotación @Param.

Siete, fragmento sql

7.1 Extraer 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 Hacer referencia al fragmento SQL extraído
<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>

Supongo que te gusta

Origin blog.csdn.net/sgsgkxkx/article/details/133499371
Recomendado
Clasificación