Springboot-Mybatis(idea)-自学笔记

发布时间 2023-08-07 14:58:31作者: 一粒金灿米

Spring-boot-Mybaties快速入门

使用Mybatis查询所有用户数据

  1. 准备工作(创建springboot工程,数据库表格user,实体类User)

  2. 引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)

  3. 编写SQL语句(注解/XML)

  4. 单元测试

    package com.example;
    
    import com.example.mapper.UserMapper;
    import com.example.pojo.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    
    @SpringBootTest  //springboot整合单元测试的注解
    class SpringbootMybatiesQuickstartApplicationTests {
    
    	//自动装配
    	@Autowired
    	private UserMapper userMapper;
    
    
    	@Test
    	public void testListUser(){
    		//将查询到的数据 放到 userList里,之后通过 foreach遍历输出
    		List<User> userList=userMapper.list();
    		userList.stream().forEach(user -> {
    			System.out.println(user);
    		});
    	}
    }
    
    

lombok

  • 使用前,先在pom中引用。

    <dependency>
    			<groupId>org.projectlombok</groupId>
    			<artifactId>lombok</artifactId>
    </dependency>
    
  • 注意事项:Lombok会在编译时,自动生成对应的java代码。我们在使用lombok时,还需要安装一个lombok的插件(idea自带)

  • Lombok是一个实用的Java类库,能通过注解的像是自动生成构造器,getter/setter,equals,hashcode,toString等方法,并可以自动化生成日志变量,简化java开发,提高效率。

    注解                                                                 作用
     @Getter/@Setter                                        为所有属性提供get/set方法
     @ToString                                             会给类自动生成易阅读的toString方法
     @EqualsAndHashCode                            根据类所拥有的非静态字段自动重写equals方法和hashCode方法
     !! @Data                    提供了更综合的生成代码功能(@Getter +@Setter+@ToString +@EqualsAndHashCode)
     !! @noArgsConstructor       为实体类生成无参的构造器方法
     !! @AllArgsConstructor      为实体类生成除了static修饰的字段之外带有各参数的构造器方法
    
  1. <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    例如:添加该行
    <version>2.2.6.RELEASE</version>
    创建的项目中的 pom.xml依赖 爆红,解决办法是 在下面指定 版本号
    

Mybatis基本操作

输出mybatis日志

  • 可以在application.properties中打开,打开mybaties的日志,并指定输出到控制台

    #指定mybatis输出日志的位置,输出控制台
    mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    

参数占位符

    • 执行SQL时,会将#{...}替换为?,生成预编译SQL,会自动设置参数值
    • 使用时机:参数传递,都使用#
  • $
    • 拼接SQL.直接将参数拼接到SQL语句中,存在SQL注入问题
    • 使用时机:如果对表名,列表进行动态设置时使用。

根据主键删除

  • SQL语句:

    delete from emp where id=9;
    
  • 接口方法

    @Delete("delete from emp where id=#{id}")    //里面写sql语句。#{}为动态获取
    public void delete(Integer id);
    
  • 注意事项

    如果mapper接口方法形参只有一个普通类型的参数,#{...}里面的属性名可以随便写,如#{id},#{value}
    

新增

  • SQL语句:

    insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)
      values('Tom','汤姆',1,'1.jpg',1,'2005-02-03',1,now(),now());
    
  • 接口方法:

       //新增用户信息
     @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +"values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
        public  void insert(Emp emp);
    
  • 主键返回

    描述:在数据添加成功后,需要获取插入数据库数据的主键。如:添加套餐数据时,还需要维护套餐菜品关系表数据。

  • 实现:

       @Options(keyProperty = "id",useGeneratedKeys = true)  //返回插入内容的主键信息 添加该行内容
        @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" +
                "values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
        public  void insert(Emp emp);
    

更新

  • SQL语句:

     update emp set username ='',name='',gender='',image='',job='',
                entrydate='',dept_id='',update_time='' where id=1;
    
  • 接口方法:

     @Update("update emp set username =#{username},name=#{name},gender=#{gender},image=#{image},job=#         {job},\n" +"entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}")
        public void update(Emp emp);
    

查询(根据ID查询)

  • SQL语句

    select * from emp where id=10;
    
  • 接口方法

     @Select("select * from emp where id=#{id}")
        public Emp getByID(Integer id);        //将返回值封装到一个对象中
    
  • 数据封装

    • 实体类属性名 和 数据库表查询返回的字段名一致,mybatis会自动封装

    • 如果实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装

    • 为解决不能封装的问题

      • 方案一:起别名,在SQL语句中,对不宜阿姨那个的列名起别名,别名和实体类属性名一样。

            @Select("select id, username, password, name, gender, image, job, " +
                    "entrydate, dept_id deptId, create_time createTime, update_time updateTime from emp where id=#{id}")
            public Emp getByID(Integer id);
        
      • 方案二:通过@Results,@Result注解手动映射封装

            @Results({
                    @Result(column = "dept_id",property = "deptId"), 
                	//dept_id表中的字段名。
                	//property = "deptId"  指封装到 deptId
                    @Result(column = "create_time",property = "createTime"),
                    @Result(column = "update_time",property = "updateTime")
            })
        
            @Select("select * from emp where id=#{id}")
            public Emp getByID(Integer id);
        
      • 方案三:开启mybatis的驼峰命名自动映射开关 ---- a_cloumn ------->aCloumn。如果字段名与属性名符合驼峰命名规则,mybatis会通过驼峰命名规则映射。(强烈推荐)必须要遵守驼峰命名规则。

          //开启mybatis的驼峰命名自动映射开关 ---- a_cloumn ------->aCloumn
          //需要在application.properties 中开启
          mybatis.configuration.map-underscore-to-camel-case=true
        

查询(根据条件查询)

  • SQL语句

    select * from  emp where name like '%张%' and gender = 1 and entrydate
        between '2000-01-01' and '2025-05-06' order by update_time desc;
    
  • 接口方法:

    //未预编译。 性能低,不安全,存在SQL注入问题
    @Select("select * from  emp where name like '%${name}%' and gender = #{gender} and" +
                " entrydate between #{begin} and #{end} order by update_time desc")
        public List<Emp> list(String name, Integer gender, LocalDate begin,LocalDate end);
    
    //通过sql自带的函数concat进行字符的拼接  !!!推荐使用
     @Select("select * from  emp where name like concat('%',#{name},'%') and gender = #{gender} and" +
            " entrydate between #{begin} and #{end} order by update_time desc")
        public List<Emp> list(String name, Integer gender, LocalDate begin, LocalDate end);
    

XML映射文件(特别重要)

规范

  • XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
  • XML映射文件的namespace属性为Mapper接口全限定名一致。 必须是完整的全类名。
  • XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
  • image-20230802093602052

Mybatis的动态SQL语句

随着用户的输入或外部条件的变化而变化的SQL语句,称之为动态SQL

  • :用于判断条件是否成立,使用test属性进行条件判断,如果条件为true,则拼接SQL

     <if test="name != null">  //如果;里面的语句判断为true,则拼接下面的SQL语句
           name like concat('%', #{name}, '%')
     </if>
    

    完整写法:

    :where元素只会在子元素有内容的情况下才插入where子句。而且会自动去除子句的AND或OR.

    <select id="list" resultType="com.example.pojo.Emp">
            select *
            from emp
            <where>   //mybatis的语法。可以根据下面的 情况自动添加  and.
                <if test="name != null">
                    name like concat('%', #{name}, '%')
                </if>
                <if test="gender != null">
                    and gender = #{gender}
                </if>
                <if test="begin != null and end != null">
                    and entrydate between #{begin} and #{end}
                </if>
            </where>
            order by update_time desc
        </select>
    

    :动态地在行首插入SET关键字,并会删除额外的逗号。(用在update语句中)

    <update id="update2">
            update emp
            <set>
                <if test="username != null">username = #{username},</if>
                <if test="name != null">name= #{name},</if>
                <if test="gender != null">gender = #{gender},</if>
                <if test="image != null">image = #{image},</if>
                <if test="job != null">job = #{job},</if>
                <if test="entrydate != null">entrydate = #{entrydate},</if>
                <if test="deptId != null">dept_id = #{deptId},</if>
                <if test="updateTime != null">update_time = #{updateTime}</if>
            </set>
            where id = #{id}
        </update>
    
    • SQl语句:

      delete from emp where id in(1,2,3)
      
    • 接口方法

      //批量删除
         @Test
          public void testDeleteByIds(){
              List<Integer> ids= Arrays.asList(9,10);
              empMapper.deleteByIds(ids);
          }
      
    • XML映射文件

         <!--
          collection:遍历的集合
          item:遍历出来的数据
          separator:分隔符
          open:遍历开始前拼接的SQl片段
          close:遍历结束后拼接的SQL片段
          -->
      <delete id="deleteByIds">
              delete from emp where id in
              <foreach collection="ids" item="id" separator="," open="(" close=")">
                  #{id}
              </foreach>
      </delete>
      
  • SQL片段

    • :定义可重用的SQL片段

    • :通过属性refid,指定包含的sql的片段

       <sql id="commonSelect">
              select id,username,password,name,gender,image,job,entrydate,dept_id,creat_time,update_time from emp
        </sql>
           
           
      <select id="list" resultType="com.example.pojo.Emp">
             <include refid="commonSelect" />
              <where>
                  <if test="name != null">
                      name like concat('%', #{name}, '%')
                  </if>
                  <if test="gender != null">
                      and gender = #{gender}
                  </if>
                  <if test="begin != null and end != null">
                      and entrydate between #{begin} and #{end}
                  </if>
              </where>
              order by update_time desc
      </select>