MyBatis知识点总结-DX的笔记

MyBatis知识点总结

什么是MyBatis?

  • 它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低
  • ORM(Object Relation Mapping)对象关系映射
    • 对象:Java对象
    • 关系:数据库中的关系模型
    • 对象关系映射:Java对象和数据库的关系模型之间建立一种对用关系
    • 比如用一个Java的Student类,去对应数据库中的一张student表,类中的属性和表中的列一一对应
    • Student类就对应student表,一个Student对象就对应student表中的一行数据
  • mybatis的特点
    • mybatis是:半自动的ORM框架,需要手动编写SQL语句
    • 全自动的ORM框架(如:hibernate),不需要编写SQL语句
    • hibernate只需设置好ORM映射关系,就可以实现CRUD操作
    • mybatis需要手写SQL,灵活性更高,但是换数据库时,需要重写SQL,因为mybatis的数据无关性低
    • 相对于JDBC,它提供了输入映射和输出映射,方便sql的参数设置和结果集封装
    • 提供了关联查询动态SQL等功能,极大地提升了开发的效率

项目创建思路整理

项目结构

  • 创建Maven项目

  • 在pom.xml文件中导包

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.1</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.19</version>
        </dependency>
      </dependencies>
    
  • 在Java目录下建包

    • entity 实体类
    • utils 工具类
    • dao 数据操作对象
  • 在resources目录下建mybatis-config.xml文件

项目搭建好,开始干活

  1. 编写实体类

    • Student.java
    • 成员变量与字段名尽量相同
  2. 连接数据库的准备

    • 在mybatis-config.xml中写配置信息

      <?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>
              <setting name="logImpl" value="STDOUT_LOGGING"/>
          </settings>
      
          <!--配置数据库操作环境-->
          <environments default="mysql">
              <environment id="mysql">
                  <transactionManager type="JDBC"></transactionManager>
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql:///stusys?serverTimezone=UTC"/>
                      <property name="username" value="root"/>
                      <property name="password" value="111111"/>
                  </dataSource>
              </environment>
          </environments>
      
          <!--配置映射文件-->
          <mappers>
              <mapper resource="mapper/StudentMapper.xml"></mapper>
      <!--        <mapper class="com.dx.dao.StudentDao"></mapper>-->
          </mappers>
      </configuration>
      
  3. 写数据库连接的工具类

    public class MyBatisUtil {
        static SqlSessionFactory factory=null;
        static {
            try {
                InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
                factory = new SqlSessionFactoryBuilder().build(in);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public static SqlSession getSqlSession(){
            return factory.openSession();
        }
    }
    
  4. 开始写DAO层(数据连接对象)

    • 写StudentDao接口文件

      public interface StudentDao {
      
          List<Student> select();
      
          Student selectById(int id);
      
          int insert(Student student);
      
          int updata(Student student);
      
          int deleteById(int id);
      }
      
    • 写映射文件StudentMapper.xml

      <?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="StudentMapper">
      
          <select id="select" resultType="com.dx.entity.Student">
              select * from student
          </select>
          <select id="selectById" parameterType="int" resultType="com.dx.entity.Student">
              select * from student where id=#{id}
          </select>
      
          <insert id="insert" parameterType="com.dx.entity.Student">
              insert into student(sname,age,gender,address,phone,remark) values(#{sname},#{age},#{gender},#{address},#{phone},#{remark})
          </insert>
      
          <update id="updata" parameterType="com.dx.entity.Student">
              update student set sname=#{sname},age=#{age},gender=#{gender},address=#{address},phone=#{phone},remark=#{remark} where id=#{id}
          </update>
      
          <delete id="deleteById">
              delete from student where id = #{id}
          </delete>
      
      </mapper>
      
  5. 写实现类

    public class StudentDaoImpl implements StudentDao {
        @Override
        public List<Student> select() {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            //传入的第一个参数为:mapper文件中的命名空间名称.sql语句id
            List<Student> students = sqlSession.selectList("StudentMapper.select");
            sqlSession.close();
            return students;
        }
    
        @Override
        public Student selectById(int id) {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            //传入的第二个参数为:查询条件,如果有多个查询条件应该封装成对象(对象的成员变量名要与sql的字段名保持一致)或使用map
            Student student = sqlSession.selectOne("StudentMapper.selectById",id);
            sqlSession.close();
            return student;
        }
    
        @Override
        public int insert(Student student) {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            int result = sqlSession.insert("StudentMapper.insert", student);
            //增、删、改 都需要提交事务
            //jdbc默认自动提交,MyBatis默认手动提交
            sqlSession.commit();
            sqlSession.close();
            return result;
        }
    
        @Override
        public int updata(Student student) {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            int result = sqlSession.insert("StudentMapper.updata", student);
            //增、删、改 都需要提交事务
            //jdbc默认自动提交,MyBatis默认手动提交
            sqlSession.commit();
            sqlSession.close();
            return result;
        }
    
        @Override
        public int deleteById(int id) {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            int result = sqlSession.insert("StudentMapper.deleteById", id);
            //增、删、改 都需要提交事务
            //jdbc默认自动提交,MyBatis默认手动提交
            sqlSession.commit();
            sqlSession.close();
            return result;
        }
    }
    
  6. 写测试类

    public class MyTest {
    
        @Test
        public void crudTest(){
    
            StudentDaoImpl studentDao = new StudentDaoImpl();
    
            //查
    //        List<Student> student = new StudentDaoImpl().select();
    //        Student student = studentDao.selectById(2);
    //        System.out.println(student);
    
            //增
    //        Student student = new Student("莎莎", 22, "1", "zhegnzhou", "1242330", "iafg");
    //        int res = studentDao.insert(student);
            //改
    //        Student student = new Student(17, "shasha", 22, "1", "zhegnzhou", "1242330", "iafg");
    //        int res = studentDao.updata(student);
            //删
            int res = studentDao.deleteById(17);
    
            if (res == 1) {
                System.out.println("成功");
            } else {
                System.out.println("失败");
            }
        }
    }
    

代理模式

dao接口+mapper文件

要求

  1. mapper文件中的命名空间必须与dao接口的全限定名保持一致
  2. mapper文件中的sql语句ID必须与dao接口中的方法名称保持一致
  3. mapper文件中parameterType传入参数类型必须与dao接口中的方法形参类型保持一致
  4. mapper文件中resultType传出结果类型必须与dao接口中的方法返回值“保持一致”

使用方法

  • 不使用代理模式

    SqlSession sqlSession = MybatisUtil.getSqlSession();
    //两个参数(Mapper的命名空间名.sql标签的id , [传入的参数] )
    Emp emp = sqlSession.selectOne("empNamespace.selectById", 7566);
    System.out.println(emp);
    sqlSession.close();
    
  • 使用代理

    SqlSession sqlSession = MybatisUtil.getSqlSession();
    //获取Mapper代理对象 			getMapper(接口.class)		返回值为当前指定接口的实现对象
    DeptDao deptDao = sqlSession.getMapper(DeptDao.class);
    Dept dept = deptDao.selectById(10);
    System.out.println(dept);
    sqlSession.close();
    

mybatis配置文件

全局设置(日志和下划线转驼峰)

<settings>
    <!--开启下划线转驼峰-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!--开启sql日志输出-->
    <!--        <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>-->
    <setting name="logImpl" value="LOG4J"/>
</settings>

设置别名

  1. 自带的
    • int -> java.lang.Integer
    • _int -> int
    • double
    • string->java.lang.String
    • map -> java.util.Map,
    • hashmap -> java.util.HashMap
    • list -> java.util.List
  2. 自定义别名
<!--设置别名-->
<typeAliases>
    <!--为单个文件设置别名-->
    <typeAlias type="com.dx.entity.Emp" alias="emp"/>
    <!--为包下的所有文件设置别名,自动生成两个别名:1.类名   2.类名(首字母小写)-->
    <package name="com.dx.entity"/>
</typeAliases>

配置数据操作环境

<environments default="mysql">
    <environment id="mysql">
        <!--事务管理-->
        <transactionManager type="JDBC"></transactionManager>
        <!--数据源-->
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql:///student?serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="111111"/>
        </dataSource>
    </environment>

    <environment id="oracle">
        <transactionManager type="JDBC"></transactionManager>
        <dataSource type="POOLED">
            <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
            <property name="url" value="jdbc:oracle:thin:localhost:1521:orcl"/>
            <property name="username" value="root"/>
            <property name="password" value="111111"/>
        </dataSource>
    </environment>
</environments>

加载mapper映射文件

<mappers>
    <!--在classpath下找mapper文件-->
    <mapper resource="mapper/EmpMapper.xml"/>
    <!--classpath下找指定的类-->
    <mapper class="com.bjpowernode.dao.EmpDao"/>
    <!--批量加载接口
        1.sql使用注解式来提交mapper.xml文件
        2.mapper文件与接口同名,同目录        -->
    <package name="com.bjpowernode.dao"/>
</mappers>

log4j日志管理

日志配置文件

# 全局日志配置
log4j.rootLogger=DEBUG, stdout
# MyBatis 日志配置
#局部日志记录配置
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p %c.%M() --%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File = D:/logs/test.log
#log4j.appender.file.Append = true
#log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

log4j的使用

/**
 * java.util.logging.Logger(JUL)
 */
private Logger logger = Logger.getLogger(Log4jTest.class);

@Test
public void run(){
    //错误信息
    logger.error("error日志");
    //警告信息
    logger.warn("warn日志");
    //普通信息
    logger.info("info日志");
    //调试信息
    logger.debug("debug日志");
    //底层信息
    logger.trace("trace日志");
}

映射配置文件

结果映射

  • 自动映射

    <select id="selectAll" resultType="com.dx.entity.Emp">
    	select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno desc
    </select>
    
  • 手动映射

    <resultMap id="ResultMap" type="emp">
        <!--设置主键字段与属性对应关系-->
        <id column="empno" property="empno"/>
        <!--设置普通字段与属性对应关系-->
        <result column="ename" property="ename"/>
        <result column="job" property="job"/>
        <result column="mgr" property="mgr"/>
        <result column="hiredate" property="hiredate"/>
        <result column="sal" property="sal"/>
        <result column="comm" property="comm"/>
        <result column="deptno" property="deptno"/>
    </resultMap>
    
    <select id="selectAll2" resultMap="ResultMap">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno desc
    </select>
    

占位符#与$

  • ${}的sql是静态sql

  • #{}的sql是动态sql

  • <!--
        #{}占位符,会预编译
        1.传入参数为简单类型,占位符中的变量名称可以随意定义
        2.传入参数为POJO类型,占位符中的变量名称必须与POJO属性名称保持一致
        String sql = "select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=?";
        ${}拼接符号, 会引起SQL注入的问题
        1.传入参数为简单类型,拼接符号中的变量名称不可以随意定义,仅能为value
        2.传入参数为POJO类型,拼接符号中的变量名称必须与POJO属性名称保持一致
        String sql = "select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=" + value;
    -->
    <select id="selectById" parameterType="int" resultType="Emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=#{empno}
    </select>
    <select id="selectById2" parameterType="int" resultType="Emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=${value}
    </select>
    
模糊查询
<!--使用#{}时,这样写是不对的,需要用concat拼接
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where ename like '%#{name}%'-->
<!--方式一:使用concat拼接-->
<select id="selectByEname" parameterType="String" resultType="emp">
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where ename like concat('%',#{name},'%')
</select>
<!--方式二:使用${}拼接-->
<select id="selectByEname2" parameterType="String" resultType="emp">
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where ename like '%${value}%'
</select>
<!--方式三:使用<bind>标签-->
<select id="selectByEname3" parameterType="String" resultType="Emp">
    <bind name="keyname" value="'%'+_parameter+'%'"/>
    select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where ename like #{keyname}
</select>

传入多参数

建议:参数为2-4个使用@Param,参数过多使用实体类或Map集合

传入参数为Map
  • mapper.xml

    <!--传入参数为map集合,占位符的变量名就是map的key-->
    <select id="selectByParam" parameterType="map" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
        where deptno=#{aaa}
        and sal>=#{bbb}
    </select>
    
  • test.java

    @Test
    public void selectByMap(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("aaa",10);
        map.put("bbb",2000);
        List<Emp> emps = empDao.selectByParam(map);
        for (Emp emp : emps) {
        	System.out.println(emp);
        }
        sqlSession.close();
    }
    
使用@Param注解
  • mapper.xml

    <select id="selectByParam2" parameterType="map" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
        where deptno=#{deptno}
        and sal>=#{sal}
    </select>
    
  • dao.java接口

    public List<Emp> selectByParam2(@Param(value="deptno") Integer deptno,@Param("sal") Double sal);
    
  • test.java

    @Test
    public void selectByMap2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        List<Emp> emps = empDao.selectByParam2(10,3000.0);
        for (Emp emp : emps) {
        	System.out.println(emp);
        }
        sqlSession.close();
    }
    

分页查询

  • 使用sql语句

    <select id="selectPage" parameterType="map" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp 
        order by empno limit #{page},#{num}
    </select>
    
  • 使用 RowBounds()

    <select id="selectPage2" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno
    </select>
    
    public List<Emp> selectPage2(RowBounds rowBounds);
    
    //使用RowBounds(起始坐标,展示条数)实现
    RowBounds rowBounds = new RowBounds(10, 5);
    List<Emp> emps = empDao.selectPage2(rowBounds);
    
  • 使用PageHelper插件

    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.2.0</version>
    </dependency>
    
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
    
    <select id="selectPage3" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno
    </select>
    
    //使用分页插件 PageHelper.startPage(当前页码,每页条数);
    PageHelper.startPage(1,5);
    List<Emp> emps = empDao.selectPage3();
    
    //在PageHelper提供一个PageInfo的分页工具类
    PageInfo<Emp> pageInfo = new PageInfo<>(list);
    pageInfo.getList();
    System.out.println("当前页码:" + pageInfo.getPageNum());
    System.out.println("每页条数:" + pageInfo.getPageSize());
    System.out.println("总记录数:" + pageInfo.getTotal());
    System.out.println("总页数:" + pageInfo.getPages());
    System.out.println("上一页:" + pageInfo.getPrePage());
    System.out.println("下一页:" + pageInfo.getNextPage());
    System.out.println("是否有上一页:" + pageInfo.isHasPreviousPage());
    System.out.println("是否有下一页:" + pageInfo.isHasNextPage());
    System.out.println("是否为首页:" + pageInfo.isIsFirstPage());
    System.out.println("是否为末页:" + pageInfo.isIsLastPage());
    System.out.println("页码数组:" + Arrays.toString(pageInfo.getNavigatepageNums()));
    

插入数时返回主键值

  • <!--
        插入数据时,返回主键值(主键需要是自增长)
        useGeneratedKeys: 是否开启返回主键值功能,默认是关闭
        keyColumn: 指定表中的主键字段,如果属性名和字段名相同可省略
        keyProperty: 指定存主键值的实体对象属性名
    -->
    <insert id="insert" parameterType="emp" useGeneratedKeys="true" keyColumn="empno" keyProperty="empno">
        insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
        values (#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
    </insert>
    
  • @Test
    public void insertTest() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        Emp emp = new Emp("小小", "经理", 100, new Date(), 5600.0, 1000.0, 20);
        System.out.println("数据插入前empno="+emp.getEmpno());
        empDao.insert(emp);
        System.out.println("数据插入后empno="+emp.getEmpno());
        sqlSession.commit();
        sqlSession.close();
    }
    

动态sql

  • if

    <!--传入参数是实体类时,参数使用属性名-->
    <select id="selectUseIf" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
        where
        <if test="ename!=null and ename !='' ">
            ename like concat('%',#{ename},'%')
        </if>
        <if test="sal!=null">
            and sal >= #{sal}
        </if>
    </select>
    <!--传入参数是简单类型时,mybatis标签(if、bind等标签)只能用 _parameter 代表传入的参数-->
    <select id="selectUseIf2" parameterType="String" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
        where
        <if test="_parameter!=null and _parameter !='' ">
            ename = #{ename}
        </if>
    </select>
    
  • where和choose

    <select id="selectUseWhere" resultType="emp">
        select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp
        <where>
            <if test="ename!=null and ename !='' ">
                ename like concat('%',#{ename},'%')
            </if>
            <if test="sal!=null">
                and sal >= #{sal}
            </if>
    <!--            <choose>-->
    <!--                <when test=""></when>-->
    <!--                <when test=""></when>-->
    <!--                <when test=""></when>-->
    <!--                <otherwise></otherwise>-->
    <!--            </choose>-->
        </where>
    </select>
    
  • set

    <update id="updateUseSet" parameterType="emp">
        update emp
        <set>
            <if test="ename!=null">
                ename=#{ename},
            </if>
            <if test="job!=null">
                job=#{job},
            </if>
        </set>
        where empno=#{empno}
    </update>
    
  • foreach

    <!--批量删除 Array -->
    <delete id="deleteUseForeach" parameterType="int">
        delete from emp where empno in
        <foreach collection="array" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>
    <!--批量删除 list -->
    <delete id="deleteUseForeach2" parameterType="int">
        delete from emp where empno in
        <foreach collection="list" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>
    
  • Trim

    <!--Trim标签
        insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
        values (#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})   
     
        prefix:sql拼接的前缀
        suffix:sql拼接的后缀
        prefixOverrides:在拼接完成之后去除整个语句中指定前部
        suffixOverrides:在拼接完成之后去除整个语句中指定后部
    -->
    <insert id="insertUseTrim" parameterType="com.dx.entity.Emp">
        insert into emp
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="ename!=null"> ename, </if>
            <if test="job!=null"> job, </if>
            <if test="mgr!=null"> mgr, </if>
            <if test="hiredate!=null"> hiredate, </if>
            <if test="sal!=null"> sal, </if>
            <if test="comm!=null"> comm, </if>
            <if test="deptno!=null"> deptno, </if>
        </trim>
        <trim prefix=" values (" suffix=")" suffixOverrides=",">
            <if test="ename!=null"> #{ename}, </if>
            <if test="job!=null"> #{job}, </if>
            <if test="mgr!=null"> #{mgr}, </if>
            <if test="hiredate!=null"> #{hiredate}, </if>
            <if test="sal!=null"> #{sal}, </if>
            <if test="comm!=null"> #{comm}, </if>
            <if test="deptno!=null"> #{deptno} </if>
        </trim>
    </insert>
    
  • 测试类

    @Test
    public void if_where_choose_Test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        Emp param = new Emp();
        param.setEname("S");
        param.setSal(1000.0);
    	List<Emp> empList = empDao.selectUseIf(param);
        List<Emp> empList = empDao.selectUseWhere(param);
        for (Emp emp : empList) {
            System.out.println(emp);
        }
        sqlSession.close();
    }
    
    @Test
    public void set_Test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        Emp param = new Emp();
        param.setEmpno(666);
        param.setEname("shasha");
        param.setJob("医生");
        empDao.updateUseSet(param);
        System.out.println("插入成功!");
        sqlSession.commit();
        sqlSession.close();
    }
    
    @Test
    public void foreachTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        //批量删除-数组
    	empDao.deleteUseForeach(new Integer[]{1,2,3,4});
        //批量删除-集合
        empDao.deleteUseForeach2(Arrays.asList(1,2,3,4,5,6));
        sqlSession.commit();
        System.out.println("删除成功");
        sqlSession.close();
    }
    

使用注解

使用lombok

  • 导包

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>
    
  • 常用注解

    • @Setter 注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
    • @Getter 使用方法同上,区别在于生成的是getter方法。
    • @ToString 注解在类,添加toString方法。
    • @EqualsAndHashCode 注解在类,生成hashCode和equals方法。
    • @NoArgsConstructor 注解在类,生成无参的构造方法。
    • @RequiredArgsConstructor 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
    • @AllArgsConstructor 注解在类,生成包含类中所有字段的构造方法。
    • @Data 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
    • @Slf4j 注解在类,生成log变量,严格意义来说是常量。private static final Logger log = LoggerFactory.getLogger(UserController.class);

Mybatis注解

  • @Select

  • @Insert

  • @Delete

  • @Update

  • 简单的sql可以用,复杂的不推荐使用

  • 用法

    public interface UserMapper {
        @Insert("insert  into user (name,pwd) value (#{name},#{pwd})")
        Integer insert(User user);
        @Delete("delete  from user where id = #{id}")
        Integer delete(Integer id);
        @Select("select  id,name,pwd from user ")
        List<User> selectAll();
        /* 动态sql 写法 */
        @Select("<script>select  id,name,pwd from user <where> <if test='id != null'>id > 18</if> </where></script>")
        List<User> selectList(@Param("age") Integer age);
    }
    

缓存

一级缓存

  • 一级缓存:在同一个sqlSession中

  • 一级缓存是内存式缓存,必须使用,不能关闭

  • 查询时,先查询一级缓存,如果没有找到数据再发送sql语句查询数据,并将结果放到sqlSession中

  • @Test
    public void firstCacheTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
    
        System.out.println("——————————————————————————第一次查询——————————————————————————");
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        User user = userDao.selectUserById(2);
        System.out.println(user);
    
        //清空一级缓存
        //sqlSession.commit();
    
        System.out.println("——————————————————————————第二次查询——————————————————————————");
        UserDao userDao2 = sqlSession.getMapper(UserDao.class);
        User user2 = userDao2.selectUserById(2);
        System.out.println(user2);
    
        System.out.println("——————————————————————————两次结果对比——————————————————————————");
        System.out.println(user==user2);
    
        sqlSession.close();
    }
    

二级缓存

  • 二级缓存:在同一个SqlSessionFactory中

  • 二级缓存有三个开关

    • 第一个在mybatis-config.xml中设置cacheEnabled为true(默认开启)
    • 第二个在mapper.xml中加上 (不加上就相当于关闭)
    • 第三个在select标签中配置 useCache=“true” (默认开启)
  • 被缓存的数据需要支持序列化,所以存储的对象必须实现可序列化接口

  •  @Test
    public void secondCacheTest(){
        System.out.println("——————————————————————————第一次查询——————————————————————————");
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        User user = userDao.selectUserById(2);
        System.out.println(user);
        sqlSession.close();
    
        System.out.println("——————————————————————————第二次查询——————————————————————————");
        SqlSession sqlSession2 = MybatisUtils.getSqlSession();
        UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
        User user2 = userDao2.selectUserById(2);
        System.out.println(user2);
        sqlSession2.close();
    
        System.out.println("——————————————————————————两次结果对比——————————————————————————");
        System.out.println(user==user2);
    }
    

联表查询⭐

使用的数据库

  • student表
idsnamecid
1小李1
2小陈2
3小郭2
4小夏1
  • classes表
idcname
1一班
2二班
3三班

一对一

  • 查询学生和其所在的班级

  • //Dao接口
    List<Student> selectStudentAndClasses();
    
  • <!--**************************** 简单使用一对多 *********************************-->
    <resultMap id="selectResultMap" type="com.dx.entity.Student">
        <!--主键字段-->
        <id column="id" property="id"/>
        <!--普通字段-->
        <result column="sname" property="sname"/>
        <result column="cid" property="cid"/>
        <!--一对一、多对一 关系映射-->
        <association property="classes" javaType="com.dx.entity.Classes">
            <id column="id" property="id"/>
            <result column="cname" property="cname"/>
        </association>
    </resultMap>
    
    <select id="selectStudentAndClasses" resultMap="selectResultMap">
        select s.id,s.sname,s.cid,c.cname from student s join classes c on s.cid=c.id
    </select>
    
  • 扩展:使用 代码块 和 继承

    <!--**************************** 扩展知识 *********************************-->
    <!--使用继承,将父标签配置全部继承到子标签中-->
    <resultMap id="BaseResultMap" type="com.dx.entity.Student">
        <id column="id" property="id"/>
        <result column="sname" property="sname"/>
        <result column="cid" property="cid"/>
    </resultMap>
    <resultMap id="selectResultMap2" type="com.dx.entity.Student" extends="BaseResultMap">
        <association property="classes" javaType="com.dx.entity.Classes">
            <id column="id" property="id"/>
            <result column="cname" property="cname"/>
        </association>
    </resultMap>
    
    <!--使用sql片段-->
    <sql id="FeildList">
        s.id,s.sname,s.cid,c.cname
    </sql>
    <select id="selectStudentAndClasses2" resultMap="selectResultMap">
        select <include refid="FeildList"></include>
        from student s join classes c on s.cid=c.id
    </select>
    

一对多

  • 查询某个班级里的学生

  • Classes selectById(Integer id);
    
  • <resultMap id="BaseResultMap" type="com.dx.entity.Classes">
        <id column="id" property="id"/>
        <result column="cname" property="cname"/>
    </resultMap>
    <resultMap id="selectByIdResultMap" type="com.dx.entity.Classes" extends="BaseResultMap">
        <collection property="studentList" ofType="com.dx.entity.Student">
            <id column="sid" property="id"/>
            <result column="sname" property="sname"/>
        </collection>
    </resultMap>
    
    <select id="selectById" resultMap="selectByIdResultMap">
        select c.id,c.cname,s.id sid,s.sname from classes c left join student s on c.id=s.cid where c.id=#{id}
    </select>
    
关联查询
  • Dao接口

    Classes selectOne(Integer id);
    
  • StudentMapper.xml

    <!--********* 用于ClassesMapper.xml中的关联查询 *********-->
    <select id="selectByCid" resultType="com.dx.entity.Student">
        select id,sname
        from student where cid=#{cid}
    </select>
    
  • ClassesMapper.xml

    <!--************************ 关联查询 ************************-->
    <resultMap id="SelectOneResultMap" type="com.dx.entity.Classes" extends="BaseResultMap">
        <!--
        	column:传递到关联查询中的数据字段名称
        	select:表示关联数据到什么地方查询
    	-->
        <collection property="studentList" ofType="com.dx.entity.Student"
                    column="id" select="com.dx.dao.StudentDao.selectByCid">
        </collection>
    </resultMap>
    
    <select id="selectOne" parameterType="int" resultMap="SelectOneResultMap">
        select id,cname
        from classes
        where id=#{id}
    </select>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值