[MyBatis] Various query functions of Mybatis, special SQL, dynamic SQL, primary and secondary cache

1. Various query functions of Mybatis

1. If there is only one query result
(1) you can use the entity class object to receive it
(2) you can also use the list and map collection to receive it;
2. If there are multiple query results
(1) use the entity class type list collection to receive it
( 2) Use the list collection of map type to receive
(3) You can add the @MapKey annotation to the method of the mapper interface. At this time, you can use the map collection as the value and the value of a unique field as the key, and put it in the same map collection

2. Execution of special SQL

1. Fuzzy query

<!--三种方式都可以实现模糊查询,推荐使用方式3-->
<select id="getUserByLike" resultType="com.jd.wds.pojo.User">
    <!--select * from user where username like '%${username}%'-->
    <!--select * from user where username like concat ('%',#{username},'%')-->
    select * from user where username like "%"#{username}"%"
</select>

2. Batch delete

<!--批量删除的特殊情况-->
<delete id="deleteMore">
    <!--此处只能使用${}的形式,因为#{}的方式会添加引号,而id的字段名是int-->
    <!--delete from user where id in (#{id})-->
    delete from user where id in (${id})
</delete>

3. Dynamically set the table name

<select id="getUserByTableName" resultType="com.jd.wds.pojo.User">
    <!--此处只能使用${},不能使用#{}-->
    <!--select * from #{tableName}-->
    select * from ${tableName}
</select>

4. The field name and attribute name are inconsistent.
insert image description here
insert image description here
According to different specifications, when creating a table, the field is named with an underscore, and the attribute name of the created class is named with a small hump. At this time, the field name and the attribute name do not exactly correspond. Three solutions:

<select id="getAllEmp" resultType="com.jd.wds.pojo.Emp">
    <!--方法1:给对应的字段名设置别名-->
    select eid,emp_name empName,age,sex,email from t_emp
</select>
<!--mybatis的核心配置文件中配置如下,此时sql语句:select * from t_emp-->
<!--方法2:设置全局配置:驼峰命名转下划线命名-->
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--方法3:使用resultmap设置自定义的映射-->
<resultMap id="empResultMap" type="com.jd.wds.pojo.Emp">
    <!--id设置的是主键名,result设置的是非主键名,column是属性名-->
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
</resultMap>
<select id="getAllEmp" resultMap="empResultMap">
    <!--解决字段名和属性名方法1:给对应的字段名设置别名-->
    select * from t_emp
</select>

5. Many-to-one mapping relationship
. Many-to-one corresponds to objects, and one-to-many corresponds to collections
. Take a chestnut: query an employee’s information and department information (multiple employees correspond to a department, typically many-to-one)
method 1: resultMap is processed through cascading property assignments

<resultMap id="empAndDeptOne" type="com.jd.wds.pojo.Emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
    <!--需要在Emp类中声明dept属性,resultMap通过级联属性赋值-->
    <result property="dept.did" column="did"></result>
    <result property="dept.deptName" column="dept_name"></result>
</resultMap>
<select id="getEmpAndDept" resultMap="empAndDeptOne">
    SELECT * FROM t_emp LEFT JOIN t_dept ON t_emp.did = t_dept.did WHERE t_emp.eid = #{eid}
</select>

Method 2: Use association to specifically handle cascading property assignments

<resultMap id="empAndDeptTwo" type="com.jd.wds.pojo.Emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
    <!--需要在Emp类中声明dept属性,使用association专门处理级联属性赋值
    javaType:需要处理的属性的类型;
    property:需要处理的属性名-->
    <association javaType="com.jd.wds.pojo.Dept" property="dept">
        <result property="did" column="did"></result>
        <result property="deptName" column="dept_name"></result>
    </association>
</resultMap>
<select id="getEmpAndDept" resultMap="empAndDeptTwo">
    SELECT * FROM t_emp LEFT JOIN t_dept ON t_emp.did = t_dept.did WHERE t_emp.eid = #{eid}
</select>

Method 3: Solve using a step-by-step query

<!--<mapper resource="com/jd/wds/mapper/EmpMapper.xml"/>-->
<!--分步查询员工所对应的部门信息-->
<!--第一步:查询员工信息-->
<resultMap id="EmpAndDeptByStepOne" type="com.jd.wds.pojo.Emp">
    <id property="eid" column="eid"></id>
    <result property="empName" column="emp_name"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
    <result property="email" column="email"></result>
    <!--association标签中property:属性名,select:第二步的sql查询语句,column:第二步的查询条件-->
    <association property="dept" select="com.jd.wds.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="did"></association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="EmpAndDeptByStepOne">
    select * from t_emp where eid=#{eid}
</select>
<!--<mapper resource="com/jd/wds/mapper/DeptMapper.xml"/>-->
<!--步骤2:根据查询道德did查询t_dept表中的数据-->
<select id="getEmpAndDeptByStepTwo" resultType="com.jd.wds.pojo.Dept">
    select * from t_dept where did = #{did}
</select>

The benefits of step-by-step query: It can implement delayed loading and improve the reuse of SQL. It must be enabled in the configuration file before it can be used. By default, delayed loading is not enabled.
6. One-to-many mapping relationship
. Many-to-one corresponds to objects, and one-to-many corresponds to collections
. Take a chestnut: query a department and the information of employees in the department (a department can have multiple employees, a typical one-to-many) Method
1 : Use collection to handle one-to-many result mapping

<resultMap id="DeptAndEmp" type="com.jd.wds.pojo.Dept">
    <id property="did" column="did"></id>
    <result property="deptName" column="dept_name"></result>
    <!--collection:处理一对多的结果映射,emps:一对多的集合名,ofType:集合emps所对应的集合类型-->
    <collection property="emps" ofType="com.jd.wds.pojo.Emp">
        <id property="eid" column="eid"></id>
        <result property="empName" column="emp_name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="email" column="email"></result>
    </collection>
</resultMap>
<select id="getDeptAndEmp" resultMap="DeptAndEmp">
    select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>

Approach 2: Use step-by-step queries to handle one-to-many result mapping

<!--分步查询-->
<!--<mapper resource="com/jd/wds/mapper/DeptMapper.xml"/>-->
<resultMap id="getDeptAndEmpByStep" type="com.jd.wds.pojo.Dept">
    <id property="did" column="did" ></id>
    <result property="deptName" column="dept_name"></result>
    <collection property="emps" select="com.jd.wds.mapper.EmpMapper.getDeptAndEmpByStepTwo" column="did">
    </collection>
</resultMap>
<!--第一步:根据did查询所在的部门信息-->
<select id="getDeptAndEmpByStepOne" resultMap="getDeptAndEmpByStep">
    select * from t_dept where did = #{did}
</select>
<!--<mapper resource="com/jd/wds/mapper/EmpMapper.xml"/>-->
<!--第二步:根据第一步查询结果的did查询所在的员工信息-->
<select id="getDeptAndEmpByStepTwo" resultType="com.jd.wds.pojo.Emp">
    select * from t_emp where did = #{did}
</select>

3. Dynamic SQL

1. The <if> element
determines whether the content in the tag should be spliced ​​into SQL according to the expression corresponding to the test attribute in the tag.

<!--通过多个条件精确查询某一条数据-->
<select id="getEmpDynamicCondition" resultType="com.jd.wds.pojo.Emp">
    select * from t_emp where 1=1
    <!--test属性的值是属性名-->
    <if test="empName != null and empName !=''">
        and emp_name = #{empName}
    </if>
    <if test="age != null and age !=''">
        and age = #{age}
    </if>
    <if test="sex != null and sex != ''">
        and sex = #{sex}
    </if>
    <if test="email != null and email != ''">
        and email = #{email}
    </if>
</select>

2. < where > element
When there is content in the tag, the where keyword will be automatically generated, and the and or or before the content will be removed; when there is no content in the tag, where will have no effect. (and or or will report an error after the content)

<select id="getEmpDynamicCondition" resultType="com.jd.wds.pojo.Emp">
    select * from t_emp 
    <where>
    <if test="empName != null and empName !=''">
        and emp_name = #{empName}
    </if>
    <if test="age != null and age !=''">
        and age = #{age}
    </if>
    <if test="sex != null and sex != ''">
        and sex = #{sex}
    </if>
    <if test="email != null and email != ''">
        and email = #{email}
    </if>
    </where>
</select>

3. < trim > element
If there is content in the tag:
prefix/suffix: add the specified content before or after the content in the trim tag
suffixoverrides /prefixoverrides: remove the specified content before or after the content in the trim tag
If there is no content in the tag, trim the tag Nothing works.

<select id="getEmpDynamicCondition" resultType="com.jd.wds.pojo.Emp">
    select * from t_emp
    <!--此时在内容之前添加where,条件前面加and|or-->
    <trim prefix="where" prefixOverrides="and|or">
        <if test="empName != null and empName !=''">
            and emp_name = #{empName}
        </if>
        <if test="age != null and age !=''">
            and age = #{age}
        </if>
        <if test="sex != null and sex != ''">
            and sex = #{sex}
        </if>
        <if test="email != null and email != ''">
            and email = #{email}
        </if>
    </trim>
</select>

4.< choose > < when > < otherwise >
equivalent to element if,else if,else if,else

<select id="getEmpDynamicCondition" resultType="com.jd.wds.pojo.Emp">
    select * from t_emp where 1=1
    <choose>
        <when test="empName != null and empName !=''">
            and emp_name = #{empName}
        </when>
        <when test="age != null and age !=''">
            and age = #{age}
        </when>
        <when test="sex != null and sex != ''">
            and sex = #{sex}
        </when>
        <when test="email != null and email != ''">
            and email = #{email}
        </when>
        <otherwise>
            did = 1
        </otherwise>
    </choose>
</select>

5. < foreach > element
foreach is used for traversal operations, and is often used for operations such as batch deletion and batch addition.

<!--批量删除操作-->
<delete id="deleteMoreUser">
    <!--方法1:使用in集合的方式-->
    delete from t_emp where eid in
    <foreach collection="eids" open="(" close=")" separator="," item="eid">
        #{eid}
    </foreach>
    <!--方法2:使用or连接条件-->
    delete from t_emp where
    <foreach collection="eids" item="eid" separator="or">
        eid = #{eid}
    </foreach>
</delete>
<!--批量插入操作-->
<insert id="insertMoreUser">
    insert into t_emp values
    <foreach collection="emps" separator="," item="emp">
        (null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},#{emp.did})
    </foreach>
</insert>

6. The SQL tag
is used to set the SQL fragment, which can be quoted at the required position.

<!--设置sql片段-->
<sql id="columns">eid,emp_name,age,sex,email</sql>
<select id="selectAllUser" resultType="com.jd.wds.pojo.Emp">
	<!--使用sql片段-->
    select <include refid="colums"></include> from t_emp where eid = #{eid}
</select>

Four, Mybatis cache

1. Mybatis's first level cache

The cache is only for the query function. The first-level cache is at the SqlSession level. It is enabled by default. When the same SqlSession is used to query the same data next time, it will be directly obtained from the cache and will not be queried from the database (the SQL statement is only executed once, and there are two same result).
There are four situations where the first-level cache fails:
(1) Different SqlSessions correspond to the first-level cache
(2) The query conditions corresponding to the same SqlSession are different
(3) Any addition, deletion, and modification operations are performed between two queries of the same SqlSession
( 4) Manually clear the cache between two queries of the same SqlSesion

//手动清空缓存
sqlSession.clearCache();

2. Second level cache of Mybatis

The second-level cache is at the SqlSessionFactory level. The query results of the SqlSession created through the same SqlSessionFactory will be cached. If the same query statement is executed later, the results will be obtained from the cache.
(1) Conditions for enabling the secondary cache :
① In the core configuration file, set the global configuration attribute cacheEnabled="true"

<setting name="cachedEnable" value="true"/>

② Set the label <cache /> in the mapping file.
③ The second-level cache must take effect after the SqlSession is closed or submitted.
④ The entity class type converted by the queried data must implement the serialization
interface
. Any addition, deletion, and modification operations between queries will invalidate the primary and secondary caches at the same time.
(3) Relevant configuration of the second-level cache
insert image description here
(4) Order of cache queries
insert image description here

Guess you like

Origin blog.csdn.net/weixin_46081857/article/details/123364732