Mybatis (tres) configura la operación básica de mapper.xml

Referencia: https://www.cnblogs.com/wuzhenzhao/p/11101555.html

Archivo de mapeo XML

  Este artículo hace referencia al sitio web oficial chino mybatis para obtener un resumen del aprendizaje: http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html

  El verdadero poder de MyBatis radica en su declaración de mapeo, que es su magia. Debido a su poder excepcional, el archivo XML del mapeador es relativamente simple. Si lo compara con el código JDBC con la misma función, inmediatamente encontrará que casi el 95% del código se guarda. MyBatis está diseñado para enfocarse en SQL para reducir el problema lo más posible.

  El archivo de mapeo SQL tiene solo unos pocos elementos de nivel superior (enumerados en el orden en que deben definirse):

  •  configuración de caché - caché para un espacio de nombres dado.
  • cache-ref  -una referencia a la configuración de caché de otros espacios de nombres.
  • resultMap  -es el elemento más complejo y poderoso utilizado para describir cómo cargar objetos desde el conjunto de resultados de la base de datos.
  •  bloques de sentencias reutilizables sql a los que pueden hacer referencia otras sentencias.
  • insert  - declaración de inserción de mapa
  • actualizar-  declaración de actualización del mapa
  • eliminar  - declaración de eliminación de mapa
  •  instrucción de consulta select -map

Seleccione

  Las declaraciones de consulta son uno de los elementos más utilizados en MyBatis. La energía de la luz no es de gran valor para almacenar datos en una base de datos. Solo es útil si puede recuperarse nuevamente. La mayoría de las aplicaciones también son más frecuentes que modificadas. Para cada operación de inserción, actualización o eliminación, generalmente hay múltiples operaciones de consulta a intervalos. Este es uno de los principios básicos de MyBatis, y también es la razón por la cual el enfoque y el esfuerzo se colocan en la asignación y la asignación de resultados. El elemento de selección de una consulta simple es muy simple. Por ejemplo:

Código de copia
<resultMap id = "BaseResultMap" type = "blog"> 
     <id column = "bid" property = "bid" jdbcType = "INTEGER" /> 
     <result column = "name" property = "name" jdbcType = "VARCHAR" / > 
     <result column = "author_id" property = "authorId" jdbcType = "INTEGER" /> 
</resultMap> 
<! - ********************** ************************************************** **************** -> 
<! - 简单 查询 -> 
<select id = "selectBlogById" resultMap = "BaseResultMap" StatementType = "PREPARED" useCache = "false" > 
     seleccione * del blog donde bid = # {bid} 
</select>
Código de copia

  # {bid} Esto le dice a MyBatis que cree un parámetro de declaración preparada (PreparedStatement). En JDBC, dicho parámetro se identifica con un "?" en SQL y se pasa a una nueva declaración preparada, Así:

// Código JDBC aproximado, no código MyBatis ... 
String selectBlogById = "SELECT * FROM BLOG WHERE BID =?"; 
PreparedStatement ps = conn.prepareStatement ( selectBlogById); 
ps.setInt (1, bid);

  Por supuesto, usar JDBC significa que se necesita más código para extraer los resultados y asignarlos a la instancia del objeto, y aquí es donde MyBatis le ahorra tiempo. El elemento select le permite configurar muchos atributos para configurar los detalles de cada instrucción.

Código de copia
<select 
  id = "selectPerson" 
  parameterType = "int" 
  parameterMap = "obsoleto" 
  resultType = "hashmap" 
  resultMap = "personResultMap" 
  flushCache = "false" 
  useCache = "true" 
  timeout = "10" 
  fetchSize = "256" 
  StatementType = " PREPARADO " 
  resultSetType =" FORWARD_ONLY ">
Código de copia

   Descripción del atributo relacionado:

Atributos Descripción
carné de identidad Se puede usar un identificador único en el espacio de nombres para referirse a esta declaración.
Parámetro Tipo El nombre completo o el alias de la clase de parámetro que se pasará a esta declaración. Este atributo es opcional porque MyBatis puede inferir los parámetros de la declaración entrante específica a través de TypeHandler. El valor predeterminado no está establecido.
parameterMap Este es un método obsoleto para hacer referencia a un parámetro externo. Utilice la asignación de parámetros en línea y el parámetro parameterType.
resultType El nombre completo o el alias de la clase del tipo deseado devuelto por esta declaración. Tenga en cuenta que si se devuelve una colección, debe establecerse en el tipo contenido en la colección, no en la colección en sí. Puede usar resultType o resultMap, pero no ambos.
resultMap Referencia con nombre a resultMap externo. El mapeo del conjunto de resultados es la característica más poderosa de MyBatis. Si lo comprende a fondo, se pueden resolver muchas situaciones de mapeo complejas. Puede usar resultMap o resultType, pero no ambos.
flushCache Después de establecerlo en verdadero, siempre que se llame a la instrucción, hará que se borre la memoria caché local y la memoria caché secundaria. El valor predeterminado es falso.
useCache Establecerlo en verdadero hará que el resultado de esta declaración sea almacenado en caché por el caché de segundo nivel. El valor predeterminado es verdadero para el elemento select.
se acabó el tiempo Esta configuración es el número de segundos que el controlador espera a que la base de datos devuelva el resultado de la solicitud antes de lanzar una excepción. El valor predeterminado no está establecido (depende de la unidad).
fetchSize Este es un mensaje para el controlador. Intente hacer que el número de filas de resultados devueltos por el controlador en lotes sea igual a este valor de configuración. El valor predeterminado no está establecido (depende de la unidad).
StatementType Uno de DECLARACIÓN, PREPARADO o LLAMABLE. Esto hará que MyBatis use Statement, PreparedStatement o CallableStatement respectivamente, el valor predeterminado es PREPARED.
resultSetType Uno de FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE o DEFAULT (equivalente a unset), el valor predeterminado es unset (dependiente de la unidad).
databaseId Si la ID del proveedor de la base de datos (databaseIdProvider) está configurada, MyBatis cargará todas las declaraciones sin databaseId o que coincidan con el databaseId actual; si hay declaraciones con o sin, las declaraciones sin o sin ellas se ignoran.
resultOrdered Esta configuración solo es aplicable a la instrucción de selección de resultados anidados: si es verdadero, se supone que se incluye el conjunto o agrupación de resultados anidados, de modo que cuando se devuelve una fila de resultados principal, no se producirá ninguna referencia al conjunto de resultados anterior. Situación Esto no causará memoria insuficiente al recuperar conjuntos de resultados anidados. Valor predeterminado: falso .
resultSets Esta configuración solo es aplicable a múltiples conjuntos de resultados. Enumerará los conjuntos de resultados devueltos después de que se ejecute la instrucción y dará un nombre a cada conjunto de resultados, los nombres están separados por comas.

 insertar, actualizar 和 eliminar :

  La implementación de las instrucciones de cambio de datos insertar, actualizar y eliminar están muy cerca:

Código de copia
<insert 
  id = "insertAuthor" 
  parameterType = "domain.blog.Author" 
  flushCache = "true" 
  StatementType = " 
  PREPARED " keyProperty = "" 
  keyColumn = "" 
  useGeneratedKeys = "" 
  timeout = "20"> 

<update 
  id = "updateAuthor " 
  parameterType =" domain.blog.Author " 
  flushCache =" true " 
  StatementType =" PREPARED " 
  timeout =" 20 "> 

<delete 
  id =" deleteAuthor " 
  parameterType =" domain.blog.Author " 
  flushCache =" true " 
  StatementType =" PREPARADO"
  tiempo de espera = "20">
Código de copia

   Descripción del atributo relacionado:

Atributos Descripción
carné de identidad El identificador único en el espacio de nombres se puede usar para representar esta declaración.
Parámetro Tipo El nombre de clase completo o el alias del parámetro que se pasará a la instrucción. Este atributo es opcional porque MyBatis puede inferir los parámetros de la declaración entrante específica a través del procesador de tipos. El valor predeterminado no está establecido.
parameterMap Este es un método obsoleto para hacer referencia a un parámetro externo. Utilice la asignación de parámetros en línea y el parámetro parameterType.
flushCache Después de establecerlo en verdadero, siempre que se llame a la instrucción, la memoria caché local y la memoria caché de segundo nivel se borrarán. El valor predeterminado es verdadero (para insertar, actualizar y eliminar instrucciones).
se acabó el tiempo Esta configuración es el número de segundos que el controlador espera a que la base de datos devuelva el resultado de la solicitud antes de lanzar una excepción. El valor predeterminado no está establecido (depende de la unidad).
StatementType DECLARACIÓN, PREPARADA O LLAMABLE. Esto hará que MyBatis use Statement, PreparedStatement o CallableStatement respectivamente, el valor predeterminado es PREPARED.
useGeneratedKeys (Solo es útil para insertar y actualizar) Esto hará que MyBatis use el método getGeneratedKeys de JDBC para recuperar la clave primaria generada dentro de la base de datos (por ejemplo: campos de incremento automático en sistemas de administración de bases de datos relacionales como MySQL y SQL Server), valor predeterminado: falso
keyProperty (Solo es útil para insertar y actualizar) Solo marque un atributo, MyBatis establecerá su valor clave mediante el valor de retorno de getGeneratedKeys o mediante el subelemento selectKey de la instrucción de inserción, el valor predeterminado: unset ( unset ). Si desea obtener múltiples columnas generadas, también puede ser una lista separada por comas de nombres de atributos.
keyColumn (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。
databaseId 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

下面就是 insert,update 和 delete 语句的示例:

Código de copia
<insert id="insertAuthor">
  insert into Author (id,username,password,email,bio)
  values (#{id},#{username},#{password},#{email},#{bio})
</insert>

<update id="updateAuthor">
  update Author set
    username = #{username},
    password = #{password},
    email = #{email},
    bio = #{bio}
  where id = #{id}
</update>

<delete id="deleteAuthor">
  delete from Author where id = #{id}
</delete>
Código de copia

  如前所述,插入语句的配置规则更加丰富,在插入语句里面有一些额外的属性和子元素用来处理主键的生成,而且有多种生成方式。首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就 OK 了。如果你的数据库还支持多行插入, 你也可以传入一个 Blog数组或集合,并返回自动生成的主键。

Código de copia
<!--批量插入-->
<insert id="insertBlogs" useGeneratedKeys="true"
            keyProperty="bid">
     insert into blog (name, author_id) values
     <foreach item="item" collection="list" separator=",">
         (#{item.name}, #{item.authorId})
     </foreach>
</insert>
Código de copia

sql

  这个元素可以被用来定义可重用的 SQL 代码段,这些 SQL 代码可以被包含在其他语句中。它可以(在加载的时候)被静态地设置参数。 在不同的包含语句中可以设置不同的值到参数占位符上。mybatis中sql标签与include标签进行配合,灵活的查询需要的数据。

Código de copia
<sql id="ref">
    bid,name,authorId
</sql>

<select id="selectbyId" resultMap="BaseResultMap">
    select
    <include refid="ref"/>
    from
    blog where bid = #{bid}
</select>
Código de copia

  sql标签中id属性对应include标签中的refid属性。通过include标签将sql片段和原sql片段进行拼接成一个完成的sql语句进行执行。include标签中还可以用property标签,用以指定自定义属性。

Código de copia
<select id="selectbyId" resultMap="BaseResultMap">
    select
    <include refid="ref">
        <property name="abc" value="bid"/>
    </include>
    from
    blog where bid = #{bid}
</select>
Código de copia

  此时,可以在sql标签中取出对应设置的自定义属性中的值,例如接上代码例子:

Código de copia
<sql id="ref">
    ${abc},name,authorId
</sql>

<select id="selectbyId" resultMap="BaseResultMap">
    select
    <include refid="ref">
        <property name="abc" value="bid"/>
    </include>
    from
    blog where bid = #{bid}
</select>
Código de copia

   在sql标签中通过${}取出对应include标签中设置的属性值。

  关联(association)元素处理“有一个”类型的关系。 比如,在我们的示例中,一个博客有一个用户。关联结果映射和其它类型的映射工作方式差不多。 你需要指定目标属性名以及属性的javaType(很多时候 MyBatis 可以自己推断出来),在必要的情况下你还可以设置 JDBC 类型,如果你想覆盖获取结果值的过程,还可以设置类型处理器。关联的不同之处是,你需要告诉 MyBatis 如何加载关联。MyBatis 有两种不同的方式加载关联:

  • 嵌套 Select 查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。
  • 嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。

关联的嵌套 Select 查询

Código de copia
<!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题 -->
    <resultMap id="BlogWithAuthorQueryMap" type="com.wuzz.demo.associate.BlogAndAuthor">
        <id column="bid" property="bid" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <association property="author" javaType="com.wuzz.demo.entity.Author"
                     column="author_id" select="selectAuthor"/>
    </resultMap>

    <!-- 嵌套查询 -->
    <select id="selectAuthor" parameterType="int" resultType="com.wuzz.demo.entity.Author">
        select author_id authorId, author_name authorName
        from author where author_id = #{authorId}
    </select>

    <!-- 根据文章查询作者,一对一,嵌套查询,存在N+1问题,可通过开启延迟加载解决 -->
    <select id="selectBlogWithAuthorQuery" resultMap="BlogWithAuthorQueryMap" >
        select b.bid, b.name, b.author_id, a.author_id , a.author_name
        from blog b
        left join author a
        on b.author_id=a.author_id
        where b.bid = #{bid, jdbcType=INTEGER}
    </select>
Código de copia

  就是这么简单。我们有两个 select 查询语句:一个用来加载博客(Blog),另外一个用来加载作者(Author),而且博客的结果映射描述了应该使用 selectAuthor 语句加载它的 author 属性。其它所有的属性将会被自动加载,只要它们的列名和属性名相匹配。这种方式虽然很简单,但在大型数据集或大型数据表上表现不佳。这个问题被称为“N+1 查询问题”。 概括地讲,N+1 查询问题是这样子的:

  • 你执行了一个单独的 SQL 语句来获取结果的一个列表(就是“+1”)。
  • 对列表返回的每条记录,你执行一个 select 查询语句来为每条记录加载详细信息(就是“N”)。

  这个问题会导致成百上千的 SQL 语句被执行。有时候,我们不希望产生这样的后果。MyBatis 能够对这样的查询进行延迟加载,因此可以将大量语句同时运行的开销分散开来。mybatis.configuration.lazy-loading-enabled=true 可以开启延时加载 mybatis.configuration.aggressive-lazy-loading=true 可以指定哪些方法调用查询, 然而,如果你加载记录列表之后立刻就遍历列表以获取嵌套的数据,就会触发所有的延迟加载查询,性能可能会变得很糟糕。所以还有另外一种方法。

关联的嵌套结果映射

Código de copia
<!-- 根据文章查询作者,一对一查询的结果,嵌套查询 -->
    <resultMap id="BlogWithAuthorResultMap" type="com.wuzz.demo.associate.BlogAndAuthor">
        <id column="bid" property="bid" jdbcType="INTEGER"/>
        <result column="name" property="name" jdbcType="VARCHAR"/>
        <!-- 联合查询,将author的属性映射到ResultMap -->
        <association property="author" javaType="com.wuzz.demo.entity.Author">
            <id column="author_id" property="authorId"/>
            <result column="author_name" property="authorName"/>
        </association>
    </resultMap>
    <!-- 根据文章查询作者,一对一,嵌套结果,无N+1问题 -->
    <select id="selectBlogWithAuthorResult" resultMap="BlogWithAuthorResultMap" >
        select b.bid, b.name, b.author_id, a.author_id , a.author_name
        from blog b,author a
        where b.author_id=a.author_id and b.bid = #{bid, jdbcType=INTEGER}
    </select>
Código de copia

   查询文章带评论的结果(一对多)映射:

Código de copia
<!--  查询文章带评论的结果(一对多) -->
    <resultMap id="BlogWithCommentMap" type="com.wuzz.demo.associate.BlogAndComment" extends="BaseResultMap" >
        <collection property="comment" ofType="com.wuzz.demo.entity.Comment">
            <id column="comment_id" property="commentId" />
            <result column="content" property="content" />
            <result column="bid" property="bid" />
        </collection>
    </resultMap>
    <!-- 根据文章查询评论,一对多 -->
    <select id="selectBlogWithCommentById" resultMap="BlogWithCommentMap" >
        select b.bid, b.name, b.author_id , c.comment_id , c.content,c.bid
        from blog b, comment c
        where b.bid = c.bid
        and b.bid = #{bid}
    </select>
Código de copia

  按作者查询文章评论的结果(多对多):

Código de copia
<!--  按作者查询文章评论的结果(多对多) -->
    <resultMap id="AuthorWithBlogMap" type="com.wuzz.demo.associate.AuthorAndBlog" >
        <id column="author_id" property="authorId" jdbcType="INTEGER"/>
        <result column="author_name" property="authorName" jdbcType="VARCHAR"/>
        <collection property="blog" ofType="com.wuzz.demo.associate.BlogAndComment">
            <id column="bid" property="bid" />
            <result column="name" property="name" />
            <result column="author_id" property="authorId" />
            <collection property="comment" ofType="com.wuzz.demo.entity.Comment">
                <id column="comment_id" property="commentId" />
                <result column="content" property="content" />
                <result column="bid" property="bid" />
            </collection>
        </collection>
    </resultMap>

    <!-- 根据作者文章评论,多对多 -->
    <select id="selectAuthorWithBlog" resultMap="AuthorWithBlogMap" >
        select b.bid, b.name, a.author_id , a.author_name , c.comment_id , c.content,c.bid
        from blog b, author a, comment c
        where b.author_id = a.author_id and b.bid = c.bid
    </select>
Código de copia

动态 SQL

  MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

  1. if
  2. choose (when, otherwise)
  3. trim (where, set)
  4. foreach

  其中  choose再实际开发中应用的较少,我们这里就其他3个标签进行测试

Código de copia
<!--动态sql-->
    <select id="selectBlogById2" resultMap="BaseResultMap" statementType="PREPARED" useCache="false"
        parameterType="blog">
        select * from blog
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
            <if test="bid != null and bid !='' ">
                bid = #{bid}
            </if>
            <if test="name != null and name !='' ">
                AND name = #{name}
            </if>
            <if test="authorId != null and authorId != ''">
                AND author_id = #{author_id}
            </if>
        </trim>
    </select>
Código de copia

   foreach: Otro requisito de operación común de SQL dinámico es atravesar una colección, generalmente al construir declaraciones condicionales IN. Por ejemplo:

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

Supongo que te gusta

Origin www.cnblogs.com/flgb/p/12688311.html
Recomendado
Clasificación