Mybatis

mybatis 和 mybatis-plus 配置文件: 用于配置数据库连接和 MyBatis 运行时所需的各种特性,包含了设置和影响 MyBatis 行为的属性、映射文件的位置。mapper接口和mapper.xml之间需要遵循一定规则,才能成功的让mybatis将mapper接口和mapper.xml绑定起来。创建IUserMapper接口: 用于操作数据库CURD的方法。文件:用于mybatis配置文件读取数据库信息。resources 目录下 创建。resources 目录下 创建。resources 目录下 的。类:用于跟数据库字段做映射。 阅读详情

一 .MyBatis框架

1.Mybatis环境搭建步骤

​ 1.新建项目,项目下新建目录lib,涉及到的jar包放入lib目录下,右键add as lib…

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-69GjPWGi-1692620456055)(C:\Users\dis\Desktop\笔记\Mybatis\lib\Snipaste_2023-08-20_14-53-48.png)]

​ mybatis核心jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bGkgVRqn-1692620456058)(C:\Users\dis\Desktop\笔记\Mybatis\lib\Snipaste_2023-08-20_14-54-39.png)]

​ mybatis依赖的jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jKTEJbV-1692620456059)(C:\Users\dis\Desktop\笔记\Mybatis\lib\Snipaste_2023-08-20_14-54-43.png)]

​ 数据库的驱动包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nHYtsZ8T-1692620456059)(C:\Users\dis\Desktop\笔记\Mybatis\lib\Snipaste_2023-08-20_14-54-48.png)]

​ 2.编写核心配置文件

​ 3.编写SQL映射文件,编写实体类

​ 4.测试

2.使用

     //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatis.xml");
        //2.构建SqlSessionFactory实例
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //3.获取会话
        SqlSession session = factory.openSession();
        //4.执行sql
        //selectList("命名空间.id")
        List<Dept> list = session.selectList("com.yjxxt.mappers.DeptMapper.queryAll");
        list.forEach(System.out::println);
        //5.关闭会话
        session.close();

3.配置文件

mybatis提供两种配置文件, 核心配置文件 mybatis-config.xml|mybatis.xml 与 SQL映射文件mapper.xml

1.mybatis.xml

是一个xml文件,命名无要求,位置无要求,一般成为mybatis.xml,放在src路径下

<?xml version="1.0" encoding="UTF-8" ?>
<!--约束-->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--根元素 : 核心设置-->
<configuration>
    <!-- settings标签 -->
    <settings>
        <!-- 设置MyBatis使用log4j日志支持 -->
        <setting name="logImpl" value="LOG4J"/>
    </settings>

    <!--
        用于指定使用哪一个开发环境
        default : 用于指定使用的环境的id属性值
    -->
    <environments default="dev">
        <!--
            environment : 用于配置开发环境
            id : 环境的唯一标识
        -->
        <environment id="dev">
<!--
                transactionManager 事务管理器
                type="JDBC" 采用jdbc相同的事务管理机制
            -->
            <transactionManager type="JDBC"/>
            <!--
                dataSource : 用来配置数据库连接参数
                type="POOLED" 采用连接池技术
            -->
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
                <property name="username" value="SCOTT"/>
                <property name="password" value="YJXXT"/>
            </dataSource>
        </environment>
    </environments>
    <!--扫描SQL映射文件-->
    <mappers>
        <mapper resource="com/yjxxt/mappers/DeptMapper.xml"/>
    </mappers>
</configuration>
2.Mybatis SQL映射文件

在Mybatis中,推荐使用mappers作为包名,我们只需要写一个映射配置文件就可以,UserMapper.xml,用于定义要执行的sql语句,同时可以设置参数|返回值结果类型

SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

insert – 映射插入语句

update – 映射更新语句

delete – 映射删除语句

select – 映射查询语句

查询语句是 MyBatis 中最常用的元素之一(映射文件配置见代码)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
	跟标签mapper
    namespace 命名空间
        要求 : 唯一的,SQL映射文件的唯一标识
        定义方式 :
            1.随意定义,只要不重复即可,不推荐,不便于后期维护
            2.推荐使用包名.文件名 -> 推荐
-->
<mapper namespace="com.yjxxt.mappers.UserMapper">

    <!--
        select 定义查询语句
        id : 唯一标识,一个命名空间下的唯一
        resultType : 结果类型
        parameterType : 入参类型
    -->
    <select id="queryAll" resultType="com.yjxxt.pojo.User">
		select * from t_user
	</select>
</mapper>
3.三个查询方法

selectList(“命名空间.id”) 用户查询多条数据情况,返回一个List集合, 没有查到数据返回空集合,不是null

selectOne(“命名空间.id”) 用于查询单条数据,返回一个数据, 如果没有查到返回null

selectMap(“命名空间.id”,key的字段名) 用于查询多条记录情况, 返回Map集合, 需要指定那个属性作为key, sql查询结果作为value,指定的字段值作为key, 如果查不到, 返回一个空map集合,不是null
*/

 		//1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatis.xml");
        //2.构建SqlSessionFactory实例
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //3.获取会话
        SqlSession session = factory.openSession();
        //4.执行sql
        //selectList("命名空间.id")
        List<Dept> list = session.selectList("com.yjxxt.mappers.DeptMapper.queryDept");
        list.forEach(System.out::println);

        System.out.println("--------------------------------------------------");
        //selectList("命名空间.id",入参)
        List<Dept> list2 = session.selectList("com.yjxxt.mappers.DeptMapper.queryDeptByLoc","NEW YORK");
        list2.forEach(System.out::println);

        System.out.println("--------------------------------------------------");

        //selectOne("命名空间.id")
        //selectOne("命名空间.id",入参)
        Dept dept = session.selectOne("com.yjxxt.mappers.DeptMapper.queryDeptById",10);
        System.out.println(dept);

        System.out.println("--------------------------------------------------");
        //selectMap("命名空间.id","作为key的字段名")
        //selectMap("命名空间.id",入参,"作为key的字段名")
        Map<Integer,Dept> map = session.selectMap("com.yjxxt.mappers.DeptMapper.queryDeptByLoc","NEW YORK","deptno");
        System.out.println(map);

        //5.关闭会话
        session.close();
    }

4.resultType结果类型

基本数据类型(包装类) String Date JavaBean List Map List-Map

1.Date类型
 <!--Date : 根据员工编号查询员工入职日期-->
    <select id="queryDateByNo" parameterType="int" resultType="date">
        select hiredate from emp where empno = #{empno}
    </select>
//Date
        Date date = session.selectOne("com.yjxxt.mappers.EmpMapper.queryDateByNo",7369);
        System.out.println(date);
2.List类型
<!--List类型 :查询指定名字类型的用户信息 -->
<select id="queryUserByUsernameLike" resultType="user" parameterType="string">
select * from t_user where uname like '%'||#{0}||'%'
</select>
/*
* List : 查询指定名字类型的用户信息
*/
@Test
public void testList(){
SqlSession session = MybatisUtils.getSession();
List<User> list =
session.selectList("com.yjxxt.mapper.UserMapper.queryUserByUsernameLike","i");
list.forEach(System.out::println);
session.close();
}
3.Map类型
 <!--Map : 根据员工编号查询员工信息-->
    <select id="queryEmpByNo" parameterType="int" resultType="map">
        select * from emp where empno = #{empno}
    </select>
 //Map
        Map<String,Object> map = session.selectOne("com.yjxxt.mappers.EmpMapper.queryEmpByNo",7369);
        System.out.println(map);
4.List-Map类型
	<!--List<Map> : 根据员工姓名模糊查询-->
    <select id="queryEmpByNameLike" parameterType="String" resultType="map">
        select * from emp where ename like '%'||#{ename}||'%'
    </select>
//List<Map>
        List<Map<String,Object>> list = session.selectList("com.yjxxt.mappers.EmpMapper.queryEmpByNameLike","A");
        list.forEach(System.out::println);

二. Log4J日志

1.日志级别

DEBUG(人为调试信息)

INFO(普通信息)

WARN(警告)

ERROR(错误)

FATAL(系统错误)

这五个级别是有顺序的,DEBUG < INFO < WARN < ERROR < FATAL

Log4j有一个规则:只输出级别不低于设定级别的日志信息

2.配置文件

可以使用properties或者xml进行配置,使用一个叫 log4j.properties 的配置文件, 会设定 log4j的设置信息, 例如日志级别, 日志输出方式, 日志格式等等.

# Set root category priority to INFO and its only appender to CONSOLE.
# log4j.rootCategory=DEBUG, CONSOLE
 log4j.rootCategory=INFO, CONSOLE, LOGFILE

# 单独设置SQL语句输出级别为DEBUG
# 方法级别设置(SQL语句)
# log4j.logger.com.yjxxt.mappers.DeptMapper.queryDept=DEBUG
# 类级别设置(SQL映射文件)
# log4j.logger.com.yjxxt.mappers.DeptMapper=DEBUG
# 类级别设置(SQL映射文件)
log4j.logger.com.yjxxt.mappers=DEBUG

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 
log4j.appender.CONSOLE.layout.ConversionPattern=- %m %n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender 
log4j.appender.LOGFILE.File=d:/test.log 
log4j.appender.LOGFILE.Append=true 
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout 
log4j.appender.LOGFILE.layout.ConversionPattern=- %m %l %n

3.常见的日志输出格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zVBZXF5x-1692620456061)(C:\Users\dis\Desktop\笔记\Mybatis\lib\Snipaste_2023-08-20_15-13-55.png)]

4.Mybatis对Log4J的支持

通过settings标签开启 log4j 的支持

settings用于设置 MyBatis 在运行时的行为方式, 例如:缓存, 延迟加载, 日志等.

<!-- settings标签 -->
<settings>
<!-- 设置MyBatis使用log4j日志支持 -->
<setting name="logImpl" value="LOG4J"/>
</settings>

三.软编码与别名

1.通过properties标签实现软编码

src下定义配置文件db.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=SCOTT
password=TIGER

mybatis核心配置文件中添加properties标签,指定加载外部的properties文件,注意定义位置 setting上面

<!-- 加载外部的properties文件 -->
<properties resource="db.properties" />

获取properties文件中数据时候,要通过${}的方式获取

 <environments default="dev">
        <!--环境配置-->
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

2.typeAliases标签

给User类定义别名为u

<typeAliases>
<typeAlias type="com.yjxxt.pojo.User" alias="u"/>
</typeAliases>

省略alias属性, 表示类别名为类名, 大小写不敏感

<typeAliases>
<typeAlias type="com.yjxxt.pojo.User"/> alias属性不写,默认类名,不区分大小写
</typeAliases>

可以通过package标签给整个包下的所有类定义别名,别名为类名

<typeAliases>
<package name="com.yjxxt.pojo"/> <!-- 包下所有的类默认类名 -->
</typeAliases>
<select id="queryAll" resultType="u">
select id,uname,upwd,birthday from t_user
</select>
<select id="queryById" resultType="User">
select id,uname,upwd,birthday from t_user where id=125
</select>

3.Mybatis的内建别名

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCKSNlm3-1692620456062)(C:\Users\dis\Desktop\笔记\Mybatis\lib\Snipaste_2023-08-20_15-35-22.png)]

四.parameterType入参类型

如果执行的是条件查询,DML,需要在调用方法的时候传递参数,此时, 可以在sql标签中通过parameterType属性指定参数的类型(别名|权限定名). 而在sql语句,通过#{}的方式获取参数

入参类型 : 基本数据类型|包装类 String Date Javabean Map List|数组…

1.一个参数的查询

根据员工姓名查询员工信息,当参数只有一个,#{}可以任意填写匹配参数

    <!--String : 根据员工姓名查询员工信息-->
    <select id="queryEmpByName" parameterType="String" resultType="emp">
        select * from emp where ename = #{ename}
    </select>

2.多个参数查询

多个参数传递时, 由于sqlSession中提供的查询方法,只允许传递一个sql参数, 因此可以对多个参数进行封装,可以对象,集合,数组…

 <!--Javabean : 根据员工姓名与员工的薪资查询员工信息-->
 <!--sql中的占位符的名字匹配入参对象的属性名,根据属性名匹配属性值-->
    <select id="queryEmpByNameSal" parameterType="emp" resultType="emp">
        select * from emp where ename = #{ename} and sal = #{sal}
    </select>
<!--Map : 根据员工薪资与员工的部门编号查询员工信息-->
    <select id="queryEmpBySalDeptno" parameterType="map" resultType="emp">
        select * from emp where sal = #{sal} or deptno = #{deptno}
    </select>

<!--数组|list : 根据多个员工编号查询员工信息-->
    <select id="queryEmpByNoSome"  resultType="emp">
        select * from emp where empno in (
        <foreach collection="array" separator="," item="item">
            #{item}
        </foreach>
        )
    </select>

五.工具类的封装

package com.yjxxt.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/*
    封装获取会话的工具类
 */
public class SessionUtils {
    private static SqlSessionFactory factory = null;

    static{
        try {
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSession(){
        SqlSession session = null;
        if(factory!=null){
            session = factory.openSession(); //手动提交
            //session = factory.openSession(true); //自动提交
        }
        return session;
    }
}

//1.获取会话
        SqlSession session = SessionUtils.getSession();
        //2.执行sql
        //selectList("命名空间.id")
        List<Dept> list = session.selectList("com.yjxxt.mappers.DeptMapper.queryAll");
        list.forEach(System.out::println);
        //3.关闭会话
        session.close();

六.事务

测试增删改

事务 :
需要手动提交的 : 需要通过session设置提交|回滚 --> 默认手动提交

​ 设置自动提交 factory.openSession(true);

session.commit(); //事务提交

1.增删改操作

​ 测试增删改

​ insert

​ update

​ delete

​ 注意: 增删改结果类型默认影响函数

SQL映射文件:

   <!--新增一条部门数据-->
    <insert id="insertDept" parameterType="Dept">
        insert into dept values(#{deptno},#{dname},#{loc})
    </insert>

    <!--根据部门编号修改部门名称-->
    <update id="updateDept" parameterType="Dept">
        update dept set dname=#{dname} where deptno = #{deptno}
    </update>

    <!--根据部门编号删除部门信息-->
    <delete id="deleteDept" parameterType="int">
        delete from dept where deptno = #{deptno}
    </delete>

Java测试类:

 //1.获取会话
        SqlSession session = SessionUtils.getSession();
        //2.执行sql
        //insert
        /*int rows = session.insert("com.yjxxt.mappers.DeptMapper.insertDept",new Dept(80,"网管部2","北京"));
        System.out.println(rows);
        */

        //update
        //int rows = session.update("com.yjxxt.mappers.DeptMapper.updateDept",new Dept(80,"网管部2222","北京"));

        //delete
        int rows = session.delete("com.yjxxt.mappers.DeptMapper.deleteDept",80);
        if(rows>0){
            session.commit(); //事务提交
        }else{
            session.rollback(); //回滚
        }

        //3.关闭会话
        session.close();

七.接口绑定方案

Myabtis中,提供了一套接口绑定方案,程序员可以提供一个接口,然后提供一个与接口所对应的mapper.xml文件

1.测试接口绑定方案

​ 步骤 :

1.定义接口,定义抽象功能
package com.yjxxt.mappers;
import com.yjxxt.pojo.Dept;
import java.util.List;
/*
    接口绑定方案下的接口 :
 */
public interface DeptMapper {
    // 查询所有的部门信息
    public List<Dept> queryAll();
}
2.定义与接口绑定的SQL文件,定义SQL语句,按照要求进行定义

​ 1.接口与SQL映射文件名字要保持一致,并放在同一个包下

​ 2.SQL映射文件的命名空间namespace定义为与之绑定的接口的包名.类名

​ 3.SQL标签的id属性值与接口中所对应的抽象方法的方法名保持一致

​ 4.SQL语句的参数与返回值要求与对应的抽象方法的参数与返回值保持一致

<mapper namespace="com.yjxxt.mappers.DeptMapper">
    <!--查询所有的部门信息-->
    <select id="queryAll" resultType="Dept">
        select * from dept
    </select>
</mapper>
3.核心配置文件中通过Mapper扫描接口
  <!--扫描接口 : 接口绑定方案-->
    <mappers>
        <!--<mapper class="com.yjxxt.mappers.DeptMapper"/>
        <mapper class="com.yjxxt.mappers.EmpMapper"/>-->
        <package name="com.yjxxt.mappers"/>  <!--包扫描-->
    </mappers>
4.在java代码中通过获取接口实现类对象调用功能
   		//1.获取会话
        SqlSession session = SessionUtils.getSession();
        //2.获取接口实现类对象--> 指定哪一个接口
        DeptMapper mapper = session.getMapper(DeptMapper.class);
        //3.调用方法
        List<Dept> list = mapper.queryAll();
        list.forEach(System.out::println);
        //4.关闭会话
        session.close();

2.通过接口绑定解决多参数传递问题

方式一:

接口中定义方法

List<Emp> queryEmpBySalDeptno(double sal,int deptno);

映射文件中提供对应的标签. 此时, SQL 语句中获取方式有两种, 通过#{arg+数字}或#{param+数字}的方式.

   <select id="queryEmpBySalDeptno" resultType="Emp">
        <!--sql中如果出现多参数传递,可以实现,默认占位符的名字为 : [arg0,arg1|param1,param2]-->
        <!--select * from emp where sal > #{arg0} and deptno = #{arg1}-->
        <!--select * from emp where sal > #{param1} and deptno = #{param2}-->
    </select>

方式二:

接口中定义方法, 参数中使用@Param 注解设定参数名用于在 SQL 语句中使用.

List<Emp> queryEmpBySalDeptno(@Param("sal") double sal,@Param("dno") int deptno);

映射文件中提供对应的标签. 此时, SQL 语句中获取方式有两种, 通过#{参数名称}或#{param+数字}的方式.

 	<select id="queryEmpBySalDeptno" resultType="Emp">
        select * from emp where sal > #{sal} and deptno = #{dno}
    </select>

3.接口增删改

  //插入一个新的部门信息
    int insertDept(Dept dept);

    //根据部门编号修改部门名称
    int updateDept(@Param("deptno") int deptno, @Param("dname") String dname);

    //根据部门编号删除
    int deleteDept(int deptno);
 <!--插入一个新的部门信息-->
    <insert id="insertDept" parameterType="dept">
        insert into dept values(#{deptno},#{dname},#{loc})
    </insert>
    <!--根据部门编号修改部门名称-->
    <update id="updateDept">
        update dept set dname = #{dname} where deptno = #{deptno}
    </update>

    <!--根据部门编号删除-->
    <delete id="deleteDept" parameterType="int">
        delete from dept where deptno = #{deptno}
    </delete>
  //1.获取会话
        SqlSession session = SessionUtils.getSession();
        //2.获取接口实现类对象--> 指定哪一个接口
        DeptMapper2 mapper = session.getMapper(DeptMapper2.class);
        //3.调用方法
        //1个参数
        //int rows = mapper.insertDept(new Dept(66,"六部","上海"));

        //int rows = mapper.updateDept(66,"六六六部");
        int rows = mapper.deleteDept(66);
        System.out.println(rows>0?"操作成功":"失败");
        //4.关闭会话
        session.close();

八.动态 SQL

1.if

用于进行条件判断, test 属性用于指定判断条件. 为了拼接条件, 在 SQL 语句后强行添加 1=1 的恒成立条件

test : 用于设置判断条件,类似if语句的()

会自动帮助把第一个满足条件的if标签中的and关键字去掉

<select id="sel" resultType="user">
select * from t_user where 1=1
<if test="username != null and username != ''"> and username=#{username}
</if>
<if test="password != null and password != ''"> and password=#{password}
</if>
</select>

2.where

用于管理 where 子句. 有如下功能:

  1. 如果没有条件, 不会生成 where 关键字
  2. 如果有条件, 会自动添加 where 关键字
  3. 如果第一个条件中有 and, 去除之
<select id="queryEmp" resultType="emp">
        select * from emp
        <where>
            <if test="ename!=null and ename!=''">
                and ename=#{ename}
            </if>
            <if test="deptno!=0">
                and deptno=#{deptno}
            </if>
        </where>
    </select>
List<Emp> queryEmp(@Param("ename") String ename,@Param("deptno") int deptno);

3.choose…when…otherwise

这是一套标签, 功能类似于 switch…case…

<select id="queryEmpByIdName"  resultType="emp">
        select * from emp
        <where>
            <choose> <!--相当于switch-->
                <when test="empno!=0"> <!--case-->
                    and empno = #{empno}
                </when>
                <when test="ename!=null and ename!=''"> <!--case-->
                    and ename=#{ename}
                </when>

            </choose>
        </where>
    </select>
 List<Emp> queryEmpByIdName(@Param("empno") int empno,@Param("ename") String ename);

4.set

用于维护 update 语句中的 set 子句,与where标签类似. 功能如下:

  1. 满足条件时, 会自动添加 set 关键字
  2. 会去除 set 子句中多余的逗号
  3. 不满足条件时, 不会生成 set 关键字
 <update id="updateEmp" parameterType="Emp">
        update emp
        <set>
            ename = #{ename},
            <if test="sal!=0">
                sal=#{sal}
            </if>
        </set>
        where empno = #{empno}
    </update>
   int updateEmp(Emp emp);

5.trim

用于在前后添加或删除一些内容

  1. prefix, 在前面添加内容
  2. prefixOverrides, 从前面去除内容
  3. suffix, 向后面添加内容
  4. suffixOverrides, 从后面去除内容
<update id="updateEmp" parameterType="Emp">
        update emp
        <trim prefix="set" suffixOverrides=",">
            ename = #{ename},
            <if test="sal!=0">
                sal=#{sal}
            </if>
        </trim>
        where empno = #{empno}
    </update>
   int updateEmp(Emp emp);

6.bind

用于对数据进行再加工, 用于模糊查询

 <select id="queryEmpByNameLike" parameterType="string" resultType="emp">
        <bind name="ename" value="'%'+ename+'%'"/>
        select empno,ename,hiredate,job,sal,comm,deptno from emp where ename like #{ename}
    </select>
    List<Emp> queryEmpByNameLike(String ename);

7.foreach 与 sql…include

用于在 SQL 语句中遍历集合参数, 在 in 查询中使用

sql用于提取 SQL 语句, include用于引用 SQL 语句

  1. collection: 待遍历的集合
  2. open: 设置开始符号
  3. item: 迭代变量
  4. separator: 项目分隔符
  5. close: 设置结束符
 <sql id="empField">
        empno,ename,hiredate,job,sal,comm,deptno
    </sql>
<select id="queryEmpByIdSome" resultType="emp">
        select <include refid="empField"/> from emp where empno in
        <foreach collection="list" item="item" separator="," open="(" close=")">
            #{item}
        </foreach>
    </select>
List<Emp> queryEmpByIdSome(List<Integer> list);

九.Mybatis缓存机制

缓存的重要性是不言而喻的。 使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。

mybatis 也提供了对缓存的支持, 分为一级缓存和二级缓存。 但是在默认的情况下, 只开启一级缓存。

一级缓存

  1. 默认开启. 线程级别的缓存, SqlSession 的缓存;
  2. 在一个 SqlSession 生命周期中有效. SqlSession 关闭,缓存清空;
  3. 在同一个 SqlSession 中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;
  4. 不同的 SqlSession 之间的缓存是相互隔离的;
  5. 用一个 SqlSession, 可以通过配置使得在查询前清空缓存;flushCache=“true”
  6. 任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。

二级缓存

  1. 进程级别的缓存, SqlSessionFactory 的缓存
  2. 在一个SqlSessionFactory生命周期中有效. 可以在多个SqlSession 生命中期中共享.
  3. 默认关闭, 需要使用的时候, 要为某个命名空间开启二级缓存(在 mapper.xml 中配置cache).
  4. 由于在更新时会刷新缓存, 因此需要注意使用场合:查询频率很高, 更新频率很低时使用, 即经常使用 select, 相对较少使用delete, insert, update。
  5. 缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响。但刷新缓存是刷新整个namespace 的缓存, 也就是你 update 了一个, 则整个缓存都刷新了。
  6. 最好在 「只有单表操作」 的表的 namespace 使用缓存, 而且对该表的操作都在这个 namespace中。 否则可能会出现数据不一致的情况。

十. 列名和属性名不一致问题

如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名(结果集中的字段名)和属性名会自动匹配.

1)通过resultMap标签自定义表与javabean类型的映射情况

​ 不同名的字段必须手动设置映射关系

​ 同名的字段可以不设置,默认会根据自动映射机制找同名

2)为字段起别名

​ 要求字段的别名与类型对应的属性名保持一致

1.使用resultMap

resultMap用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap,表示不再采用自动映射机制.

<mapper namespace="com.yjxxt.mappers.DeptMapper">
    <!--自定义结果的映射关系-->
    <resultMap id="deptMap" type="Dept">
        <!--id : 定义主键字段与属性的映射关系-->
        <id column="deptno" property="id"/>
        <!--id : 定义非主键字段与属性的映射关系-->
        <result column="dname" property="name" />
        <!--<result column="loc" property="loc" />-->
    </resultMap>

    <!--resultMap-->
    <!--<select id="queryAll" resultMap="deptMap">
        select * from dept
    </select>-->

    <!--别名实现-->
    <select id="queryAll" resultType="dept">
        select deptno id,dname name,loc from dept
    </select>
</mapper>

2.关系映射查询

数据库中表与表之间的关系:
一对一 (人->身份证)

一对多 (夏令营->学生)

多对一 (学生->班级)

多对多 (学生->课程)

3.resultMap 的关联方式实现多表查询(一对一|多对一)

  1. 在 EmpMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应班级的信息.
  2. 通过resultMap标签定义映射关系, 并通过association标签指定对象属性的映射关系. 可以把association标签看成一个resultMap标签使用. javaType 属性表示当前对象, 可以写全限定路径或别名.
<!--
    关系映射查询
        resultMap 的关联方式实现多表查询(一对一|多对一)
-->
<mapper namespace="com.yjxxt.mappers.EmpMapper">
    <!--自定义结果集中的字段与javabean类中属性的映射关系-->
    <resultMap id="EmpDept" type="Emp">
        <!--主键字段与属性的映射关系-->
        <id column="empno" property="empno"></id>
        <!--非主键字段与属性的映射关系-->
        <result column="ename" property="ename"></result>
        <result column="job" property="job"></result>
        <result column="mgr" property="mgr"></result>
        <result column="hiredate" property="hiredate"></result>
        <result column="sal" property="sal"></result>
        <result column="comm" property="comm"></result>
        <result column="deptno" property="deptno"></result>
        <!--association : 定义javabean类型属性与字段的映射关系-->
        <association property="pddDept" javaType="Dept">
            <id property="id" column="deptno" />
            <result property="name" column="dname" />
            <result property="loc" column="loc" />
        </association>
    </resultMap>
    <select id="queryEmpDept" resultMap="EmpDept">
        select empno,ename,job,mgr,hiredate,sal,comm,emp.deptno,dname,loc from emp join dept on emp.deptno = dept.deptno
    </select>
</mapper>
	private int empno;
    private String ename;
    private double sal;
    private String job;
    private double comm;
    private int mgr;
    private Date hiredate;
    private int deptno;

    //属性: javabean : 员工对象所在的部门信息
    private Dept pddDept;

4.resultMap 的关联方式实现多表查询(一对 多)

  1. 在 ClazzMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应学生的信息.

  2. 通过resultMap定义映射关系, 并通过collection标签指定集合属性泛型的映射关系. 可以collection标签看成一个resultMap标签使用.ofType 属性表示集合的泛型, 可以写全限定路径或别名.

班级类中添加一个List容器存储学生类型 的数据 :

public class Clazz implements Serializable{
private int id;
private String name;
private int roomNum;
  private List<Student> stus;
}
<mapper namespace="com.yjxxt.mapper.ClazzMapper">
<resultMap type="clazz" id="cmap">
<id property="id" column="cid" />
<result property="name" column="cname" />
<result property="room" column="room" />
<collection property="stus" javaType="list"
ofType="student">
<id property="id" column="sid" />
<result property="name" column="sname" />
<result property="age" column="age" />
<result property="gender" column="gender" />
<result property="cid" column="cid" />
</collection>
</resultMap>
<select id="selAll" resultMap="cmap">
   select c.id cid, c.name cname,
c.room, s.id sid, s.name sname, s.age, s.gender from t_student s right
join t_class c on s.cid=c.id </select>
</mapper>

十一.注解开发

Mybatis中注解的作用:

使用注解一般用于简化配置文件. 但是, 注解有时候也不是很友好(有时候反而更麻烦), 例如动态 SQL等,所
以注解和配置文件可以配合使用

1.CRUD 注解

@Select: 类似于select标签

@Insert: 类似于insert标签

@Update: 类似于update标签

@Delete: 类似于delete标签

2.其他注解

@Results: 类似于resultMap标签

@Result: 类似<resultMap的子标签

@One: 类似于association标签

@Many: 类似于collection标签

// 查询所有的部门信息
    @Select("select * from dept")
    public List<Dept> queryAll();

    //插入一个新的部门信息
    int insertDept(Dept dept);

    //根据部门编号修改部门名称
    int updateDept(@Param("deptno") int deptno, @Param("dname") String dname);

    //根据部门编号删除
    int deleteDept(int deptno);
Mybatis三剑客(mybatis-generator、mybatis-plugin、mybatis-pagehelper)介绍、配置及破解 本文用的是maven,idea15Mabatis三剑客分别是:mybatis-generator、mybatis-plugin、mybatis-pagehelper一、mybatis-generator根据我们的数据库自动生成pojo、dao和xml文件 pojo里面放的是跟数据库字段一一对应的对象、dao层是接口,供service使用,xml是这个dao层接口的实现,sql语句都写在xml里1. 阅读详情

相关推荐

深度解析 MyBatis 生态三大主流框架:MyBatis-Flex、MyBatis-Plus 与 Fluent-MyBatis

本文对比分析了MyBatis三大增强框架:MyBatis-Flex、MyBatis-Plus和Fluent-MyBatis。MyBatis-Flex采用轻量级架构,无SQL解析设计使其性能最佳;MyBatis-Plus功能全面,企业级特性丰富;Fluent-MyBatis提供流式API,代码可读性强。三者各具特色,开发者可根据性能需求、功能要求和开发体验选择合适的框架。

awei0916的专栏 1944

Mybatis-Plus和Mybatis区别

核心关系:MyBatis-Plus 是 MyBatis 的增强版,完全兼容 MyBatis,不改变原有使用方式,仅做功能补充。核心差异:MP 提供了「通用 CRUD、条件构造器、分页插件、代码生成器」等开箱即用的功能,大幅减少重复代码;而原生 MyBatis 更侧重 SQL 的手动控制。选型建议:优先选 MyBatis-Plus(开发效率更高),遇到复杂 SQL 时,仍可像原生 MyBatis 一样手动编写,兼顾效率与灵活性。

weixin_53050448的博客 1241

避坑指南:Win10安装Docker Desktop时Hyper-V报错的7种解决方案(2024最新版)

本文提供了2024年最新、最全面的Windows 10系统下Docker Desktop安装时Hyper-V报错的解决方案指南。文章深入剖析了Hyper-V与Docker的共生关系,并系统性地给出了从BIOS/UEFI设置、Windows功能启用、bcdedit命令修复到处理多虚拟化环境共存等7种核心解决方案,帮助开发者彻底解决安装困局,顺利部署容器化开发环境。

weixin_28840143的博客 530

MYBATIS缓存

MYBATIS的第一缓存是SQLSession 并且这种缓存是即使在仅仅只有一个框架的情况下都是存在的, 因为第一缓存是默认开启的(default), 因为第一缓存级别使用的是SqlSession, 所以在调用同一个SqlSession, 并且在这同一个SqlSession当中多次查询同一个数据, 那么仅仅只会执行一次相应的SQL语句, 之后会直接从SQL缓存当中进行获取以我的测试类为例@Test结果如图所示, 跟我们预想的一样, 在第一级别的缓存下, 仅仅调用了一次相应的查询语句。

2303_79546217的博客 1432

【鸿蒙游戏上架审核规范指南】

华为鸿蒙游戏上架审核规范指南摘要

weixin_44161102的博客 924

Unity性能优化 - 动态图集

Unity 动态图集是 Unity 引擎中用于处理游戏纹理优化的一种技术。本文介绍了什么是动态图集,动态图集的优缺点,以及提供了一套完整的代码供大家参考。

qq_33808037的博客 4840

MyBatis

mybatis、mybatis-spring、mybatis-springboot源码学习

parkerJ 645

杰理外挂flash使用教程(四):制作fat32文件系统格式的资源文件

本文档提供了FAT文件系统镜像生成与资源打包的完整指南,包含两种实现方案:推荐的WSL/Ubuntu环境方案和Windows原生方案。详细说明了从创建空白镜像、格式化、资源文件复制到最终打包为设备可用的res.bin文件的完整流程,并对比了FAT32与FAT16的特性差异。文档还包含关键文件说明、使用注意事项和典型应用场景,适用于嵌入式系统开发、固件升级等场景。

qq_42014563的博客 1340

Mybatis的批量操作

每种方法都有其适用场景和限制。例如,使用 标签生成的批量 SQL 在某些数据库中可能因为 max_allowed_packet 大小限制而失败。因此,在选择批量处理方案时,需要根据具体的业务需求和数据库特性进行综合考虑。愿你我都能在各自的领域里不断成长,勇敢追求梦想,同时也保持对世界的好奇与善意!

weixin_45809780的博客 2602

innovus获取mem pin shape box脚本

innovus mem 的pin shae只能通过attitude editor看属性获取其pin shape的box,但是想用脚本处理一定box时,没有别的办法能直接获取box属性。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 1108

芒果YOLO11改进23:主干Backbone篇GhostNet:原创改进高效 GhostNet 网络,华为出品,打造全新检测器

主干Backbone篇GhostNet:原创改进高效 GhostNet 网络,华为出品,打造全新检测器

包括YOLOv5、YOLOv7、YOLOv8等模型改进 406

MyBatis02-mybatis-config.xml配置文件讲解

mybatis-config.xml核心配置文件,内容的讲解

qq_31532983的博客 1404

代谢组数据分析(二十六):LC-MS/MS代谢组学和脂质组学数据的分析流程

本教程概述了LC-MS/MS在代谢组学和脂质组学数据分析中的应用流程。首先介绍了样本的采集、提取和LC-MS/MS分析,随后详细阐述了质谱数据的预处理、峰值识别、特征注释,以及数据标准化和统计分析的重要性。特别强调了使用XCMS和CAMERA进行数据对齐和加合物识别,以及利用MultiABLER和LipidFinder进行数据过滤、插补和标准化处理。此外,还介绍了如何应用EigenMS算法进行数据标准化,以及如何使用Limma包进行差异分析。整个流程旨在提高数据质量,确保分析结果的准确性和可靠性,为后续的生

专注生信领域 1956

Spring Boot整合MyBatis实现简单的CRUD

这篇文章主要针对java初学者,详细介绍如何创建一个基本的springboot项目来对数据库进行crud操作。

沐雨橙风ιε的博客 4489

NX二次开发PK获取对象类型

PK_ENTITY_ask_class(),获取对象类型建议用这个函数,比较通用,包含所有对象类型,可以替代UF_MODL_ask_edge_type(),UF_MODL_ask_body_type(),UF_MODL_ask_face_type()等函数。

qq_39541524的博客 827

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

springboot整合mybatis(一)入门

mybatis

xiatianit的博客 3026

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

MyBatis缓存机制学习

MyBatis缓存机制解析:本文详细介绍了MyBatis的一级缓存和二级缓存机制。一级缓存默认开启,作用域为SqlSession,基于HashMap存储;二级缓存需手动配置,作用域为Mapper级别,支持第三方缓存框架如EhCache。文章通过代码示例演示了缓存特性,测试了缓存生效条件,并详细解析了缓存标签属性(回收策略、刷新间隔等)。同时介绍了MyBatis与EhCache的整合步骤,包括依赖配置、参数调整等。最后分析了二级缓存的适用场景(读多写少、非敏感数据)和局限性(分布式环境不一致、缓存粒度粗等问题

ywl470812087的博客 12万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

MyBatis是什么?MyBatis-Plus是什么?

MyBatis就是负责实现数据持久化的一套半成品程序,MyBatis-Plus是基于MyBatis的一个增强框架。

m0_58137791的博客 508

Mybatis动态查询条件构建的历史演进:MyBatis,MyBatis-Generator-Example,MyBatis-Plus,MyBatis-Flex

Mybatis动态查询条件构建的历史演进:MyBatis,MyBatis-Generator-Example,MyBatis-Plus,MyBatis-Flex。 MyBatis-Generator动态查询条件构建。 updateByExampleSelective的含义。

宋冠巡的博客 1843

【Mybatis】mybatis原生与mybatis-puls效率比较

【Mybatis】mybatis原生与mybatis-puls效率比较 背景 mybatis-plus是近年来最流行的mybatis敏捷开发的插件,提供了简单的crud与条件查询.我们现在就来比较一下mybatis-plus与原生的mybatis比较一下效率问题 mybatis-plus官网 开始 我们先的有一个工具,能知道mapper层代码的执行时间,这个在我的博客里已经有了.需要的朋友可以...

清欢渡的博客 6562

Mybatis批量插入的几种方式

这种方式是我们比较常用的方式,比传统的循环调用xml插入语句要好得多,在MySql的文档中也提到过这个,如果要优化插入速度时,可以将许多小型操作组合到一个大型操作中。在我们的项目中,会不停地使用批量插入这个方法,而因为MyBatis对于含有的语句(即包含元素),无法采用缓存,所以在每次调用方法时,都会重新解析sql语句。在相关的情况下:将有大量的记录要插入,并且将达到数据库配置的限制(默认情况下,每条语句大约有2000个参数),如果语句本身变得太大,最终可能会出现DB堆栈错误。

qq_58557109的博客 4269

Mybatis增强版MyBatis-Flex介绍

本文介绍了 Mybatis-Flex,一个用于增强 MyBatis 的框架。相对于 MyBatis-Plus,Mybatis-Flex提供了一些显著的特点,如支持联表查询以及在Mybatis-Plus中收费的功能在Mybatis-Flex中是免费的。文章概述了 MyBatis-Flex 的功能特点,并深入介绍了联表查询的不同方案。

沉淀所学,分享所思,让热爱与成长同行。商务记录AI实战经验,助力开发者快速成长。 热爱AI,希望做出有影响力的技术成果。 技术点亮生活,分享连接价值与机会。 专注AI落地实战,陪你走好技术每一步。 3万+

Mybatis与Mybatis-Plus实现及区别详解

本文将详细介绍Mybatis和Mybatis-Plus的实现原理以及它们之间的区别。通过文字和图片并茂的方式,帮助读者更好地理解这两种持久层框架。 Mybatis和Mybatis-Plus都是基于MyBatis的持久层框架,用于简化数据库操作。Mybatis是一个底层的持久层框架,它支持定制化SQL、存储过程以及高级映射。而Mybatis-Plus则是在Mybatis的基础上进行增强的工具,提供了一套通用的CRUD操作接口,省去了每次都要手写sql语句的麻烦。

a_20220306283ljc的博客 2626
上一篇: Oracle 数据库
下一篇: HTML的基础
地球魔
博客等级 码龄6年 317粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值