SpringBoot整合Mybatis+Mp_day03

1.SpringBoot整合Mybatis说明

1.1 Mybatis介绍

1、MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
2、MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL语句 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索以及释放资源等jdbc繁杂的过程代码。
3、Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
4、总之,Mybatis对JDBC访问数据库的过程进行了封装,简化了JDBC代码,解决JDBC将结果集封装为Java对象的麻烦。

1.2 ORM思想

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

核心知识:
宗旨:利用对象操作数据库
1、要求查询的结果集可以自动封装为对象(查-读)
2、利用对象封装数据,之后(自动)动态的生成SQL语句,进行CRUD操作(写)

1.3 @SpringBootTest注解

说明:@SpringBootTest注解是SpringBoot自1.4.0版本开始引入的一个用于测试的注解

/**
 * 要求:1、注解类所在的包要与启动类在相同包下或者在其子包下
 *      2、从Spring容器中获取对象调用
 */
@SpringBootTest
public class ControllerTest {

    /**
     * 调用由spring容器管理的 Controller Service UserMapper 接口中的方法
     */
    @Autowired
    private UserMapper userMapper;//代理对象

    @Test
    public void test1(){
        List<User> list = userMapper.selectAllUser();
        for (User user:list) {
            System.out.println(user);
        }
    }

}

1.4 Mybatis的调用过程

1、Spring容器为接口创建实例对象或者代理对象
2、根据@Autowired注解为接口注入实例化对象/代理对象
3、用户通过Mapper接口,调用接口中的方法
4、接口根据全限定路径去对应XXX.xml文件中的namespace从而映射到.xml文件
5、再根据接口中的方法名去对应XXX.xml文件中的SQL语句的ID,从而执行SQL语句
6、将返回的结果集读入到用来封装数据的对象中去

在这里插入图片描述

1.5 Mybatis的动态SQL语句

引用:

<sql id="col">
     id,name,age,sex
 </sql>

1.5.1 if语句

<select id="selectUserByUsernameAndSex" resultType="User">
       select <include refid="col"></include>  from demo_user
       <if test="name!=null">
           name=#{name}
       </if>
        <if test="sex!=null">
            and sex=#{sex}
        </if>
   </select>

这样写我们可以看到,如果 sex 等于 null,那么查询语句为 select * from user where name=#{name},但是如果name 为空呢?那么查询语句为 select * from demo_user where and sex=#{sex},这是错误的 SQL 语句,如何解决呢?请看下面的 where 语句

1.5.2 where语句

<select id="selectUserByUsernameAndSex" resultType="User">
        select <include refid="col"></include>  from demo_user
        <where>
        <if test="name!=null">
            name=#{name}
        </if>
        <if test="sex!=null">
            and sex=#{sex}
        </if>
        </where>
    </select>

这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

1.5.3 if+set语句

<update id="updateUserById">
        update  demo_user
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="sex!=null and  sex!=''">
                sex=#{sex}
            </if>   
        </set>
        where  id=#{id}
    </update>

如果第一个条件 username 为空,那么 sql 语句为:update demo_user set sex=? where id=?
如果第一个条件不为空,那么 sql 语句为:update demo_user set name = ? ,sex = ? where id=?

1.5.4 choose(when,otherwise) 语句

<select id="selectUserByChoose" resultType="User">
        select  <include refid="col"></include>  from demo_user
        <where>
            <choose>
                <when test="id!=null and id!=''">
                    id=#{id}
                </when>
                <when test="name!=null and name!=''">
                    and name =#{name}
                </when>
                <otherwise>
                    and sex=#{sex}
                </otherwise>
            </choose>
        </where>
    </select>

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

1.5.4 trim 语句

trim标记是一个格式化的标记,可以完成set或者是where标记的功能
①、用 trim 改写上面第二点的 if+where 语句
prefix:前缀      
prefixoverride:去掉第一个and或者是or

<select id="selectUserByUsernameAndSex" resultType="User">
        select  <include refid="col"></include> from demo_user
        <trim prefix="where" prefixOverrides="and | or">
            <if test="name!=null">
               and  name=#{name}
            </if>
            <if test="sex!=null">
               and  sex=#{sex}
            </if>
        </trim>
    </select>

分析
1、当name与sex都满足if语句时,此时去除第一个if判断句的and,此时sql语句为 select * from demo_user where name=#{name} and sex=#{sex}
2、当name不满足if语句,sex满足时,那么第二个if语句prefixoverride生效,第二个if语句中的and被去除,此时sql语句为:select * from demo_user where sex=#{sex}
3、相反当name满足,sex不满足时,sql语句为:select * from demo_user where name=#{name}
 
 ②、用 trim 改写上面第三点的 if+set 语句
suffix:后缀  
suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)

<update id="updateUserById" >
        <trim prefix="set" suffixOverrides=",">
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="sex!=null and  sex!=''">
                sex=#{sex},
            </if>
        </trim>
    </update>

1.5.4 foreach 语句

    /**查询ID=1,3,4,6,7的数据
     */
    @Test
    public void test6(){
      int [] ids={1,3,4,6,7};
        List<User> list = userMapper.selectByIds(ids);
        for (User user:list) {
            System.out.println(user);
        }
    }
   
    <select id="selectByIds" resultType="User">
        select  <include refid="col"></include> from demo_user
        <where>
            id in
            <foreach collection="ids" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
        </where>
    </select>

2. MybatisPlus

2.1 MP介绍

在这里插入图片描述
特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.2 MP入门案例

2.2.1导入jar包

<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.4.3</version>
</dependency>

❌注意:mybatis-plus包含mybatis的功能,因此需要将原来安装的mybatis的jar包删除

2.2.2配置对象关系映射

对象关系映射配置:
1、需要将对象与表名一一对应
2、主键绑定,属性名与字段名绑定

/**
 * 对象关系映射配置:
 * 1、需要将对象与表名--对应
 * 2、主键绑定,属性绑定
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@TableName("demo_user")//对象与表名映射
public class User implements Serializable {

    //主键自增
    @TableId(type=IdType.AUTO)
    private  Integer id;
    /**如果属性与字段同名,注解可以省略*/
    //@TableField("name")
    private  String name;
    // @TableField("age")
    private  Integer age;
    // @TableField("sex")
    private  String sex;
}

2.2.3继承公共API接口

在这里插入图片描述
**注意事项:**继承接口时必须添加泛型对象,否则映射表失败

2.2.4 配置映射yml文件

#springboot整合了MP
mybatis-plus:
  mapper-locations: classpath:/mapper/*.xml
  type-aliases-package: com.jt.pojo
  configuration:
    map-underscore-to-camel-case: true
# 打印sql日志
logging:
  level:
    com.jt.dao: debug

2.2.5 API测试

@SpringBootTest
public class ControllerTest {

    @Autowired
    private UserMapper userMapper;

  /**MP实现插入信息
     */
    @Test
    public void test2(){
            User user=new User();
            user.setId(2).setName("如来佛祖").setAge(200).setSex("男");
        userMapper.insert(user);
    }
}

2.3 MP原理

1、用户调用User插入操作 userMapper.insert(User 对象)
2、接口方法中需要传递泛型对象,可以根据用户配置的注解找到泛型对象
3、根据用户的接口获取Mapper接口的父级接口BaseMapper,根据BaseMapper中的反向获取User.class的类型
4、根据User.class获取@TableName(“demo_user”)从而获取表名,再根据属性注解 @TableField(“name”)从而获取表中的字段
5、根据上述操作,然后动态的拼接SQL语句
6、最后Mybatis执行SQL语句进行数据库操作

2.4 MP用法

2.4.1 MP根据ID查询

  /**MP根据Id查询
     */
    @Test
    public void test3(){
        User user = userMapper.selectById(1);
        System.out.println(user);
    }

2.4.2 根据age=18 sex=“女”

sql:select * from demo_user where age=? and sex=?

 @Test
    public void test4() {
        User user = new User();
        user.setAge(18).setSex("女");
        //构建条件构造器--根据user中不为null的属性拼接成条件,默认都是and
        QueryWrapper queryWrapper = new QueryWrapper(user);
        List<User> list = userMapper.selectList(queryWrapper);
        for (User user1 : list) {
            System.out.println(user1);

        }
    }

2.4.3 gt、eq(age>18 sex=“女”)

sql:select * from demo_user where age>18 and sex='女’

@Test
        public void  test5(){
             //queryWrapper进行连着加'.'时,需要为添加泛型 QueryWrapper<User>
             QueryWrapper<User> queryWrapper=new QueryWrapper();
             queryWrapper.gt("age",18)
                          .eq("sex","女");
           List<User> list = userMapper.selectList(queryWrapper);
           for (User user1 : list) {
               System.out.println(user1);

           }
       }

2.4.4 like、likeLeft、likeRight(用模糊查询: 查询name包含"君"的数据)

sql :select * from demo_user where name like '%君%'

@Test
       public void test6(){
           QueryWrapper<User> queryWrapper=new QueryWrapper();
           queryWrapper.like("name", "君");
           List<User> list = userMapper.selectList(queryWrapper);
           for (User user1 : list) {
               System.out.println(user1);
           }
       }

注意:queryWrapper.likeLeft() / queryWrapper.likeRight() 指的是%所在的位置

sql: select * from demo_user where name like '君%'

//此处的left和right指的是%的位置
       @Test
       public void test7(){
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.likeLeft("name", "君");
           List<User> list = userMapper.selectList(queryWrapper);
           for (User user1 : list) {
               System.out.println(user1);
           }
       }

2.4.5 notLike(查询名字中不包含“君”子的信息)

sql:select * from demo_user where name not like '%君%'

@Test//查询名字中不包含“君”子的信息
        public void test8(){
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.notLike("name", "君");
           List<User> list = userMapper.selectList(queryWrapper);
           for (User user1 : list) {
               System.out.println(user1);
           }
       }

2.4.6 orderByDesc(查询age>18 (按照年龄降序排序),如果年龄相同,按照性别排序)

sql:select * from demo_user order by age,sex

@Test
       public void test9(){
        QueryWrapper<User> queryWrapper=new QueryWrapper();
           queryWrapper.gt("age", 18)
                   .orderByDesc("age","sex");
           List<User> list = userMapper.selectList(queryWrapper);
           for (User user1 : list) {
               System.out.println(user1);
           }
       }

2.4.7 in(查询id in 1,3,5,7;)

拓展:in 和 or:
* 在单表中查询 in与or差不多
* 在多表查询中 or的效率更高
sql:select * from demo_user where id in (1,3,5,7)

@Test
    public void test10(){
        //1、条件构造器
        QueryWrapper<User> queryWrapper=new QueryWrapper();
        queryWrapper.in("id", 1,3,5,7);
        List<User> list = userMapper.selectList(queryWrapper);
        for (User user1 : list) {
            System.out.println(user1);
        }

        //2、Mp的特殊方法:尽可能使用对象类型(对象类型中含有方法)
        //int[]ids={1,2,3,4,5,6};会报错,因为基本类型中不含方法
        Integer [] ids=new Integer[]{1,2,3,4,5,6};
        List idList= Arrays.asList(ids);//数组转集合
        List<User> list1 = userMapper.selectBatchIds(idList);
        for (User user1 : list1) {
            System.out.println(user1);
        }
    }

2.4.8 StringUtils.hasLength() 、eq(condition,column,val)

高级用法:根据name和age动态查询数据
sql:

      select <include refid="col"/> from demo_user
        <where>
            <if test="name!=null">
                name=#{name}
            </if>

            <if test="age!=null">
               and age=#{age}
            </if>
        </where>
      ````

Condition 判断:当字符串不为空且长度大于0时,会拼接where条件,否则不拼接


```java
@Test
    public void test11(){
        String name=null;
        String sex="女";
        QueryWrapper<User> queryWrapper=new QueryWrapper();
        //判断是否有值
        Boolean nameFlag=StringUtils.hasLength(name);
        Boolean sexFlag=StringUtils.hasLength(sex);
        queryWrapper.eq(nameFlag,"name", name)
                .eq(sexFlag, "sex", sex);
        List<User> list1 = userMapper.selectList(queryWrapper);
        for (User user1 : list1) {
            System.out.println(user1);
        }
    }

分析:当name=null时,此时的sql语句是:select * from demo_user where sex=?
name条件被省略;

2.4.8 deleteById(Integer x)

/**删除ID=x的语句*/
    @Test
    public void test12(){
        Integer i = userMapper.deleteById(234);
        if(i!=null)
        {
            System.out.println("删除成功!");
        }
    }

2.4.9 deleteBatchIds(Collection x)

/**删除id in(x,x,x,....)*/
       @Test
       public void test13(){
        Integer [] ids=new Integer[]{50,51,52,53};
        List<Integer> list = Arrays.asList(ids);//数组转集合
        Integer i=userMapper.deleteBatchIds(list);
        if(i!=null)
        {
            System.out.println("删除成功!");
        }
    }

2.4.10 删除 name=** and age=**

/**删除name=”小法“ and age=20 的信息
     */
    @Test
    public void test14(){
        QueryWrapper<User> queryWrapper=new QueryWrapper();
        queryWrapper.eq("name", "小法")
                .eq("age", 20);
        Integer i = userMapper.delete(queryWrapper);
        if(i!=null)
        {
            System.out.println("删除成功!");
        }
    }

2.4.11 修改信息,name=,age=

/**修改 name=”猪八戒“的信息,将name改为”祝君好运“,age=100
     */
    @Test
    public void test15(){
        QueryWrapper<User> queryWrapper=new QueryWrapper();
        User user=new User();
        user.setName("祝君好运").setAge(100);
        queryWrapper.eq("name", "猪八戒");
        Integer i = userMapper.update(user, queryWrapper);
        if(i!=null)
        {
            System.out.println("更改成功!");
        }
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值